assume cs:codesg
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983','1984','1985','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,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,11542,14430,15257,17800
data ends
;该段存储实际数值
table segment
db 21 dup('year summ ne ?? ')
table ends
;该段存储待显示的内容
display_str segment
db 1680 dup(' ')
db 0
display_str ends
;开辟一个栈空间
sta segment
dw 16 dup(0)
sta ends
codesg segment
start:
mov ax,sta
mov ss,ax
mov sp,16
mov ax,data
mov es,ax
mov ax,table
mov ds,ax
mov cx,21
mov bx,0
mov di,0
mov si,168
;写入源数据
s:
;写入年份
push es:[bx]
pop [di]
add di,2
push es:[bx].2
pop [di]
add di,3
;写入总收入,并存入被除数寄存器中
mov ax,es:[bx].84
push ax
pop [di]
add di,2
mov dx,es:[bx].86
push dx
pop [di]
add di,3
;写入人数
push es:[si]
pop [di]
;计算并写入人均收入
div word ptr [di]
add di,3
mov [di],ax
add di,3
;累加变量
add bx,4
add si,2
loop s
;写入目标显示数据
mov ax,table
mov ds,ax
mov si,0
mov ax,display_str
mov es,ax
mov di,0
call turn_all_display
;显示所有数据
mov dh,1
mov dl,1
mov cl,7ah
mov ax,display_str
mov ds,ax
mov si,0
call show_str
mov ax,4c00h
int 21h
;将数值转换为十进制字符串并存储到指定位置,参数ax,dx双字型数据,ds:si字符串首地址
dtoc:
;寄存器入栈
push bx
push ax
push dx
push si
push ds
push cx
re_do:
mov bx,10
call divdw
add bx,30h
mov [si],bl
mov bx,0
inc si
mov cx,dx
jcxz judge_l
judge_l:mov cx,ax
jcxz dtoc_ok
jmp short re_do
dtoc_ok:
;寄存器出栈
pop cx
pop ds
pop si
pop dx
pop ax
pop bx
ret
;在指定位置显示字符串,参数dh行号,dl列号,cl颜色,ds:si字符串地址
show_str:
;寄存器入栈
push cx
push ax
push dx
push di
push es
push bx
;计算行偏移数值
mov ax,160
mul dh
mov di,ax
mov dh,0
add dl,dl
add di,dl
sub di,2
mov al,cl
show_byte:
mov cl,[si]
mov ch,0
jcxz ok
mov bx,0b800h
mov es,bx
mov es:[di],cl
inc di
mov es:[di],al
inc si
inc di
jmp short show_byte
ok:
;寄存器出栈
pop bx
pop es
pop di
pop dx
pop ax
pop cx
ret
;将所有行数据转为显示数据,参数ds:si源数据首地址,es:di目标数据首地址
turn_all_display:
push cx
push ds
push si
push es
push di
mov cx,21
turn_all_display_s0:
call turn_display
add si,10h
add di,80
loop turn_all_display_s0
pop di
pop es
pop si
pop ds
pop cx
ret
;将一行实际数值转为显示数值,参数ds:si源行首地址,es:di目标行首地址
turn_display:
;寄存器入栈
push ds
push si
push es
push di
push ax
push cx
push bx
;转存年份
mov cx,4
turn_display_s:
mov ax,ds:[si]
mov es:[di],ax
inc si
inc di
loop turn_display_s
inc si
;转存总收入
push ds
push es
push si
push di
mov ax,[si]
mov dx,[si+2]
mov bx,es
mov ds,bx
inc di
mov si,di
call dtoc
;颠倒字节
push ax
mov ax,10
call relist
pop ax
pop di
pop si
pop es
pop ds
;转存总人数
push ds
push es
push si
push di
mov ax,[si+5]
mov dx,0
mov bx,es
mov ds,bx
add di,12
mov si,di
call dtoc
;颠倒字节
push ax
mov ax,5
call relist
pop ax
pop di
pop si
pop es
pop ds
;转存人均收入
push ds
push es
push si
push di
mov ax,[si+8]
mov dx,0
mov bx,es
mov ds,bx
add di,18
mov si,di
call dtoc
;颠倒字节
push ax
mov ax,5
call relist
pop ax
pop di
pop si
pop es
pop ds
;寄存器出栈
pop bx
pop cx
pop ax
pop di
pop es
pop si
pop ds
ret
;防溢出除法运算,双字型被除数,入参被除数高位dx低位ax,除数bx,出参结果高位dx低位ax,余数bx
divdw:
;寄存器入栈
push si
push di
mov si, ax ; 将低 16 位保存到另外的寄存器中
mov ax, dx
mov dx, 0
div bx ; 执行 H/N,div 指令执行后,ax 中保存着商int(H/N),dx 中保存着余数rem(H/N)
mov di, ax ; 将 int(H/N) 保存到另外的寄存器中
mov ax, si ; dx 中的数为 rem(H/N)*65536,ax 中的数为被除数的低 16 位
div bx ; [rem(H/N)*65536 + L]/N = [(dx)*65536 + (ax)] / (cx)
mov bx, dx ; cx 中存放余数
mov dx, di ; 将结果的高 16 位放入 dx 中,ax 默认保留着结果的低 16 位
;寄存器出栈
pop di
pop si
ret
;将一段内存中的高低位字节颠倒存储,入参ds:si开始字节,ax长度
relist:
push ds
push si
push ax
push bx
push cx
push di
mov di,ax
sub di,1
add di,si
mov bx,2
div bl
mov cl,al
mov ch,0
relist_s0:
mov bl,[si]
mov al,[di]
mov [si],al
mov [di],bl
inc si
sub di,1
loop relist_s0
pop di
pop cx
pop bx
pop ax
pop si
pop ds
ret
codesg ends
end start
03-20
1676
