|
发表于 2021-3-23 14:46:58
|
显示全部楼层
对比楼主的代码加上注释,还加上了个人的理解(看了一天了有的地方还是不理解。。。)。
- 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
复制代码 |
|