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除法
第一个子程序功能:
- 将寄存器中的16进制数字转换为10进制字符数字(这里实际上就是调用第二个子程序,获得数据每一位的值),压入栈中
- 将栈中的字符数字依次出栈,存入指定位置的显示缓冲区
第二个子程序功能:(来自:2.解决除法溢出)
- 计算dword型数据除10的结果,余数就是数据的每一位
主程序流程:(整体框架来自:实验 7)
- 获取数据段数据,保存到指定寄存器,利用第一个子程序功能存入显示缓存区。
- 平均工资,先获取数据段中的总工资和人数,计算出平均工资,并存入指定寄存区,最后调用第一个子程序存入显示缓冲区。
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