课程设计1
本帖最后由 拖着拖把去拖鞋 于 2023-3-3 15:16 编辑用了3个循环.改了几次,这次应该是可读性最好的了.欢迎指导
; 显示数据在显示器上
assume cs:code
data segment
; 21个年头
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年来每一年的收入,偏移位置开头为54H
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
; 21年来每一年的雇员,偏移位置开头为A8H
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
; 存放每一年的人均收入,偏移地址开头为D2H
dw 21 dup (0)
; 21行40列的输出字符串,偏移地址开头为FCH
db 840 dup (20H)
;偏移地址开头为444H,分别是年份、收入、雇员、人均收入的偏移地址
dw 0H,54H,0A8H,0D2H
;偏移地址开头为44cH,分别是年份、收入、雇员、人均收入字符串的偏移地址
dw 0FCH,106H,110H,11AH
data ends
stack segment
dw 8 dup (0)
stack ends
code segment
start: movax,data
movds,ax
movax,stack
movss,ax
movsp,32
movsi,54H ; 用于定位年收入
movdi,0A8H ; 用于定位年雇员
movbp,0D2H ; 用于定位人均收入
movcx,21
; l0用于计算年人均收入
l0: movax,ds:
movdx,ds:
movbx,ds:
divbx ; 计算年人均收入
movds:,ax ; 存入计算得出的人均收入
addsi,4
adddi,2
addbp,2
loop l0
movcx,21
l1: push cx
; 存入年份 start
movdi,ds: ; 存入即将要处理的年份的偏移地址
movsi,ds: ; 存入即将要写入数据的偏移地址
movax,ds: ; 存入即将要处理的年份
movds:,ax ; 将年份存入字符串
movax,ds: ; 存入即将要处理的年份
movds:,ax ; 将年份存入字符串
adddi,4 ; 移到下一个要处理的年份
addsi,40 ; 移到下一行,对应年份的位置
movds:,di ; 更新内存中的地址
movds:,si ; 更新内存中的地址
; 存入年份 end
; 存入收入 start
movdi,ds: ; 存入即将要处理的收入的偏移地址
movsi,ds: ; 存入即将要写入数据的偏移地址
movax,ds:
movdx,ds:
push si
call change_to_dec_init ; 转换收入数据
popsi
adddi,4
addsi,40
movds:,di ; 更新内存中的地址
movds:,si ; 更新内存中的地址
movdx,0
; 存入收入 end
; 录入雇员 start
movdi,ds:
movsi,ds: ; 存入即将要写入数据的偏移地址
movax,ds:
push si
call change_to_dec_init ; 转换雇员数据
popsi
adddi,2
addsi,40
movds:,di ; 更新内存中的地址
movds:,si ; 更新内存中的地址
; 录入雇员 end
; 录入人均收入 start
movdi,ds: ; 存入人均收入的偏移地址
movsi,ds: ; 存入即将要写入数据的偏移地址
movax,ds:
push si
call change_to_dec_init ; 转换人均收入数据
popsi
adddi,2
addsi,40
movds:,di ; 更新内存中的地址
movds:,si ; 更新内存中的地址
; 录入人均收入 end
popcx
deccx
jcxz l1_end
jmpl1
l1_end: nop
movcx,21
movsi,123H
; l3用于输出前的预处理,把每一行后面置为0
l2: movbyte ptr ds:,0 ; 每一行最后放0,作为结尾
addsi,40
loop l2
movsi,0FCH ; 用于定位字符串数据
movdi,0 ; 用于定位显存位置
movdh,3 ; 行号
movdl,30 ; 列号
movbl,2 ; 颜色
call show_str_init
movcx,21
; l4用于输出数据到显示器
l3: push cx
call show_str_start
adddi,80 ; 换行.数据占了40列也就是80个字节,所以160-80
popcx
loop l3
movax,4c00h
int21h
; 名称: change_to_dec
; 功能: 将dword或word型数据转变为表示十进制数的字符串,字符串以0结尾
; 参数: ax=数据低16位
; dx=数据高16位
; ds:si指向字符串首地址
; 返回: 无
change_to_dec_init: movcx,0
push cx ; 作为结尾
change_to_dec_start:movcx,10
call divdw
addcx,ax ; 处理数据中有0意外结束循环的问题
jcxz change_to_dec_ok
subcx,ax
addcx,30h ; 算出ASCII码中对应的十进制数
push cx ; 由于先算出来的是最后一位,先入栈暂存
jmpshort change_to_dec_start
change_to_dec_ok: popcx
jcxz change_to_dec_end
movds:,cl
incsi
jmpshort change_to_dec_ok
change_to_dec_end:ret
; 名称: divdw
; 功能:进行不会产生溢出的除法运算
; 参数: ax=被除数低16位
; dx=被除数高16位
; cx=除数
; 返回: ax=结果低16位
; dx=结果高16位
; cx=余数
; 公式:X:被除数、N:除数、H:X高16位、L:X低16位、int():取商、rem():取余数
; X/N=int(H/N)*65536+/N
divdw: push ax ; 暂存被除数低16位
movax,dx ; 存放被除数高16位
movdx,0 ; 除数16位的话dx会参与运算,置0避免溢出
divcx ; 计算int()和rem()
movbx,ax ; 暂存结果高16位
popax
divcx ; 计算(rem(H/N)*65536+L)/N
movcx,dx ; 存放返回值余数
movdx,bx ; 存放返回值高16位
ret
; 名称: show_str
; 功能: 在指定的位置,用指定的颜色,显示一个0结尾的字符串
; 参数: dh=行号(取值范围0~24)
; dl=列号(取值范围0~79)
; cl=颜色
; ds:si指向字符串首地址
; ds:di指向当前显示位置
; 返回: 无
show_str_init: movax,0b800h ; 显示区域的开头
moves,ax
movch,0
movcl,dh
ssil0: adddi,160 ; 计算跳到指定行的字节数
loop ssil0
movcl,dl
ssil1: adddi,2 ; 计算跳到指定列的字节数
loop ssil1
ret
show_str_start: movch,0
movcl,ds:
jcxz show_str_ok
moves:,cl ; 存放需要显示的字符
moves:,bl ; 存放需要显示的颜色
incsi
adddi,2
jmpshort show_str_start
show_str_ok: movbyte ptr es:,0 ; 增加一个字符串之间的间隔
movbyte ptr es:,0
adddi,2
incsi ; 跳过字符串结尾的‘0’
ret
code ends
end start
页:
[1]