|
主题 : : 【分享我的实验9】已调试通过,一个循环,带超详细注释、地址算法,带高亮闪烁效果(书上未要求高亮闪烁效果) [待解决] |
回复[ 4次 ]
点击[ 339次 ] | |
|
|
|
|
[帖 主]
[ 发表时间:2011-02-07 19:37 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2011-02-07 19:07 |
d segment
db 'welcome to masm!'
;'welcome to masm!'共有16个字符(不算引号),welcome七个,空格一个,to两个,空格一个,masm!五个
d ends
assume cs:c,ds:d
c segment
k:
mov ax,d
mov ds,ax
;将ds指向d段
mov ax,0b800h
mov es,ax
;将es指向b800h
mov bx,0
mov si,0
mov di,0
;相关寄存器初始化
mov cx,16
;设置循环次数(从标记X处开始到loop x之间的程序将重复执行16次)
x:
mov bx,1824
;将es:[bx][si]指向显存中第一行第一个要写入的数据的地址
;(以后每次循环后将换回第一行并指向后一个的地址)
;1824是怎么算出来的呢
;书上要求在屏幕中间显示字符串,对于80*25模式,显示器可以显示25行(横的)80列(竖的)的共25*80个字符
;因为要显示3行'welcome to masm!'(引号不算,共16个字符)
;那么在分别从第12,13,14行的第33列开始显示,则正好为屏幕中间
;(上空1到11行,下空15到25行,上下都空11行;左空1到32列,从33到48列显示字符,右空49到80列,左右都空32列)
;上空的11行空去了11*80=880个字符,第12行左边还要再空去32列(32个字符),则一共空去了880+32=912个字符
;每个字符占2个字节(ASCII码一个,属性一个),则一共空去了912*2=1824个字节
;因为字符在显存中不分行列(行和列只是对于显示器显示字符的形式)从B800H:0000开始的地址连续存储
;要空去1824个字节也就是要将从B800H:0000到B800H:1823的地址跳过,从B800H:1824的地址开始写入
mov al,[di]
;将ds:[di]所指的字符串(welcome to masm!)中的字符的ASCII码值存进al
;(当前指向第一个字母w的ASCII码值,循环后指针将逐次按单位字节后移)
mov ah,8ah
;将高亮闪烁绿字的属性字节存进ah
mov es:[bx][si],ax
;将高亮闪烁绿字w的ASCII码值和属性字节同时写入显存中的指定位置(循环后将依次写入后面的字符)
add bx,160
;换到下一行
mov ah,0ach
;将绿底高亮闪烁红字的属性字节存进ah
mov es:[bx][si],ax
;将绿底高亮闪烁红字w的ASCII码值和属性字节同时写入显存中的指定位置(同上)
add bx,160
;换到下一行
mov ah,0f9h
;将白底高亮闪烁蓝字的属性字节存进ah
mov es:[bx][si],ax
;将白底高亮闪烁蓝字w的ASCII码值和属性字节同时写入显存中的指定位置(同上)
add si,2
;si后移2字节位置,实现在每次循环后将es:[bx][si]指向显存中每一行后一个要写入的字符的地址
inc di
;di后移1字节位置,实现在每次循环后将ds:[di]指向字符串中后一个字符的ASCII码值
loop x
;跳转到标记x处重复执行
;loop x这条指令将执行16次,每执行一次cx减1,执行第16次的时候cx为0,循环结束
;实现从标记x处开始到loop x之间的程序重复执行16次
mov ax,4c00h
int 21h
;程序返回,貌似是返回到debug(将cpu的控制权交还给使这个实验得以运行的程序debug)
;至于喂神马这两条指令就能实现程序返回,偶也不懂
c ends
end k
;指明程序的入口从标记k处开始(程序加载后将cs:ip指向标记k处的第一条指令的地址) | | |
|
|
|
|
[第1楼]
[ 回复时间:2011-02-07 20:06 ]
[引用]
[回复]
[ top ] | |
荣誉值:93
信誉值:0
注册日期:2010-11-29 14:28 |
|
|
|
|
|
[第2楼]
[ 回复时间:2011-02-07 23:41 ]
[引用]
[回复]
[ top ] | |
荣誉值:268
信誉值:12
注册日期:2010-06-18 22:19 |
|
|
|
|
|
[第3楼]
[ 回复时间:2011-03-08 00:51 ]
[引用]
[回复]
[ top ] | |
荣誉值:6
信誉值:0
注册日期:2009-12-03 21:13 |
assume cs:code,ds:data,ss:stack
data segment
db 'Welcome to masm!'
dw 02h,24h,71h ;三种颜色的代码
data ends
stack segment
dw 8 dup(0)
stack ends
code segment
start:mov ax,data ;设置字符所在为ds段
mov ds,ax
mov ax,stack ;设置载空间
mov ss,ax
mov sp,16
mov ax,0b800h ;设置输出为ES段
mov es,ax
mov bp,1030 ;bp=80*12行+70=1030差不多在中间了
mov si,16 ;设置si为颜色所在内存地址
mov cx,3 ;显示3行所以设外层loop为3
s1:mov di,0
mov bx,0
push cx ;外层loop用来保存cx值
mov cx,16
s:push [bx] ;把ds:0中的字显示到屏幕第12行中间
pop es:[bp+di] ;这里用di来每显一个字后向2字节
push [si] ;把颜色输入
pop es:1[bp+di]
inc bx
add di,2 ;这里用di来每显一个字后向2字节
loop s
add si,2 ;换一种颜色
add bp,160 ;屏幕显示换一行
pop cx ;取回外层loop的CX值
loop s1
mov ax,4c00h
int 21h
code ends
end start | | |
|
|
|
|
[第4楼]
[ 回复时间:2011-03-08 23:22 ]
[引用]
[回复]
[ top ] | |
荣誉值:0
信誉值:0
注册日期:2010-12-18 12:40 |
在内循环写完一行后,进行外循环时为什么bx不重新清零啊?我试着把bx清零,程序依然正确运行...这是为什么呢? | | |
|