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