|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
追了小甲鱼10多年前的视频到现在,留一点学习笔记。
关于汇编实验七--具有里程碑意义的编程,也是花了3天时间从0思考,排查,调试和回看知识点。
【基本思路】
题目给出了4个源数据段,分别是年份、年收入、人数、人均。其中前3个字段是提前定义好的,人均这个字段可以根据年收入除以人数通过循环逐个写入table段;
ds段地址寄存器指向data段,es段地址寄存器指向table目标数据段。
通过4段循环,分别从data数据段按照一定格式导入table数据段。
【问题拆分】
1. 源数据段在哪里?
-A. 年份段:db类型,每1个年份是4个字节(4个单字节字符串),21年就是84个字节。即ds:0~ds:53H;
-B. 年收入段:dd类型,每1个双字类型占用4个字节,21个就是84个字节,继续在54H地址上加。即ds:54H~ds:0A7H;
-C. 人数段:dw类型,每1个字型数据占用2个字节,21个就是42个字节。即ds:0A8H~ds:0D2H;
2. 目标数据段怎么存放?
题目给出了定义21段'year summ ne sr ',这里数了一下,正好是16个字节;
以第一行数据为例:
年份存在es:[0]~es:[3];
年收入存在es:[05H]~es:[08H],其中05H、06H存低位数据,07H、08H存高位数据,分别用ax,dx存储低位、高位数据;
人数存在es:[0AH]~es:[0BH],这里由于是1个字型数据,直接用ax mov过去就行;
人均存在es:[0DH]~es:[0EH]
3. 循环变量:
利用3个计数偏移寄存器bx、di、si来实现:
年份段:2重循环,内循环bx变量每次+1,外循环si变量+4取到每个年份的第一个字段,di变量+16定位es段的第一位
年收入段:1层循环,每次si+4指向下一个double word数据,di变量+16定位es段,加上[05H]和[07H]低位、高位数据段地址
人数:1层循环,每次si+2指向下一个字型数据,di变量+16定位es段,加上[0AH]偏移量
人均:1层循环,仅用di变量+16定位,每一次将es:[05H+di]和es:[07H+di]地址值分别给ax, dx,做除法后商被写入ax,最后mov es:[di+13], ax
【源码】
assume cs:code,ds:data,es:table,ss:stack
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,1356,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 summ ne sr ')
table ends
stack segment
db 0,0
stack ends
code segment
start: mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov si,0 ; 年份数据偏移
mov di,0 ; table段偏移
mov cx,20 ; 处理21个年份,这里我用了栈段,第一次push cx没走到loop,cx不会-1,因此初始值设定20
; 复制年份到table段
year_loop:
push cx
mov cx,4
mov bx,0 ; 每次内循环重置bx,这也是我之前排查好久的点,debug一看数据怎么老错位
copy_year:
mov al,[si+bx]
mov es:[di+bx],al
inc bx
loop copy_year
add si,4 ; 下一个年份
add di,16 ; table下一行
pop cx
loop year_loop
; 处理summ(总收入)
mov si,84 ; summ数据起始偏移(21*4=84)
mov di,0
mov cx,21
summ_loop:
mov ax,[si] ; 低16位
mov dx,[si+2] ; 高16位
mov es:[di+5],ax
mov es:[di+7],dx
add si,4 ; 下一个dd
add di,16
loop summ_loop
; 处理ne(雇员数)
mov si,168 ; ne数据起始偏移(84+84=168)
mov di,0
mov cx,21
ne_loop:
mov ax,[si]
mov es:[di+10],ax ; ne字段偏移0AH
add si,2
add di,16
loop ne_loop
; 计算sr(人均收入)
mov di,0
mov cx,21
sr_loop:
mov ax,es:[di+5] ; 总和的低16位
mov dx,es:[di+7] ; 总和的高16位
div word ptr es:[di+10] ; 正确除数:ne字段值
mov es:[di+13],ax ; sr字段偏移0DH
add di,16
loop sr_loop
mov ax,4C00H
int 21H
code ends
end start |
|