我尽量使每个程序都有富于趣味性的输出,不知大家对这个程序的输出结果是否有兴趣。这个程序给我们提出了两个问题:第一,为什么这一串文字是倾斜的?第二,为什么paradise一词中第二个字母a 是一个蓝方块?
答案十分简单:首先指令stosw可以让DI寄存器自动加2,因此当我们给DI加上80的时候,DI寄存器的实际增量是82,所以DI指向了下一行的下一列。大家可以修改程序给DI加上78,想想输出结果会是什么样子,然后运行程序看看实际输出和想象中是否一致。至于那个字母"a"的去向就更不用多说,我们每显示一个字符就将属性值加1,显示字符"a"时属性值恰好是11H,所以字符"a"和背影融为一体了。
这个程序十分简单,不过它很形象地说明了每个字符行与显示缓存中的80个字节的对应关系。下面这个程序稍微复杂一些,其中的子过程outchar可以接收字符的行号与列号,由它自行算出偏移量。
data segment
assume ds:data ;定义一个字符串
msg db 'Enter into the paradise.',0 ;保存当前的显示模式
mode db ?
data ends
code segment
assume cs:code
main proc far
mov ax,data ;初始化DS寄存器
mov ds,ax
mov ah,0fh ;取得当前的显示模式
int 10h
mov mode,al ;保存当前的显示模式
mov ax,0001h ;设置新的显示模式为01H
int 10h
mov dx,0 ;设置第一个字符的起始位置
mov cx,2 ;每次显示2个字符
mov ah,1 ;设置第第一个字符的属性
mov si,offset msg ;SI寄存器指向字符串MSG
dispmsg:
lodsb ;取得一个字符
or al,al ;已经到字符串结尾了吗?
jz exit ;已到结尾,转EXIT结束
call outchar ;显示AX寄存器中的字符及属性
inc ah ;属性字节加1
inc dh ;下一个字符的行、列号加1
inc dl
jmp dispmsg ;显示下一个字符
exit: mov ah,0 ;等待键盘输入
int 16h
mov ah,0 ;恢复显示模式
mov al,mode
int 10h
mov ah,4ch ;结束进程
int 21h
main endp
outchar proc near ;OUTCHAR子过程
push es ;保存将要使用的寄存器
push di
push bx
push cx
push dx
push ax
mov ax,0b800h ;设置ES寄存器指向显示缓冲区
mov es,ax
mov al,dh ;字符所在行号送入AL寄存器
mov bh,80
mul bh ;计算"行号 80"
mov di,ax ;"行号 80"的结果送入DI寄存器
shl dl,1 ;计算"列号 2"
mov dh,0
add di,dx ;偏移量=行号 80+列号 2
pop ax ;从堆栈中取出字符及属性
rep stosw ;送入显示缓冲区
pop dx ;恢复寄存器
pop cx
pop bx
pop di
pop es
ret ;返回
outchar endp
code ends
end main
助记符:MUL(Multiple)
用 途:将两个数相乘
格 式:MUL 寄存器
MUL 存储单元
执 行:指定寄存器或存储单元中的数据与累加器中的数据相乘,16位的结果
保存在累加器AX中,32位的结果由DX寄存器与AX共同保存,AX保存结
果的低16位,DX保存高16位。