王爽 汇编语言 第三版 实验10 编写子程序

时间:2020-12-25 20:36:38

1、显示字符串


源代码

assume cs:code
data segment
db 'Welcome to masm!',0
data ends

code segment
start: mov dh,8
mov dl,3
mov cl,2
mov ax,data
mov ds,ax
mov si,0
call show_str

mov ax,4C00H
int 21H

;---------------------------------------------------------
;名称:show_str
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串
;参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),
; (cl)=颜色,ds:si指向字符串的首地址
;返回:无
;---------------------------------------------------------
show_str: ;B800H显示缓冲区的起始地址,关于显示缓冲区的问题可以参考实验9
mov ax,0B800H
mov es,ax

;计算对应行号的起始偏移地址,一行有0A0H个字节(行数 * 0A0H = 偏移地址)
mov al,dh
mov bl,0A0H
mul byte ptr bl
mov bp,ax

;计算对应列号的起始偏移地址,一列有2个字节(列号 * 2 = 偏移地址)
mov ah,0
mov al,dl
add ax,ax
mov di,ax

mov ah,cl ;设置对应的颜色值

;-----------------------------------------------------------------------------------------
;名称:print
;功能:向屏幕输出字符
;参数:(si)=偏移地址(字符串段地址 ds),(bp)=从哪一行的偏移地址开始,(显示缓冲区段地址 es)
; (di)=从哪一列的偏移地址开始,(显示缓冲区段地址 es)
;返回:无
;-----------------------------------------------------------------------------------------
print: ;取得ds段偏移地址为si的字节数据,并保存到 cl 中
mov ch,0
mov cl,ds:[si]

jcxz ok ;如果cx的值为0,是则跳转到 ok 标号
mov al,ds:[si] ;将字节数据保存到 al 中
mov es:[bp+di],ax ;输出到指定的显示缓冲区位置上

;累加操作
add di,2
inc si
jmp short print

ok: ret
code ends
end start

程序运行示例图


王爽 汇编语言 第三版 实验10 编写子程序


2、解决除法溢出的问题


源代码

assume cs:code

code segment
main: mov ax,4240H
mov dx,000FH
mov cx,0AH
call divdw

mov ax,4C00H
int 21h

;------------------------------------------------------------------------------
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型
;参数:(ax)=dword型数据的低16位
; (bx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位
; (ax)=结果的低16位
; (cx)=余数
;------------------------------------------------------------------------------
divdw: push ax ;将低16位保存到栈中
;根据公式:X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N
mov ax,dx ;设置ax为高16位
mov dx,0
call doDiv ;跳转到doDiv执行取得商int()和余数rem()

mov bx,si ;此时的商int()为结果的高16位,先保存到bx寄存器中
pop ax ;从栈中取出低16位设置给ax
mov dx,di ;dx为rem()

call doDiv ;跳转到doDiv执行
mov dx,bx ;设置结果的高16位
mov ax,si ;设置结果的低16位
mov cx,di ;设置余数
ret

;---------------------------------------
;名称:doDiv
;功能:两数相除 取商,取余数
;参数:(ax)=底16位,(dx)=高16位,(cx)=除数
;返回:(si)=商,(di)=余数
;---------------------------------------
doDiv: div word ptr cx
mov si,ax
mov di,dx
ret

code ends

end main


程序运行示例图


call divdw前

王爽 汇编语言 第三版 实验10 编写子程序

call divdw后

王爽 汇编语言 第三版 实验10 编写子程序


3、数值显示


源代码

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
;功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符
;参数:(ax)=word型数据
; di:si指向字符串的首地址
;返回:无
;---------------------------------------------------------------
dtoc: mov cx,ax
;如果cx为0,则表示除到最后了,跳转到ok1
jcxz filling
;循环取余数操作,列如ax=12666,依次拿12666,1266,126,12,1去除以10取得余数
mov dx,0
mov bx,10
div word ptr bx

add dx,30H ;余数需进行+30H操作(十进制数码字符对应的ASCII码 = 十进制数码值 + 30H)
push dx ;将数据放入栈中
inc si
jmp short dtoc

;-------------------------------------
;名称:filling
;功能:向ds段地址(字符串)填充数据
;参数:(si)=数据个数(向栈中取几次数据)
;返回:无
;-------------------------------------
filling: mov cx,si
mov si,0
a: pop ax
mov ds:[si],al
inc si
loop a
mov ds:[si],cl ;保证字符串以0为结尾符
mov si,0 ;修改为0,保证show_str正确执行
ret

;以下代码从第一题复制而来
show_str: mov ax,0B800H
mov es,ax
mov al,dh
mov bl,0A0H
mul byte ptr bl
mov bp,ax
mov ah,0
mov al,dl
add ax,ax
mov di,ax
mov ah,cl
print: mov ch,0
mov cl,ds:[si]
jcxz ok
mov al,ds:[si]
mov es:[bp+di],ax
add di,2
inc si
jmp short print
ok: ret
code ends

end start

程序运行示例图


王爽 汇编语言 第三版 实验10 编写子程序