我尽量使每个程序都有富于趣味性的输出,不知大家对这个程序的输出结果是否有兴趣。这个程序给我们提出了两个问题:第一,为什么这一串文字是倾斜的?第二,为什么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位。