; 子程序:dtoc
; 功能:将word型数据转变成表示十进制的字符串,字符串以0结尾
; 参数:(ax) = word 型数据
; ds:si 指向字符串首地址
; 返回:无
; 应用举例,将12666以10进制的形式显示在屏幕的8行3列,用绿色显示出来,显示用到第一个子程序show_str
assume cs:code
data segment
db 10 dup(0)
data ends
stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 16
mov dx, 0c1h
mov ax, 76f3h
mov si, 0
call dwtoc
mov dh, 8
mov dl, 3
mov cl, 2
call show_str
mov ah, 01h
int 21h
mov ax, 4c00h
int 21h
; 子程序:dwtoc
; 功能:将dword型数据转变成表示十进制的字符串,字符串以0结尾
; 参数:(ax) = dword 型数据的低16位
; (dx) = dword型数据的高16位
; ds:si 指向字符串首地址
; 返回:无
dwtoc:
mov cx, 0
push cx
s_dwtoc:
mov cx, 10 ; 除数
call divdw ; 余数在cx中
add cx, 30h
push cx ; 保存余数的ASCII形式
; 判断是否商为0,如果高低16位都为0,则返回
mov cx, dx
jcxz ok_dxz;
; 高位不为0,则直接跳回,继续执行运算
jmp short s_dwtoc
; 商的高位为0
ok_dxz:
mov cx, ax
jcxz ok_axz
jmp short s_dwtoc
; 商的低位为0
ok_axz:
; 赋值到 ds:[si]
mov dx, si ; 保存si,si为字符串的首地址
loop_dtoc:
pop cx
mov ds:[si], cl
jcxz end_dwtoc
inc si
jmp short loop_dtoc
mov si, dx
end_dwtoc:
mov si, dx
ret
dtoc:
; 先把一个0放进堆栈,在后面s2从堆栈中取出的时候,可以根据cx为0跳转
mov cx, 0
push cx
s1_dtoc:
mov dx, 0
mov cx, 10
div cx
mov cx, dx ; dx余数
add cx, 30h
push cx ; 保存在堆栈
mov cx, ax ; ax为商,当商为0的时候,各位的值就已经得到了,就可以跳出循环
jcxz ok1_dtoc
jmp short s1_dtoc
ok1_dtoc:
mov ch, 0
s2_dtoc:
; 从堆栈中取出
pop cx
jcxz ok2_dtoc
mov ds:[si], cl
inc si
jmp short s2_dtoc
ok2_dtoc:
ret
show_str:
push ax
push bx
push cx
push dx
push es
push si
; 计算好字串开始显示的地址Y = 160*(行数-1) + 列数*2-2, B800 : Y
; 循环将参数里的字串写进显卡内存,并检测到0就返回
; bx = 160*(行数-1)
mov bh, dh
sub bh, 1
mov al, 160
mul bh
mov si, ax ; si 为根据行数算出来的偏移值
; ax = 列数*2-2
mov bl, dl
mov al, 2
mul bl
sub ax, 2 ; 根据列数算出来的偏移值
add si, ax ; 行数和列数的和存在SI中了
mov ax, 0b800h
mov es, ax
mov bx, si ; 将si 的值保存在bx中,bx为显存显示偏移值
mov si, 0 ; 题目要求。。。
mov dl, cl ; 保存字体颜色属性
mov ch, 0
s:
mov cl, ds:[si]
mov es:[bx], cl
jcxz ok
mov es:[bx+1], dl
inc si
add bx, 2
jmp short s
ok:
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
; 子程序:divdw
; 要求:进行不会除法溢出的除法运算,被除数为dword,除数为word,结果为dword
; 参数:(ax) = 被除数dword型的低16位
; (dx) = 被除数dword型的高16位
; (cx) = 除数
;
; 返回:(dx) = 结果的高16位
; (ax) = 结果的低16位
; (cx) = 余数
divdw:
mov bx, ax ; 缓存ax——被除数的低16位
mov ax, dx ; ax = H, 被除数的高16位
mov dx, 0
div cx ; ax 为商,dx为余数 = rem(H/N) * 65536
push ax ; 结果的商,也就是最后要放在dx中的
mov ax, bx ; dx为 rem(H/N) * 65536, 为高16位,ax为低16位,再进行一次除法运算
div cx ; ax 为商——最后结果的低16位,dx为余数——为最后结果,应赋给cx
mov cx, dx
pop dx
ret
code ends
end start