汇编学习--第十一天

3.数值显示

实际上,方法就是,数值除10,取余数,就得到数值的每一位,再观察得到,数字xH(x=0,1...9)对应,十进制数字30H+xH

assume cs:code
data segment
    dw 123,12666,1,8,3,38
data ends
code segment
start:    mov ax,data
        mov ds,ax
        mov ax,2000h
        mov es,ax
        
        mov si,0;表示数据段中的偏移地址
        mov di,0;将16进制数存储为10进制字符的偏移地址
        mov cx,6
        
        ;循环取出数据段中的数据
s:        mov ax,ds:[si]
        call show_str
        add si,2
        loop s
        
        mov ax,4c00h
        int 21h
        
show_str:    push cx
            mov bp,0;bp记录入栈次数
            
            ;方法:将该数除以10,得到的余数就是该数的一位数
            ;注意,我们判断数字转换结束的条件是商为0,但是loop是先减cx,再判断,所以需要inc cx
            ;处理一个16进制数,将每一位转换为10进制字符,压入栈中
            ;压栈原因:因为得到的数据是逆序的,所以需要入栈,再出栈,得到顺序的数
s0:            mov dx,0
            mov bx,10
            div bx
            mov cx,ax
            inc cx
            add dx,30h;数字转字符
            push dx;转换的数据入栈
            inc bp
            loop s0
            
            ;将栈中的数据取出,存储到指定位置
            mov cx,bp
            mov bx,0
store_str:    pop dx
            mov byte ptr es:[di],dl
            inc di
            loop store_str

            pop cx
            inc di;这里di表示每个10进制字符之间有个间隙,方便查看
            ret
            
code ends
end start

 

让显示这些数值,实际上就是上个程序,储存位置变成了显示缓冲区

assume cs:code
data segment
    dw 123,12666,1,8,3,38
data ends
code segment
start:    mov ax,data
        mov ds,ax
        mov ax,0b800h
        mov es,ax
        
        mov si,0;表示数据段中的偏移地址
        mov di,0;将16进制数存储为10进制字符的偏移地址
        mov cx,6
        
        ;循环取出数据段中的数据
s:        mov ax,ds:[si]
        call show_str
        add si,2
        loop s
        
        mov ax,4c00h
        int 21h
        
show_str:    push cx
            mov bp,0
            
            ;方法:将该数除以10,得到的余数就是该数的一位数
            ;注意,我们判断数字转换结束的条件是商为0,但是loop是先减cx,再判断,所以需要inc cx
            ;处理一个16进制数,将每一位转换为10进制字符,压入栈中
            ;压栈原因:因为得到的数据是逆序的,所以需要入栈,再出栈,得到顺序的数
s0:            mov dx,0
            mov bx,10
            div bx
            mov cx,ax
            inc cx
            add dx,30h;数字转字符
            push dx;转换的数据入栈
            inc bp
            loop s0
            
            ;将栈中的数据取出,存储到显示缓冲区
            mov cx,bp
            mov bx,0
store_str:    pop dx
            mov byte ptr es:[di+500h+4],dl;低位数据,500h表示显示器第8行,4表示第3列
            mov byte ptr es:[di+500h+4+1],2;高位属性,2就是00000010,绿色
            add di,2
            loop store_str

            pop cx
            add di,2;方便查看
            ret
            
code ends
end start

 

这个程序中,s0部分对应着dtoc子程序(十六进制转换为十进制字符),show_str子程序对应着store_str部分

 

课程设计 1

程序主要由三部分构成主程序,两个子程序。

两个子程序包含字符输出,存储的子程序和dword除法

第一个子程序功能:

  1. 将寄存器中的16进制数字转换为10进制字符数字(这里实际上就是调用第二个子程序,获得数据每一位的值),压入栈中
  2. 将栈中的字符数字依次出栈,存入指定位置的显示缓冲区

 

