使用temp空间来暂存每一行要显示的字符, 然后调用show_str子程序 进行显示
外层21次循环
难点:dd段的数字太大,无法简单进行除10存储, 需要借助div_d 大除法的子程序(更改的),
assume cs:code,ds:table,ss:stack
stack segment
db 32 dup (0)
stack ends
table segment
db 81 dup(0) ; temp空间
; 81 * 1 = 81 byte
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
; 21 * 4 = 84 byte
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514 ; 12
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
; 21 * 4 = 84 byte
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
; 21 * 2 = 42 byte
db 1,0,0,0,0 ; 循环的第几,年的第几,钱的第几,人的第几,当前temp空间的指向
; 5 * 1 = 5 byte
table ends
code segment
start:
mov ax,stack
mov ss,ax
mov sp,32
mov ax,table ; 原始数据
mov ds,ax
mov bx,0 ; 年的计数
mov cx,21
main_loop:
push cx
; ds:[84+84+42+5] 是temp区域
; =========== 年 ===============
; 显示4列
mov cx,4
mov bl,ds:[81+84+84+42][1] ; 年的字节在哪
mov bh,0
mov si,0
start_s1:
mov dl, ds:81[bx] ; 记得跳过81byte
mov ds:[si],dl
inc bx
inc si
loop start_s1
mov al,4
mov ds:[81+84+84+42][4],al
; ================ 空格 =================
mov cx,4 ; 空格数量
; mov dl,ds:[81+84+84+42][4]
call add_space ; 存储空格
; add dl,4
; mov ds:[81+84+84+42][4],dl ; temp扩增了
; =================== 收入 ==================
; 显示10列
mov bl,ds:[81+84+84+42][2] ; 收入的字节在哪
mov bh,0
mov ax,ds:[81+84][bx]
mov dx,ds:[81+84][bx+2]
mov bl,ds:[81+84+84+42][4]
mov bh,0
mov si,bx ; 存到 ds:[..] 中
call dtoc
add bl,10
mov ds:[81+84+84+42][4],bl ; temp扩增了
; ================ 空格 =================
mov cx,4 ; 空格数量
call add_space ; 存储空格
; ============= 人数 ========================
; 显示6列
mov bl,ds:[81+84+84+42][3] ; 人数bx位置
mov bh,0
mov ax,ds:[81+84+84][bx] ; 低位
mov dx,0 ; 高位没有
mov bl,ds:[81+84+84+42][4]
mov bh,0
mov si,bx ; 存到 ds:[..] 中
call dtoc
add si,6
mov ds:[81+84+84+42][4],si ; temp扩增了
; ================ 空格 =================
mov cx,4 ; 空格数量
call add_space ; 存储空格
; ====== 人均收入 =======================
; 占6位
mov bl,ds:[81+84+84+42][2]
mov al,ds:[81+84+84+42][3]
mov bh,0
mov ah,0
mov di,ax
mov ax,ds:[81+84][bx] ; 收入 低位
mov dx,ds:[81+84][bx].[2] ; 收入 高位
div word ptr ds:[81+84+84][di]
; mov ax,ax ; 使用数字字符化,ax可以不动
mov dx,0 ; 高位没有
mov bl,ds:[81+84+84+42][4]
mov bh,0
mov si,bx ; 存到 ds:[..] 中
call dtoc
add bl,6
mov ds:[81+84+84+42][4],bl ; temp扩增了
; ================ 空格 =================
mov cl,80
sub cl,ds:[81+84+84+42][4] ; 空格数量
mov ch,0
call add_space ; 存储空格
; ==================== 显示 =================
mov al,0
mov bl,ds:[81+84+84+42][4]
mov bh,0
mov ds:[bx],al ; 最后一位存个0
mov si,0
mov dh,ds:[81+84+84+42][0] ; row
mov dl,1 ; column
call show_str
; ======== 收尾 ===========
mov al,ds:[81+84+84+42][0]
add ax,1
mov ds:[81+84+84+42][0],al ;更新循环次数
mov al,ds:[81+84+84+42][1]
add al,4
mov ds:[81+84+84+42][1],al
mov al,ds:[81+84+84+42][2]
add al,4
mov ds:[81+84+84+42][2],al
mov al,ds:[81+84+84+42][3]
add al,2
mov ds:[81+84+84+42][3],al
pop cx
dec cx
jcxz main_over
jmp far ptr main_loop
; loop main_loop ;超长度
main_over:
mov cx,25
sub cx,21
mov di,0
over_s:
push cx
mov cx,80 ; 空格数量
call add_space
mov si,0
mov dh,ds:[81+84+84+42][0].[di] ; row
mov dl,1 ; column
call show_str
pop cx
loop over_s
mov ax,4c00h
int 21h
; -------------------------------------------
add_space:
push si
push ax
push dx
push cx
mov dl,ds:[81+84+84+42][4]
; cx => 空格个数
; dl => 第几列
mov dh,0
mov si,dx
mov al,' '
start_s2:
mov ds:[si],al
add si,1
loop start_s2
pop cx ; 先把cx复原
add dl,cl
mov ds:[81+84+84+42][4],dl ; temp扩增了
pop dx
pop ax
pop si
ret
; ------------------------------------------
dtoc:
; in ax 低位 dx 高位
; out ds:[si] ds:[si+2] 地址
push ax
push bx
push cx
push dx
mov bx,0 ;记录位数
run1:
mov cx,10 ; 除数
call divdw
; 处理
add cl,'0' ; 变成字符
mov ch,0
push cx ; 倒得入栈
inc bx
push dx ; 备份dx,这是高位
or dx,ax ; 判断作为商的ax和dx为0吗
mov cx,dx ; 给cx 判断结束吗
pop dx
jcxz ok1 ; 除法结束
jmp run1
ok1:
; ==== 开始写入 =====
mov cx,bx
mov dx,bx
mov bx,si ; 从ds:[si] 开始放字符
dtoc_s1:
pop ds:[bx]
inc bx
loop dtoc_s1
mov cx,10 ; dd 最大可能用10byte
sub cx,dx
jcxz dtoc_s3
dtoc_s2: ; 填充空格
mov al,' '
mov ds:[bx],al
inc bx
loop dtoc_s2
dtoc_s3:
mov al,0
mov ds:[bx],al
pop dx
pop cx
pop bx
pop ax
ret
;----------------------------------------------------
divdw:
; in : 被除数 ax:low 16 dx:high 16 除数 cx
; out: 商 ax:low 16 dx:high 16 余数 cx
push bx
mov bx,ax ; backup 被除数 low 16
mov ax,dx
mov dx,0 ; no high
div cx
push ax ; save high 16 of result
mov ax,bx ; original 被除数 low 16
mov dx,dx ; 上一次的余数就是这一次的高位
div cx
mov cx,dx ; 余数
pop dx ; high 16
pop bx
ret
; --------------------------------------------------
show_str:
; 显示 ds:[si] 中的 到0结束
push dx
push cx
push ax
push bx
push si
mov cl,2 ; color
mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov bx,ax ; calculate row
mov dh,0
add dx,dx
sub dx,2
add bx,dx ; add the column
mov al,cl ; color
show_str_s1:
mov cl,ds:[si]
mov ch,0
jcxz show_str_ok
mov ch,al
mov es:[bx],cx
add si,1
add bx,2
jmp show_str_s1
show_str_ok:
pop si
pop bx
pop ax
pop cx
pop dx
ret
code ends
end start
第一版耗时10小时
优化花费2小时