课程设计1
将实验7(见原书)中Power idea 公司的数据按照如下格式在屏幕上显示出来。
提示:因为程序要显示的数据有些己经大于65535,应该编写一个新的数据到字符串的转化子程序,完成dword型数据到字符串的转化。说明如下:
名称:dtoc
功能:将dword型数据转变为表示十进制的字符串,字符串以0为结尾符。
参数:(ax)=dword型数据的低16位
(dx)=dword型数据的高16位
ds:si指向字符串的首地址
返回:无
在这个子程序中要注意除法溢出的问题,可以用实验10中设计的子程序divdw来解决。
代码如下:
assume cs:code
data segment
dw 1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514,345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226,11542,14430,15257,17800
dw 5,3,42,104,85,210,123,111,105,125,140,136,153,211,199,209,224,239,260,304,333
db 10,0,0,0,0,10,0,0,0 ;内存数据初始地址 ds:[0d2h]
;内存单元的使用:第一个用作8位除数 第二三个暂存cx 第4.5个存call后的ip 第6.7位做16位除数10 第8.9位暂存si
data ends
stack segment
dw 16 dup(0) ;已开始一位一位放入字符+属性
stack ends
;寄存器使用记录:cs,ip不能动 ds用作 数据段地址 si用作年份、雇员数、工资、内存数据的偏移地址 di用作总收入偏移地址 ss,sp设置栈
; cx 放21次循环,中间可保存再利用 es:bp显存
;所有寄存器,已使用标记* ax bx cx* dx ds* es* cs* ip* ss* sp* si* di* bp*
;
code segment
start: mov ax,data
mov ds,ax
mov si,0h ;雇员si+7eh 工资si+0a8h 内存数据初始地址 ds:[0d2h]
mov di,2ah ;di表示总收入偏移地址
;设置数据段偏移地址
mov ax,stack
mov ss,ax
mov sp,20h
;设置栈
mov ax,0b800h
mov es,ax
mov bp,0h
;设置显存初始段地址
mov cx,21
s: mov ds:[0d3h],cx ;将循环次数cx存入内存单元,。。。。。。。。。。。。。。。。保存cx,释放cx
mov ax,0ah
push ax ;先入栈0ah作为结束标志
mov ax,ds:[si] ;将月份放入ax中,之后用除法。。。。。。。。。。。锁定ax
s0: div byte ptr ds:[0d2h]
add ah,30h ;数字加30h变为对应字符
mov cl,al
mov ch,0 ;商暂存到cx中......................锁定cx
mov al,ah ;放到低位
mov ah,2h ;高位存放颜色属性 黑底绿字
push ax ;入栈一个年份的一个字符
jcxz ok
mov ax,cx ;将商再存入ax......................释放cx
jmp short s0 ;循环得把每一位入栈
ok: ;........................。。。。。。。。。。。。。。。。。。。。释放ax
s1: pop ax
mov cx,0ah
sub cx,ax
jcxz ok2
mov es:[bp],ax
add bp,2
jmp short s1 ;将字符放入显存, 完成一个年份的显示
ok2:mov ax,ds:[di]
mov dx,ds:[di+2] ;ax,dx被除数,。。。。。。。。。。。。锁定ax,dx
call dtoc
;。。。。。。。。。。。。。。。。。。释放ax,dx
mov bp,40
s3: pop ax
mov cx,0ah
sub cx,ax
jcxz oks
mov ah,2h
mov es:[bp],ax
add bp,2
jmp short s3 ;将字符放入显存, 完成一个总收入的显示
oks: mov dx,0
mov ax,ds:[si+7eh] ;将雇员数放入ax中,之后用除法。。。。。。。。。。。锁定ax
call dtoc
;........................。。。。。。。。。。。。。。。。。。。。释放ax
mov bp,80 ;改变显存行偏移地址
s6: pop ax
mov cx,0ah
sub cx,ax
jcxz ok_s6
mov ah,2h
mov es:[bp],ax
add bp,2
jmp short s6 ;将字符放入显存, 完成一个雇员数的显示
ok_s6: mov ax,0ah
push ax ;先入栈0ah作为结束标志
mov ax,ds:[si+0a8h] ;将工资放入ax中,之后用除法。。。。。。。。。。。锁定ax
s7: div byte ptr ds:[0d2h]
add ah,30h ;数字加30h变为对应字符
mov cl,al
mov ch,0 ;商暂存到cx中......................锁定cx
mov al,ah ;放到低位
mov ah,2h ;高位存放颜色属性 黑底绿字
push ax ;入栈一个工资的一个字符
jcxz ok_s7
mov ax,cx ;将商再存入ax......................释放cx
jmp short s7 ;循环得把每一位入栈
ok_s7: ;........................。。。。。。。。。。。。。。。。。。。。释放ax
mov bp,120 ;改变显存行偏移地址
s8: pop ax
mov cx,0ah
sub cx,ax
jcxz ok_s8
mov es:[bp],ax
add bp,2
jmp short s8 ;将字符放入显存, 完成一个雇员数的显示
ok_s8: mov ax,es
add ax,0ah
mov es,ax ;显存下一行
mov bp,0 ;重置显存行偏移地址
add si,2 ;下一组年份、雇员、工资
add di,4 ;下一组总收入
mov cx,ds:[0d3h] ;.................。。。。。。。。。。。。。。。。恢复cx
sub cx,1
jcxz wan
jmp near ptr s
wan:mov ax,4c00h
int 21h
dtoc: mov ds:[0d9h],si ;暂存si。。。。。。。。。。。。暂时释放si
pop ds:[0d5h] ;出栈ip到内存单元,防止取不出来
mov si,0ah
push si ;入栈0a0h作为一个数据结束标志
s4: push ax ;保存被除数低16位
mov ax,dx
mov dx,0h
div word ptr ds:[0d7h] ;高16位先除
mov si,ax ;高16位先除的商放在si,商还在dx中,当做低16位除的高16位
pop ax ;恢复低16位到ax中
div word ptr ds:[0d7h]
add dx,30h
push dx ;最终商的余数入栈
mov dx,si ;高16位先除的商也是最终商的高16位,最终商的低16为就在ax中
mov cx,ax
jcxz s88 ;判断低16位是否为0,为0则继续判断高16位,否则执行下一句,继续循环
jmp near ptr s4
s88: mov cx,dx
jcxz ok_dtoc ;高16位也为0则结束一个数字,否则执行下一句,继续循环
jmp near ptr s4
ok_dtoc:mov si,ds:[0d9h] ;。。。。。。。。。。。。。。。。。恢复si
push ds:[0d5h] ;从内存单元找到ip,并跳转
ret
code ends
end start
代码结果图: