assume cs:codesg
a segment
dw 1975,1976,1977,1978,1979,1980,1981,1982,1983
dw 1984,1985,1986,1987,1988,1989,1990,1991,1992
dw 1993,1994,1995 ;42
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000 ;84
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800 ;42
;dw 5,3,42,104,85,210,123,111,105,125,140,136,153,211,199,209,224,239,260
;dw 304,333 ;42
a ends
codesg segment
start:
mov ax,a
mov ds,ax ;a段数据段地址做ds
mov ax,0b800h ;显存地址做es
mov es,ax
mov si,0 ;显存偏移
mov di,0 ;字符偏移(收入)
mov bx,0 ;字符偏移
mov cx,21
ls: push cx
mov ax,[bx] ;第一组字符(年份),低16位
mov dx,0 ;清零高16位
call dtoc
add si,14h
mov ax,[di+42] ;第二组字符(收入),低16位
mov dx,[di+44] ;高16位
call dtoc
add si,14h
mov ax,[bx+126] ;第三组字符(人数),低16位
mov dx,0 ;清零高16位
call dtoc
push bx ;因为要用到所以保存
add si,14h
mov ax,[di+42] ;第二组字符(收入),低16位
mov dx,[di+44] ;高16位
mov bx,[bx+126] ;人数字符
call divdw ;除法
call dtoc
pop bx
add si,100 ;显存换行写入
add bx,2 ;下一个字符
add di,4 ;下一个收入字符
pop cx
loop ls
mov ax,4c00h
int 21h
dtoc:
push bx ;保存bx要用作之后用做被除数
mov cx,0 ;初始化cx
push cx ;保存cx做计次用
s0:
mov bx,10 ;除法的被除数
call divdw ;跳转到除法
jcxz checklow ;divdw代码结束时才会回到这里,cx=0跳转checklow
s2: pop cx ;恢复计次
inc cx ;计次
add bx,30h ;余,ascll码
push bx ;保存字符ascll码
push cx ;保存计次
;mov cx,10
;loop s0
jmp short s0
divdw: ;除法
push ax ;保存ax,先除dx
mov ax,dx ;dx的值给ax
mov dx,0 ;清零,余(dx)
div bx ;ax除以bx,高16位/10
mov cx,ax ;商给cx
pop ax ;还原ax
div bx ;ax/bx = 低16位/10
mov bx,dx ;余给bx
mov dx,cx ;第一次除法的商给dx
ret
checklow: ;当divdw段代码执行完成时,到jcxz checklow并且cx=0时跳转到这
mov cx,ax ;ax是divdw子程序的商
jcxz showdw ;当除法,商=0时跳转
jmp short s2 ;计算下一个 ,1975 →197
;mov cx,0
;jcxz s2
showdw: ;做字符ascll码
pop cx ;把保存的次数拿出来
inc cx ;加上一次循坏(最后余的)
add bx,30h ;divdw 的余,第一位数(1975的1)
push bx ;把每个数字的ascll保存在栈
mov bx,0 ;清零bx s1要用做显存的偏移变量
s1: pop ax ;把数字的ascll码拿出来
mov es:[si+bx],al ;bx是定位下一个显存字符的变量,(00 00 00 = [bx] 00 [bx])
add bx,2 ;下一组显存数据(00 00 00 = 00 00 [bx])
loop s1
pop bx
ret
codesg ends
end start