
assume cs:codesg ,ds:data ,es:table
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 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
dw 11542,14430,15257,17800
dw 1,2,3
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
buffer segment;定义字符缓冲区
db 16 dup (0)
buffer ends
codesg segment
start:
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov si,0;定位data中的单个年份字符
mov bx,0;定位table中的结构型数据
mov di,0;定位收入
mov bp,0;定位人均收入
mov cx,21
s: push cx
mov cx,4
s1: mov al,ds:[si];拷贝年份(注:其实可以不用循环,拷贝两次字即可)
mov es:[bx],al
inc si
inc bx
loop s1
pop cx
sub bx,4
mov es:[bx+4],' '
mov ax,ds:[84+di];拷贝年收入
mov es:[bx+5],ax
add di,2
mov ax,ds:[84+di]
mov es:[bx+7],ax
add di,2
mov es:[bx+9],' '
mov ax,ds:[168+bp];拷贝雇员数
mov es:[bx+0ah],ax;注意前导0
add bp,2
mov es:[bx+0ch],' '
mov ax,es:[bx+5];计算平均收入(注:其实在拷贝收入的时候直接用ax,dx传送即可省去这两步)
mov dx,es:[bx+7]
div word ptr es:[bx+0ah];不要忘了word ptr
mov es:[bx+0dh],ax
mov es:[bx+0fh],' '
add bx,16
loop s
;------------------清除屏幕,可以写成子程序(入栈保存参数)------------------
push ax
push cx
push es
push di
mov ax,0b800H
mov es,ax
mov di,0
mov cx,2000
lp: mov byte ptr es:[di],' '
add di,2
loop lp
pop di
pop es
pop cx
pop ax
;-----------------清除屏幕完毕---------------------------------------------
mov cx,21;进入循环前的前期准备
mov bp,0;定位table表的行
mov bl,1;定位屏幕行
circle: push cx
;---------显示年份----------------------------------------------------------
mov dh,bl;固定行(1~25)
mov dl,1;固定列(1~80)
mov cl,12;颜色属性:红色高亮
mov ax,table
mov ds,ax
mov si,bp
call show_str_4;功能为显示4个字符
;-----------年份显示完毕----------------------------------------------------
;-----------显示收入(四字节)----------------------------------------------
mov ax,table
mov ds,ax
mov ax,ds:[bp+5]
mov dx,ds:[bp+7]
mov cx,0AH
mov di,buffer;将字符写入到buffer段中
mov ds,di
mov si,0
call dtoc
mov dh,bl
mov dl,20
mov cl,12
call show_str
;------------收入显示完毕------------------------------------------------
;------------显示雇员两字节-----------------------------------------------
mov ax,table
mov ds,ax
mov ax,ds:[bp+0AH]
mov dx,0
mov cx,0AH
mov di,buffer;将字符写入到buffer段中
mov ds,di
mov si,0
call dtoc
mov dh,bl
mov dl,40
mov cl,12
call show_str
;------------雇员显示完毕--------------------------------------------
;------------人均收入两字节------------------------------------------
mov ax,table
mov ds,ax
mov ax,ds:[bp+0DH]
mov dx,0
mov cx,0AH
mov di,buffer;将字符写入到buffer段中
mov ds,di
mov si,0
call dtoc
mov dh,bl
mov dl,60
mov cl,12
call show_str
;-------------人均收入显示完毕------------------------------------
add bp,16
inc bl
pop cx
dec cx;这快的处理是因为loop转移长度的限制。模拟loop指令
cmp cx,0
je exit
jmp near ptr circle
;------------全部显示完毕------------------------------------------
exit: mov ax,4C00H
int 21H
;-------------------------------------------------------------------
dtoc: push ax;子程序中使用的寄存器入栈
push bx
push cx
push dx
push di
push si
mov di,0;计数器,记录余数的个数
s11: mov cx,10;除数
call divdw
inc di
add cx,30H;余数+30H转化为ASCII码
push cx
cmp dx,0
jne s11
cmp ax,0
jne s11
mov cx,di
p: pop ds:[si]
inc si
loop p
;由于show_str的需要,ds:di处的字符串以零作尾。
;mov byte ptr ds:[si],0这条语句有无皆可,因为最后一次入栈的时候高8位一定是零
pop si;子程序中使用的寄存器出栈
pop di
pop dx
pop cx
pop bx
pop ax
ret
;----------------------------------------------------------------------
show_str:
push ax;子程序中使用的寄存器入栈
push cx
push dx
push ds
push es
push si
push di
mov al,160;计算行号和列号对应的显存地址
mov ah,0;不要忽略了
dec dh
mul dh
dec dl
add dl,dl
mov dh,0;不要忽略了
add ax,dx
mov di,ax
mov dl,cl;由于下面的jcxz指令要用到cx,所以用dl保存cl的值
mov ax,0b800h
mov es,ax
s22: mov al,ds:[si]
mov cl,al
mov ch,0
jcxz ok
mov es:[di],al
mov es:[di+1],dl;颜色属性被保存在dl中
inc si
add di,2
jmp short s22
ok: pop di;子程序中使用的寄存器出栈
pop si
pop es
pop ds
pop dx
pop cx
pop ax
ret
;----------------------------------------------------------
show_str_4:
push ax;子程序中使用的寄存器入栈
push cx
push dx
push ds
push es
push si
push di
mov al,160;计算行号和列号对应的显存地址
mov ah,0;不要忽略了
dec dh
mul dh
dec dl
add dl,dl
mov dh,0;不要忽略了
add ax,dx
mov di,ax
mov dl,cl;由于下面的loop指令要用到cx,所以用dl保存cl的值
mov ax,0b800h
mov es,ax
mov cx,4
l: mov al,ds:[si]
mov es:[di],al
mov es:[di+1],dl;颜色属性被保存在dl中
inc si
add di,2
loop l
pop di;子程序中使用的寄存器出栈
pop si
pop es
pop ds
pop dx
pop cx
pop ax
ret
;---------------------------------------------------------------------
divdw: push bx;要用到的寄存器bx、di入栈,下面用它来暂存参数的值
push di;不要将ax,dx,cx入栈,因为程序的目的最终是要修改它们的值
mov bx,ax
mov ax,dx
mov dx,0
div cx;这一步做完以后,ax中为结果的高十六位,即int(H/N),dx中是rem(H/N)的值
mov di,ax
mov ax,bx
div cx;这一步做完以后,ax中为结果的低16位,dx中存储余数
mov cx,dx
mov dx,di
pop di
pop bx
ret
;---------------------------------------------------------------------------
codesg ends
end start