欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《汇编语言第三版》王爽学习历程——实验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列以绿色字显示:
《汇编语言第三版》王爽学习历程——实验10(3)

数值:17573, 在10行7列以7号字体显示:
《汇编语言第三版》王爽学习历程——实验10(3)

没有清屏是因为需要一个参照物来比较是否在N行M列显示。