《汇编语言第三版》王爽学习历程——实验10(3)
程序员文章站
2024-03-24 08:45:46
...
编写子程序——数值显示
新人自己分析的,希望大神给予意见~!
问题描述:
将数值显示到屏幕上
子程序描述
名称:dtoc
功能:将word型数据转变为表示十进制数的字符串,字符串以0结尾
参数:(ax)=word数据, ds:si指向字符串的首地址
返回:无
分析
个人认为这个子程序还是蛮简单的。
1、并不是内存中存的多少,在屏幕上就能显示多少,因为显卡遵循ASCII码,除非存的数正好和该数的编码是一样的,那么就比较好了,不过事实并不是这样。
由书中提示可以知道,十进制数码字符对应的ASCII码 = 十进制数码+30H。
2、既然是一个一个显示,那就必须要把一个多位数拆成一个一个的数,书中也给出了方法,除10取余,只不过除完后必须逆序存入数据段,如:12666,拆完后是66621,。讲到逆序,就很容易想到用栈了。
汇编代码:
assume cs:codesg
datasg segment
db 16 dup(0)
datasg ends
stacksg segment
db 64 dup(0)
datasg ends
codesg segment
start:
mov ax, stacksg
mov ss, ax
mov sp, 40h ;初始化栈
mov ax, datasg
mov ds, datasg
mov si, 0 ;初始化数据段
mov ax, 12666
call dtoc
mov dh, 1
mov dl, 3
mov cl, 2
call show_str
mov 4c00h
int 21h
dtoc:
push ax
push bx ;用来存放除数0AH
push cx ;用来判断是否除完
push dx ;用32位除法,用来保存余数
push si ;数据段偏移地址
push di ;计算数的位数
mov cx, 0
mov dx, 0
mov di, 0
mov bx, 0ah ;寄存器的初始化
s0: ;开始短除法取余数并入栈
div bx
mov cx, ax
push dx ;余数入栈
mov dx, 0 ;重置被除数高位
inc di
jcxz ok ;若商为0,则取余数已经完成
jmp short s0
ok: ;完成取余后,需要入数据段
mov cx, di ;出栈次数
s1:
pop ax
add ax, 30h ;对应ascii字符码
mov ds:[si], al ;逆序入数据段
inc si
loop s1
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
show_str:
push es ;把子程序中用到的寄存器入栈保存原有数据
push ax
push bx
push dx
push cx ;保存字符属性
push di
push si
mov ax, 0b800h
mov es, ax ;初始化显示缓冲区
mov al, 0a0h ;进行行的计算,来确定行的偏移地址
sub dh, 1
mul dh
mov bx, ax ;行计算完毕
mov al, 2 ;进行列的计算,来确定列的偏移地址
sub dl, 1
mul dl
mov di, ax ;列计算完毕
mov al, cl
mov cx, 0 ;重置一下寄存器,以后需要用它判断是否结束
s_str:
mov cl, ds:[si]
jcxz ok_str ;判断如果字符读取完了就可以跳出循环了
mov es:[bx][di], cl ;字符送入完毕
mov ex:[bx][di+1], al ;字符属性送入
inc si
add di, 2
jmp shrot s_str ;字符的循环复制
ok_str:
pop si ;相关寄存器出栈保持调用者原有寄存器数据不变
pop di
pop cx
pop dx
pop bx
pop ax
pop es
ret
codesg ends
end start
数值:12666, 在1行3列以绿色字显示:
数值:17573, 在10行7列以7号字体显示:
没有清屏是因为需要一个参照物来比较是否在N行M列显示。
上一篇: 你真的理解HelloWorld吗
下一篇: APP自动化测试(二)-appium