|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 拖着拖把去拖鞋 于 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: mov ax,data
- mov ds,ax
- mov ax,stack
- mov ss,ax
- mov sp,32
- mov si,54H ; 用于定位年收入
- mov di,0A8H ; 用于定位年雇员
- mov bp,0D2H ; 用于定位人均收入
- mov cx,21
- ; l0用于计算年人均收入
- l0: mov ax,ds:[si]
- mov dx,ds:[si+2]
- mov bx,ds:[di]
- div bx ; 计算年人均收入
- mov ds:[bp],ax ; 存入计算得出的人均收入
- add si,4
- add di,2
- add bp,2
- loop l0
- mov cx,21
- l1: push cx
- ; 存入年份 start
- mov di,ds:[444H] ; 存入即将要处理的年份的偏移地址
- mov si,ds:[44CH] ; 存入即将要写入数据的偏移地址
- mov ax,ds:[di] ; 存入即将要处理的年份
- mov ds:[si],ax ; 将年份存入字符串
- mov ax,ds:[di+2] ; 存入即将要处理的年份
- mov ds:[si+2],ax ; 将年份存入字符串
- add di,4 ; 移到下一个要处理的年份
- add si,40 ; 移到下一行,对应年份的位置
- mov ds:[444H],di ; 更新内存中的地址
- mov ds:[44CH],si ; 更新内存中的地址
- ; 存入年份 end
- ; 存入收入 start
- mov di,ds:[446H] ; 存入即将要处理的收入的偏移地址
- mov si,ds:[44EH] ; 存入即将要写入数据的偏移地址
- mov ax,ds:[di]
- mov dx,ds:[di+2]
- push si
- call change_to_dec_init ; 转换收入数据
- pop si
- add di,4
- add si,40
- mov ds:[446H],di ; 更新内存中的地址
- mov ds:[44EH],si ; 更新内存中的地址
- mov dx,0
- ; 存入收入 end
- ; 录入雇员 start
- mov di,ds:[448H]
- mov si,ds:[450H] ; 存入即将要写入数据的偏移地址
- mov ax,ds:[di]
- push si
- call change_to_dec_init ; 转换雇员数据
- pop si
- add di,2
- add si,40
- mov ds:[448H],di ; 更新内存中的地址
- mov ds:[450H],si ; 更新内存中的地址
- ; 录入雇员 end
- ; 录入人均收入 start
- mov di,ds:[44AH] ; 存入人均收入的偏移地址
- mov si,ds:[452H] ; 存入即将要写入数据的偏移地址
- mov ax,ds:[di]
- push si
- call change_to_dec_init ; 转换人均收入数据
- pop si
- add di,2
- add si,40
- mov ds:[44AH],di ; 更新内存中的地址
- mov ds:[452H],si ; 更新内存中的地址
- ; 录入人均收入 end
- pop cx
- dec cx
- jcxz l1_end
- jmp l1
- l1_end: nop
- mov cx,21
- mov si,123H
- ; l3用于输出前的预处理,把每一行后面置为0
- l2: mov byte ptr ds:[si],0 ; 每一行最后放0,作为结尾
- add si,40
- loop l2
- mov si,0FCH ; 用于定位字符串数据
- mov di,0 ; 用于定位显存位置
- mov dh,3 ; 行号
- mov dl,30 ; 列号
- mov bl,2 ; 颜色
- call show_str_init
- mov cx,21
- ; l4用于输出数据到显示器
- l3: push cx
- call show_str_start
- add di,80 ; 换行.数据占了40列也就是80个字节,所以160-80
- pop cx
- loop l3
- mov ax,4c00h
- int 21h
- ; 名称: change_to_dec
- ; 功能: 将dword或word型数据转变为表示十进制数的字符串,字符串以0结尾
- ; 参数: ax=数据低16位
- ; dx=数据高16位
- ; ds:si指向字符串首地址
- ; 返回: 无
- change_to_dec_init: mov cx,0
- push cx ; 作为结尾
- change_to_dec_start:mov cx,10
- call divdw
- add cx,ax ; 处理数据中有0意外结束循环的问题
- jcxz change_to_dec_ok
- sub cx,ax
- add cx,30h ; 算出ASCII码中对应的十进制数
- push cx ; 由于先算出来的是最后一位,先入栈暂存
- jmp short change_to_dec_start
- change_to_dec_ok: pop cx
- jcxz change_to_dec_end
- mov ds:[si],cl
- inc si
- jmp short 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+[rem(H/N)*65536+L]/N
- divdw: push ax ; 暂存被除数低16位
- mov ax,dx ; 存放被除数高16位
- mov dx,0 ; 除数16位的话dx会参与运算,置0避免溢出
- div cx ; 计算int()和rem()
- mov bx,ax ; 暂存结果高16位
- pop ax
- div cx ; 计算(rem(H/N)*65536+L)/N
- mov cx,dx ; 存放返回值余数
- mov dx,bx ; 存放返回值高16位
- ret
- ; 名称: show_str
- ; 功能: 在指定的位置,用指定的颜色,显示一个0结尾的字符串
- ; 参数: dh=行号(取值范围0~24)
- ; dl=列号(取值范围0~79)
- ; cl=颜色
- ; ds:si指向字符串首地址
- ; ds:di指向当前显示位置
- ; 返回: 无
- show_str_init: mov ax,0b800h ; 显示区域的开头
- mov es,ax
- mov ch,0
- mov cl,dh
- ssil0: add di,160 ; 计算跳到指定行的字节数
- loop ssil0
- mov cl,dl
- ssil1: add di,2 ; 计算跳到指定列的字节数
- loop ssil1
- ret
- show_str_start: mov ch,0
- mov cl,ds:[si]
- jcxz show_str_ok
- mov es:[di],cl ; 存放需要显示的字符
- mov es:[di+1],bl ; 存放需要显示的颜色
- inc si
- add di,2
- jmp short show_str_start
- show_str_ok: mov byte ptr es:[di],0 ; 增加一个字符串之间的间隔
- mov byte ptr es:[di+1],0
- add di,2
- inc si ; 跳过字符串结尾的‘0’
- ret
- code ends
- end start
复制代码 |
|