课程设计一

 

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 

原文地址:https://www.cnblogs.com/xpjiang/p/4524437.html