在本次实验中,通过编写3个子程序来认识几个常见的问题和掌握解决这些问题的方法。
1. 显示字符串
问题
编写一个通用的显示字符串的子程序,提供显示的位置(行、列)、内容和颜色的接口。
应用举例:在屏幕的8行3列,用绿色显示data段中的字符串。
assume cs:code
data segment
db 'Welcome to masm!',0
data ends
code segment
start:
mov dh,8
mov dl,2
mov cl,2
mov ax,data
mov ds,ax
mov si,0
call show_str
mov ax,4c00h
int 21h
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串
;参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),
; (cl)=颜色,ds:si指向字符串的首地址
;返回:无
show_str:
push ax
push bx
push cx
push di
mov ax,0b800h ;使es指向显示缓冲区的起始段地址
mov es,ax
sub ax,ax ;使di指向指定列
mov al,2
mul dl
mov di,ax
mov al,0a0h ;使bx指向指定行
mul dh
mov bx,ax
mov dl,cl
sub cx,cx
show_str_change:
mov cl,ds:[si]
jcxz show_str_ok
mov es:[bx+di],cl
mov es:[bx+di+1],dl
inc si
add di,2
jmp show_str_change
show_str_ok:
pop di
pop cx
pop bx
pop ax
ret
code ends
end start
2. 解决除法溢出的问题
问题
使用div指令做除法运算时,如果结果的商大于al或ax所能存储的最大值,将会发生除法溢出错误。编写一个名为divdw的子程序来解决该问题。
子程序描述
名称:divdw
功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。
参数:(ax)=dword型数据的低16位
(dx)=dword型数据的高16位
(cx)=除数
返回:(dx)=结果的高16位,(ax)=结果的低16位
(cx)=余数
应用举例:计算1000000/10(F4240H/0AH)
assume cs:code
code segment
start:
mov ax,4240h
mov dx,0fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位
; (cx)=余数
divdw:
push bx
push ax
mov ax,dx
mov dx,0
div cx
mov bx,ax
pop ax
div cx
mov cx,dx
mov dx,bx
pop bx
ret
code ends
end start
3. 数值显示
问题
编程,将data段中的数据以十进制的形式显示出来。
子程序描述
名称:dtoc
功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
参数:(ax)=word型数据
ds:si指向字符串的首地址
返回:无
应用举例
编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。在显示时调用本次实验中的第一个子程序show_str。
assume cs:code
data segment
db 10 dup (0)
data ends
code segment
start:
mov ax,12666
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
dtoc:
push bx
push cx
push si
mov di,0 ;记录字串的长度
mov cx,0
dtoc_change:
mov bx,10
div bx
push dx
inc di
mov cx,ax
jcxz dtoc_write
mov dx,0
jmp dtoc_change
dtoc_write:
mov cx,di
dtoc_write_s0:
pop ax
add ax,30h
mov ds:[si],ax
inc si
loop dtoc_write_s0
dtoc_end:
pop si
pop cx
pop bx
ret
show_str:
push ax
push bx
push cx
push di
mov ax,0b800h ;使es指向显示缓冲区的起始段地址
mov es,ax
sub ax,ax ;使di指向指定列
mov al,2
mul dl
mov di,ax
mov al,0a0h ;使bx指向指定行
mul dh
mov bx,ax
mov dl,cl
sub cx,cx
show_str_change:
mov cl,ds:[si]
jcxz show_str_ok
mov es:[bx+di],cl
mov es:[bx+di+1],dl
inc si
add di,2
jmp show_str_change
show_str_ok:
pop di
pop cx
pop bx
pop ax
ret
code ends
end start