第二个子程序功能:(来自:2.解决除法溢出

  • 计算dword型数据除10的结果,余数就是数据的每一位

 

主程序流程:(整体框架来自:实验 7)

  1. 获取数据段数据,保存到指定寄存器,利用第一个子程序功能存入显示缓存区。
  2. 平均工资,先获取数据段中的总工资和人数,计算出平均工资,并存入指定寄存区,最后调用第一个子程序存入显示缓冲区。

 

  1 assume cs:code,ds:data,es:table
  2 
  3 data segment
  4 db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
  5 db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
  6 db '1993','1994','1995'
  7 ;以上是表示21年的字符串 4 * 21 = 84
  8 
  9 dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
 10 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
 11 ;以上是表示21年公司总收入的dword型数据 4 * 21 = 84
 12 
 13 dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
 14 dw 11542,14430,15257,17800
 15 ;以上是表示21年公司雇员人数的21个word型数据 2 * 21 = 42
 16 data ends
 17 
 18 table segment
 19 db 21 dup ('year summ ne ?? ') ; 'year summ ne ?? ' 刚好16个字节
 20 table ends
 21 
 22 stack segment
 23     dw 8 dup (0)
 24 stack ends
 25 
 26 code segment
 27 start:        mov ax,data
 28             mov ds,ax
 29             mov ax,0b800h
 30             mov es,ax
 31             mov ax,stack
 32             mov ss,ax
 33             mov sp,16
 34         
 35             mov cx,21    ;外层循环每一年的情况
 36             mov bx,0a0h    ;表示第几年的情况
 37             mov di,0    ;存储年份地址
 38         
 39             mov bp,0    ;1.获取到data段中雇员数数据 2.保存bx的值
 40 s0:    push cx    
 41         mov cx,4
 42         mov si,0    ;表示这一年中的第几个
 43         
 44         ;年份
 45 s:      mov al,ds:[di];一位一位保存字符
 46         mov es:[bx+si],al
 47         mov byte ptr es:[bx+si+1],2
 48         
 49         add si,2
 50         inc di
 51         loop s
 52         add si,2
 53       
 54        ;收入
 55        mov dx,ds:[di+52h]
 56        mov ax,ds:[di+50h]
 57        mov si,24;指定列的位置,13列
 58        call show_str
 59         
 60         ;雇员数
 61         mov ax,ds:[bp+0a8h]
 62         mov dx,0
 63         mov si,44;指定列的位置,23列
 64         call show_str
 65         
 66         ;人均收入
 67         mov dx,ds:[di+52h]
 68         mov ax,ds:[di+50h]
 69         push bx
 70         mov bx,ds:[bp+0a8h]
 71         div bx
 72         mov dx,0
 73         pop bx;顺序不能变
 74         mov si,64;指定列的位置,33列
 75         call show_str
 76         
 77         pop cx
 78         add bp,2
 79         add bx,0a0h
 80         loop s0
 81         
 82         mov ax,4c00h
 83         int 21h
 84 
 85 ;调用divdw子程序(除10),获取余数(数据段数据的16进制形式)
 86 ;将余数转换为10进制字符,入栈
 87 ;循环上面操 88 ;判断结束条件:因为被除数为dword形式,需要先判断dx(高16位)是否为0,再判断ax(低16位)是否0
 89 show_str:push bp
 90         push bx
 91         
 92             mov bp,0
 93 
 94 s1:         
 95         mov cx,0ah
 96         call divdw
 97         add cx,30h;数字转字符
 98         push cx;转换的数据入栈
 99         mov cx,dx
100         inc cx
101         inc bp
102         loop s1
103             
104         mov cx,ax
105         inc cx
106         loop s1
107             
108         ;获取表示行的数值bx,在栈中的位置的偏移地址
109         mov cx,bp;在bx上入了多少次栈
110         mov bx,sp;现在的栈顶
111 s3:    add bx,2;找到bx的位置
112         loop s3
113         mov cx,bp
114             
115        mov bx,ss:[bx]
116 store_str:    
117             pop dx
118             mov byte ptr es:[bx+si],dl;低位数据,500h表示显示器第8行,4表示第3列
119             mov byte ptr es:[bx+si+1],2;高位属性,2就是00000010,绿色
120             add si,2
121             loop store_str
122         
123             pop bx
124             pop bp
125             add si,2
126             ret
127             
128 divdw: push ax
129           ;高16位计算
130           mov ax, dx
131           mov dx, 0 
132           div cx
133           mov bx, ax
134           ;低16位计算
135           pop ax
136           div cx
137          ;低16位
138           mov cx, dx
139           ;余数
140           mov dx, bx 
141           ret
142 code ends
143 end start

 

posted @ 2019-07-15 01:13  Hk_Mayfly  阅读(345)  评论(0编辑  收藏  举报