实现思路是先按照书中引导的3个问题写好子程序,然后再写,本课程设计的部分。由于是低级语言建议多写注释,(我的代码中加了许多)。多多的debug调试。
assume cs:codesg
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995';年
;收入
dd 16,22,382,1536,2390,8000,16000,24486,50065,97479,140417,197514
dd 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
dw 11542,14430,15257,17800;人数
data ends
table segment
db 21 dup ('year s n ? ',0)
table ends
stack segment
db 16 dup (0)
stack ends
codesg segment
start:
mov ax,table
mov ds,ax;表
mov ax,stack
mov ss,ax
mov sp,10H
mov ax,data
mov es,ax;es data
mov cx,21;循环21次
mov bx,0
mov bp,0
mov di,0
;name s
;数据格式化存入内存中('year s n ? ',0)| bits (4 7 5 3 ) + '0'
;每行共24字符
s:
mov si,0
push cx
mov cx,4;年有四位
s0: ;年
mov al,es:[bp+si+0]
mov byte ptr [bx].0h[si],al
inc si
loop s0
;收入 原:逐个字节copy
; 现:改为对应数值各个位的ASCII码(用于显示)
push ax
push dx
mov si,0
mov ax,es:es:84[bp+si];dword 低16位 84 = 4*21
add si,2
mov dx,es:84[bp+si];dword 高16位
mov si,bx
add si,5;该行收入对应的位置
call dtoc;数字转成字符串存到内存
pop dx
pop ax
;人数
push ax
push dx
mov ax,es:[168+di];168十进制数 4*21 + 4*21 人数的起始地址
mov dx,0
mov si,bx
add si,0dh;表中人数对应的位置
call dtoc
pop dx
pop ax
;mov word ptr [bx].0aH,ax
;div 算平均工资 (16位除法 dx=高16位 ax=低16位 || 结果ax=商 dx=余数)
;目前没有将测量数值转换成平均值
mov dx,es:es:84[bp+2];dword 低16位 84 = 4*21
mov ax,es:es:84[bp+0];dword 低16位 84 = 4*21
div word ptr es:168[di];求得商ax
;下边4行摆放商到合适的位置
mov dx,0
mov si,bx
add si,19;表中人均收入对应的位置
call dtoc
add bx,24;写入新地址 格式化后每行有24个字符(新添加0字符)
add bp,4
add di,2
pop cx
loop s
mov cx,21
mov dh,2;行
mov si,0;从 ds:[0]开始显示
show:
push si
push cx
;显示表格
;显示配置项
mov dl,3;列
mov cl,2;绿色
call show_str;显示
add si,13
add dl,13
call show_str
add si,6
add dl,6
call show_str
pop cx
pop si
add si,24
inc dh
loop show
mov ax,4c00h
int 21h
;进行不会产生溢出的除法运算
;被除数位dword dx 高 16位 | ax低16位
;cx 除数
;结果 dx 高16位 | ax 低16位 | cx余数
divdw:
push si
mov si,ax;低16位
mov ax,dx
mov dx,0h
div cx;ax 商 dx余数
push ax
mov ax,si
div cx;
mov cx,dx;存余数
pop dx
pop si
ret
; 输入 (ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
;结果 ds:si指向字符串的首地址
dtoc:
push di;余数个数
push dx
push cx
push si
push bx
mov di,0
mov cx,10
push ax
push dx
;s0 求余数个数
;输入 除数 cx 16位 操作数低16位 ax 操作数 高16位dx
;单步结果 商ax 余数dx
;最终结果 di 存储余数个数
dtocs0:
push cx
call divdw
mov cx,dx
or cx,ax;商为0代表数字处理结束
inc di
jcxz dtocs;通过把商转移进cx(dx or ax) 判断除法是否结束
pop cx
jmp dtocs0
dtocs:
pop cx
push bx;push
mov bx,si
mov byte ptr ds:[di+bx],0;字符串结束符 ds:[si]指向生成字符串的首地址
pop bx;pop
pop dx
pop ax; dx:ax源操作数
;s1 把数字的ASCII存到ds:0中
dtocs1:
push cx ;除数
dec di
call divdw
add cl,30h
push bx
mov bx,si
mov ds:[di+bx],cl;位值对应的ASCII码
pop bx
mov cx,dx;!!!
or cx,ax;!!! 判断商为0
jcxz dtocok
pop cx
jmp dtocs1
dtocok:
pop cx
pop bx
pop si
pop cx
pop dx
pop di
ret
show_str:
push cx
push ax
push di
push si
push bx
push dx
mov al,0a0h;每行字符数
sub dh,1
mul dh
mov di,ax;//行数*行
mov dh,0
sub dl,1
mov al,2h
mul dl
add di,ax
mov ax,0b800h
mov es,ax
mov bl,cl;样式
;起始地址 ds:[si] ,显示该字符串
;样式位于bl中
shostrs:
mov cl,[si]
mov ch,0h
jcxz showstrok
mov byte ptr es:[di],cl
inc di
mov byte ptr es:[di],bl
inc di
inc si
jmp shostrs
showstrok:
pop dx
pop bx
pop si
pop di
pop ax
pop cx
ret
codesg ends
end start