assume cs:code,ds:data
data segment
db '1975','1976','1977','1978','1979','1980','1981'
db '1982','1983','1984','1985','1986','1987','1988'
db '1989','1990','1991','1992','1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065
dd 97479,140417,197514,345980,590827,803530,1183000
dd 1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793
dw 4037,5635,8226,11542,14430,15257,17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
;显示数据缓冲区
printdata segment
dw 8 dup (0)
printdata ends
code segment
;==================================================
;将data中的数据存放到table中。
;==================================================
start: mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov bx,0000h
mov si,0000h
mov bp,0000h
mov cx,0015h
s_put: mov ax,[bx].0000h[si]
mov es:[bp],ax
mov ax,[bx].0002h[si]
mov es:[bp].0002h,ax
mov ax,[bx].00a8h
mov es:[bp].000ah,ax
mov ax,[bx].0056h[si]
mov dx,ax
mov es:[bp].0007h,ax
mov ax,[bx].0054h[si]
mov es:[bp].0005h,ax
div word ptr es:[bp].000ah
mov es:[bp].000dh,ax
add bx,0002h
add si,0002h
add bp,0010h
loop s_put
;=====================================================
;清屏
mov ax,0b800h
mov es,ax
mov bx,0
mov cx,07d0h;设置循环次数,对屏幕清屏。因为全屏有0fa0h个字节,传送的是字的话,需要0fa0/2次循环。
s_clear: mov word ptr es:[bx],0000h
add bx,2
loop s_clear
;======================================================
;从table中取出数据,转换为字符串,显示到显示屏中。
;======================================================
mov ax,table;数据指针定位到table,取出要显示的数据
mov es,ax
mov ax,printdata;将数据取出放到数据缓冲区的段地址
mov ds,ax
mov bh,1;bh为行数,从第一行开始显示,每循环1次,bh就加1.bl的值在循环内部中每次从3开始循环变化,表示显示的列。
mov cx,21;因为要显示21排数据,所以循环21次。
mov bp,0 ;取出时间是哪一年,存到数据显示缓冲区。
s_print: push cx;
;=====================
;输出时间 年
;dp偏移指针用于指示table中数据的位置
;di偏移指针用于指示printdata中存储数据的位置,每次需要清零。
;取出时间年,为4个字节,存放到显示缓冲区。
mov si,0 ;设置输出字符在显示缓冲区的起始偏移地址,用在子程序中。
mov di,0
mov ax,es:[bp]
mov [di],ax
add di,2
mov ax,es:[bp+2]
mov [di],ax
;进行显示设置,并调用显示输出子程序。在第3列显示。
mov bl,3;每一次都从第三列开始显示
mov dh,bh;显示字符所在的行
mov dl,bl;显示字符所在的列
mov cl,7
call show_str;调用输出子程序
;为下一次显示初始化显示缓冲区。
mov word ptr ds:[0],0
mov word ptr ds:[2],0
mov word ptr ds:[4],0
mov word ptr ds:[6],0
mov di,0
add bl,10;表示在下一个10列开始显示数据。
;=================================================
;输出公司总收入
;取出数据,并转换为十进制数的字符串,进行存储。
mov ax,es:[bp+5];表格偏移的第5个字节为收入
mov dx,es:[bp+7];在输出时间 年的程序段中,已经设置了si=0,存储的偏移地址,在此不需要再设置。
call ddtoc
;在第13列显示收入。
mov dh,bh;显示字符所在的行
mov dl,bl;显示字符所在的列
mov cl,7
call show_str;调用输出子程序
;为下一次显示初始化显示缓冲区。
mov word ptr ds:[0],0
mov word ptr ds:[2],0
mov word ptr ds:[4],0
mov word ptr ds:[6],0
mov di,0
add bl,10;表示在下一个10列开始显示数据。
;==================================================
;输出员工数。
;取出员工数,转换为字符串。
mov ax,es:[bp+10];表格偏移的第10个字节为员工数
mov dx,0
call ddtoc
;在第23列输出显示员工数。
mov dh,bh;显示字符所在的行
mov dl,bl;显示字符所在的列
mov cl,7
call show_str;调用输出子程序
;为下一次显示初始化显示缓冲区。
mov word ptr ds:[0],0
mov word ptr ds:[2],0
mov word ptr ds:[4],0
mov word ptr ds:[6],0
mov di,0
add bl,10;表示在下一个10列开始显示数据。
;=================================================
;输出平均收入。
;取出平均收入,转换为字符串。
mov ax,es:[bp+13];表格偏移的第10个字节为员工数
mov dx,0
call ddtoc
;在第33列输出显示平均收入。
mov dh,bh;显示字符所在的行
mov dl,bl;显示字符所在的列
mov cl,7
call show_str;调用输出子程序
;为下一次显示初始化显示缓冲区。
mov word ptr ds:[0],0
mov word ptr ds:[2],0
mov di,0
add bl,10;表示在下一个10列开始显示数据。
;==================================================
inc bh
add bp,16
pop cx
dec cx
jcxz codeend
jmp s_print
codeend: mov ax,4c00h
int 21h
;==============================================
;显示子程序 ,将ds:si中的数据输出。
show_str:push ax
push bx
push cx
push dx
push es
push si
mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov bx,ax
mov al,2
dec dl
mul dl
add bx,ax
mov al,cl
print: mov cl,[si]
mov ch,0
jcxz ok
mov es:[bx],cl
mov cl,al
mov es:[bx+1],cl
add bx,2
inc si
jmp short print
ok: pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
;===========================================
;子程序ddtoc
;四字节数据dx,ax转换为十进制数的asiic码;存放在ds:si中。
ddtoc: push ax
push bx
push cx
push dx
push si
push bp
mov bx,ax;因为要计算两次,所以先保存被除数在bx,bp中
mov bp,dx;
mov si,0;求出dxax中十进制数的位数,存放在si中
ddtoc1: inc si;每除一次数就加1,因为第一次执行除法运算之前,inc后si为1.所以si中的值为商的位数。
mov cx,10
call divdw
mov cx,ax;将商放到cx中,用于判断商是否为0,
jcxz ddtoc2
jmp short ddtoc1
ddtoc2: mov ax,bx;取出被除数
mov dx,bp
mov byte ptr [si],0
ddtoc3: mov cx,10
call divdw
dec si;按照倒序进行数字的存储
add cl,30h;将余数转换为一个数字字符。
mov [si],cl;因为余数是一位数,在8位的cl中可以存下。
mov cx,ax
jcxz ddtoc4
jmp short ddtoc3
ddtoc4: pop bp
pop si
pop dx
pop cx
pop bx
pop ax
ret
;===========================================
;divdw子程序,进行不会产生溢出的除法运算。被除数在dx,ax中,除数在cx中。
divdw: push bx
push si
mov si,ax
mov ax,dx
mov dx,0
div cx
mov bx,ax
mov ax,si
div cx
mov cx,dx
mov dx,bx
pop si
pop bx
ret
;===========================================
code ends
end start
打开App,阅读手记