本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著
实验前别忘了复习笔记
编程,将 data 段中的数据按如下格式写入到 table 段中,并计算 21 年中的人均收入(取整),结果也按照下面的格式保存在 table 段中。
data段:
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'
# 以上表示21年的21个字符串
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
# 以上表示21年公司总收入的21个dword型数据
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,15257,17800
# 以上表示21年公司雇员人数的21个word型数据
data ends
table segment
db 21 dup ('year summ ne ??')
table ends
分析
由于寄存器数量限制,用两次循环。
第一次循环:先内循环四次移动年份,再分两次移动收入的低位和高位 第二次循环:先移动人数,再作除法
- 定义栈用于嵌套循环
- 对于移动年份,需要嵌套循环
- 对于移动收入,由于是双字需要两次移动,以idata==2来移动高低位
- 对于计算平均值,需要先存入ax和dx,是16位除法
mov不能直接对两个内存空间操作,需要借助寄存器- table段使用一个寄存器即可表示
答案
assume cs:codesg,ds:datasg,es:tablesg,ss:stacksg
datasg 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
dd 197514,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
datasg ends
tablesg segment
db 21 dup ('year summ ne ?? ') ;16字节
tablesg ends
stacksg segment
dd 4 dup (0) ;定义16字节,8字,4双字的栈段
stacksg ends
codesg segment
start:mov ax,datasg
mov ds,ax
mov ax,tablesg
mov es,ax
mov ax,stacksg
mov ss,ax
mov sp,10h
;以上是段寄存器的声明
mov bx,0 ;指向第一个年份
mov bp,84 ;指向第一个收入,由于前面存储有4B*21==84B的年份数据,这里需要偏移84
mov di,0 ;指向table段第一个数据
mov cx,21
s1:push cx ;外循环次数入栈
mov si,0 ;年份偏移量,由0-3
mov cx,4 ;四位年份循环4次
year:mov al,byte ptr ds:[bx][si] ;借助寄存器暂存
mov es:[di],al ;移动
inc si
inc di ;累计+4指向收入列
loop year
add bx,4 ;移动到下一个年份,为下一行准备
income:mov ax,word ptr ds:[bp]
mov dx,word ptr ds:2[bp]
mov es:1[di],ax
mov es:3[di],dx ;分两次移动双字
add bp,4 ;移动到下一个收入
add di,12 ;指向table段的人数列
pop cx
loop s1 ;第一次循环
mov bx,168 ;指向第一个人数,由于前面存储有4B*21*2==84B的年份和收入数据,这里需要偏移168
mov di,5 ;指向table的收入列的低位数据
mov cx,21
s2:mov ax,word ptr ds:[bx]
mov es:5[di],ax ;移动人数列,相对收入列偏移5
mov ax,word ptr es:[di]
mov dx,word ptr es:2[di] ;分别移动收入列低位和高位
div word ptr es:5[di] ;以人数列作为除数作除法,16位除法
mov es:8[di],ax ;结果存入平均列,相对收入列偏移8
add di,10h ;增加一行,移动到下一行的人数列
add bx,2 ;移动到下一个人数
loop s2
mov ax,4c00h
int 21h
codesg ends
end start
结果正确