任务:按照书中图片格式,打印一坨数据
注:dtoc_1子程序较实验十中dtoc有如下不同:1.操作数据范围由0-ffffH变为0-ffffffffH;2.向ds:si指向的字符串写入数据后不会添加数字0(方便后面)
代码如下:
assume cs:codesg
datasg segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985'
db '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
dd 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
dw 11542,14430,15257,17800
datasg ends ;di->年份和收入 bx->雇员
string segment
db ' ',0 ;占位32B(16字)
string ends
stacksg segment
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0 ;栈空间:0-1fH
stacksg ends
codesg segment
start:
mov ax,stacksg
mov ss,ax
mov sp,20H ;初始化栈空间
mov ax,datasg
mov es,ax
xor di,di
xor bx,bx ;es->操作数据:di->年份和收入,bx->雇员
;年份+0,收入+54H,雇员+0a8H
mov ax,string
mov ds,ax
xor si,si ;ds:si->string
mov cx,21 ;打印21年信息
mov dx,0312H;设置打印位置
s: push cx ;保存程序计数,下面需要cx寄存器
push dx ;保存打印位置,下面需要dx寄存器
mov cx,40 ;清空string:防止这公司哪年赔大了哈哈
s5: mov byte ptr ds:[si],' '
add si,1
loop s5
xor si,si
mov ax,es:[di+0]
mov dx,es:[di+2]
mov ds:[si+0],ax
mov ds:[si+2],dx
add si,8 ;写入年份信息并将si->下一位置
mov ax,es:[di+54H]
mov dx,es:[di+56H] ;(dx)(ax)=收入
push ax
push dx ;保存收入信息,以便计算人均收入
call dtoc_1
add si,8 ;写入收入信息并将si->下一位置
add di,4 ;di->下一年份和收入
xor dx,dx
mov ax,es:[bx+0a8H] ;(dx)(ax)=雇员
push ax ;保存雇员信息,以便计算人均收入
call dtoc_1
add si,8 ;写入雇员信息并将si->下一位置
add bx,2 ;bx->下一雇员
pop cx ;(cx)=雇员
pop dx
pop ax ;(dx)(ax)=收入,!注意高低位字顺序!
call divdw ;当前数据并不会溢出,这里也可以用32位除
call dtoc_1
pop dx ;归还打印位置给dx,为show_str准备参数
mov cx,2 ;设置打印颜色,为show_str准备参数
xor si,si ;将ds:si->string,为show_str准备参数
call show_str
pop cx
inc dh ;下一年信息将打印到下一行
loop s
mov ax,4c00H
int 21H
;ds:si->字符串,(bx)(ax)=操作数据
;寄存器均不会被修改
;与实验10的dtoc不同,dtoc_1的操作数据范围:0-ffffffffH
; 且字符串结尾不再添加数字0
dtoc_1:
push ax
push bx
push dx
push cx
push di ;将用到的寄存器入栈
xor di,di ;di记录转化后字符串长度,方便ok1
s3: mov cx,10
call divdw ;32位除中,商可能溢出,所以用divdw
push cx ;将余数压入栈:若直接写入string段则为逆序
inc di
mov cx,ax
add cx,dx ;检查商((bx)+(ax))是否为0
jcxz ok1
jmp s3
ok1:mov cx,di
xor bx,bx
s4: pop ax
add ax,30H ;将数字(0-9)转化为字符
mov ds:[si+bx],al ;!注意,这里是al而不是ax
inc bx
loop s4
pop di
pop cx
pop dx
pop bx
pop ax ;恢复被修改的寄存器
ret
;ds:si->字符串首地址
;dh行号 dl列号 cl颜色
;寄存器均不会被修改
show_str:
push es
push di
push ax
push bx
push cx
push dx ;将用到的寄存器入栈
mov ax,0b800H
mov es,ax
xor ax,ax
mov al,160
mul dh ;8位乘
xor dh,dh
add dx,dx
add ax,dx
mov di,ax ;es:di->指定显示首地址
mov al,cl ;cl即将被用作判断
xor bx,bx
s0: mov cl,ds:[si+bx]
jcxz ok0 ;若(cx)=0退出循环
mov es:[di+0],cl ;写入要打印的字符
mov es:[di+1],al ;写入要打印字符的颜色
inc bx
add di,2
jmp s0
ok0:pop dx
pop cx
pop bx
pop ax
pop di
pop es ;恢复被修改的寄存器
ret
;(dx)=H,(ax)=L,(cx)=N
;(dx)(ax)/(cx)=(dx)(ax)
;(dx)(ax)%(cx)=(cx)
;除返回所用寄存器外,其他均不会被修改
divdw:
push bx ;将用到的寄存器入栈
mov bx,ax ;(bx)=被除数低16位
mov ax,dx
xor dx,dx ;(dx)(ax)=H
div cx ;32位除,(ax)=H/N,(dx)=H%N
push ax ;压入H/N
mov ax,bx ;(dx)(ax)=H%N*65536+L
div cx ;(ax)=(H%N*65536+L)/N
mov cx,dx ;(cx)=(dx)=余数
pop dx ;(dx)(ax)=
; H/N*65536+(H%N*65536+L)/N
pop bx ;恢复被修改的寄存器
ret
codesg ends
end start
运行结果如下:
