实验10 编写子程序- 第三小题 (材料详见书上209页)
题目描述:
3.数值显示:将二进制数据用十进制显示到屏幕
子程序描述:
名称:dtoc
功能:将word型数据转变为表示十进制的字符串,字符串以0结尾。
参数:(ax)=word型数据
ds:si指向字符串的首地址
返回:无
应用举例:编程将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。
12666 = 317AH
10 = 0AH
以下是我解答的完整的代码:
:>----------------------------------------------------------------------------------------
assume cs:codesg, ds:datasg, ss:stacksg
datasg segment
db 16 dup(0) ;这里用16个字节来保存转换后的每位十进制ASCII码值
datasg ends ;最后一个字节总为0, 用来定位字符末尾的结束符
stacksg segment
dw 0,0,0,0,0,0,0,0
stacksg ends
codesg segment
start: mov ax, 12666
mov bx, datasg
mov ds, bx
mov bx, stacksg
mov ss, bx
mov sp, 10h ;初始化栈
mov si, 0
call dtoc
mov dh, 8
mov dl, 3
mov cl, 2
call show_str
mov ax, 4c00h
int 21H
;(用来转成十进制数对应的ASCII码的子程序)
dtoc: push dx
push cx
push bx ;以上保存子程序中要用到的寄存器
mov si, 0Eh ;初始化si指向datasg段中倒数第二个字节空间
mov bx, 0Ah ;bx保存除数,ax各dx中保存了被除数 10
s1: mov dx, 0
div bx
mov cx, ax ;保存一份ax的值,用cx来检测结果中的商ax是否为0
add dl, 30h ;由于除数是10 所以结果中的余数一定小于10,取dl就行了
mov byte ptr [si], dl ;保存对应的十进制数的ASCII值
jcxz ok1 ;如果除以10的商为0表示处理完了
dec si ;因为要倒序,si从后往前移动
jmp s1
ok1: pop bx
pop cx
pop dx
ret
;(用来在屏幕指定位置显示内容的子程序)
show_str: push es
push ax
push bx ;以上保存子程序中要用到的寄存器
mov ax, 0B800h ;显存首地址
mov es, ax
mov al, 160 ;显存中每行所占的字节数(每行能显示80个字符)
mul dh
mov bx, ax
mov al, 2 ;显存中每个显示字符所占的字节数(显示字符=属性字节+ASCII码)
mul dl
add bx, ax ;此时bx为由参数指定显示位在显存中的首地址
mov ch, 0
mov dl, cl ;因为要用cx来检测是否处理到字符串的结尾0, 先用dl保存参数cl
s0: mov cl, ds:[si] ;取出之前处理好的一个字符
jcxz ok0
mov byte ptr es:[bx], cl ;往显存中存入ASCII码
mov byte ptr es:[bx].1h, dl ;往显存中存入属性字节
inc si ;移动到下一个字符
add bx, 2 ;移动到下一个显存字符空间的首地址
jmp s0
ok0: pop bx
pop ax
pop es
ret
codesg ends
end start
:<----------------------------------------------------------------------------------------
总结:
起初还以为可以用8位的除法,测试后发现有溢出,Debug调试发现用8位除法al(最大值为FFH)保存不了4F2H (1266/10) ,还是得改用16位除数来解决溢出。jcxz指令用来处理不知道具体处理次数是很有用...
------------- 以上的习题部分及代码引用于王爽老师的<<汇编语言>>第二版 ----------------