Power idea 公司从1975年成立一直到1995年的基本情况如下:
下面的程序中,已经定义好了这些数据:
assume cs:codesg,ds:datasg
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'
;以上是表示 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 型数据
datasg ends
table segment
db 21 dup('year summ ne ?? ')
table ends
编程,将data段中的数据按如下格式写入到 table 段中,并计算 21 年中的人均收入(取整),结果也按照下面的格式保存在 table 段中。
分析:本实验中的表格规格是固定的,操作起来就相对简单一些。我们可以直接遍历数据段或者按行遍历数据段
方法一:直接遍历数据段
(1)先遍历年份、收入、人数
由于表格的每行长度为16字节,如果当前表格中遍历的年份位置是es:[di],则下一年在表格的位置是es:[di+16],以此类推将年份、总收入、人数依次案列填入表格中,每次遍历后递增4字节或2字节(年份、总收入占4个字节,总人数占两个字节,还要注意空格),遍历总收入时将数据段总收入首地址保存在栈中,之后计算平均值要用到。
(2)计算平均值
在遍历数据段人数填入表格时时,将数据段总收入首地址从栈中弹出,根据首地址读取总收入放入AX和DX中,将总人数放入BX中,利用div指令计算平均值填入表格中。
assume cs:codesg,ds:datasg,es:table,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,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
datasg ends
table segment
db 21 dup('year summ ne ?? ')
table ends
stacksg segment
dw 2 dup (0) ;栈段用于保存总收入首地址,也可以不使用栈直接用 ds:54h 表示栈段首地址(因为表格固定)
stacksg ends
codesg segment
start:mov ax,datasg ;初始化数据段、table段、栈段地址
mov ds,ax
mov ax,table
mov es,ax
mov ax,stacksg
mov ss,ax
mov cx,21
mov bx,0
mov si,0
mov di,0
s0: ;将年份按列填入表格
mov ax,[si]
mov es:[di],ax
mov ax,[si+2]
mov es:[di+2],ax
add di,16
add si,4
loop s0
mov di,5
mov cx,21 ;保存总收入首地址,之后计算平均值要用
push si
s1: ;将总收入按列填入表格
mov ax,[si]
mov es:[di],ax
mov ax,[si+2]
mov es:[di+2],ax
add di,16
add si,4
loop s1
mov di,0ah
mov cx,21
s2: ;将总人数按列填入表格,同时计算平均值
mov ax,[si]
mov es:[di],ax
;;;; 将数据段总人数当前地址临时放入栈中,让出si寄存器
pop bx
push si
mov si,bx
;;;;; 计算平均值
mov bx,ax
mov ax,[si]
mov dx,[si+2]
div bx
;;;; 将平均值填入表格中,同时栈中si寄存器恢复
mov es:[di+3],ax
add si,4
pop bx
push si
mov si,bx
add di,16
add si,2
loop s2
mov ax,4c00h
int 21h
codesg ends
end start
方法二:按行遍历数据段
在按行进行遍历时,先确定数据段中三种数据的基址,如上图所示,年份:ds:00H、总收入:ds:54H、人数:ds:a8H,然后根据基址加上偏移量所得地址找到数据后逐个按行填入表格,遍历下一行时,年份、总收入的偏移量+4,人数的偏移量+2 ,逐行遍历时,还要同时计算平均值填入表格即可。
assume cs:codesg,ds:datasg,es:table
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,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
datasg ends
table segment
db 21 dup('year summ ne ?? ')
table ends
codesg segment
start:mov ax,datasg ;初始化数据段、table段
mov ds,ax
mov ax,table
mov es,ax
mov si,0
mov di,0
mov bx,0
mov cx,21
s0: ;按行循环填入表格
mov ax,0h[bx]
mov es:0h[di],ax ;将每行的年份填入表格
mov ax,2h[bx]
mov es:2h[di],ax
mov ax,54h[bx] ;将每行的总收入填入表格
mov es:5h[di],ax
mov dx,56h[bx] ;这里使用dx存储总收入高位部分,后面计算平均值要用到
mov es:7h[di],dx
mov ax,0a8h[si] ;将每行的人数填入表格
mov es:0ah[di],ax
mov ax,54h[bx] ;之前ax存储总收入低位部分被覆盖了,要重新存一下
div word ptr 0a8h[si];计算平均值,由于bx要存储偏移量,故除数直接从内存寻址。
mov es:0dh[di],ax ;将内存结果填入表格
add bx,4 ;年份、总收入占4个字节,每次+4
add si,2 ;人数只占两个字节,每次只需+2
add di,16 ;表格每行占16个字节,遍历下一行时要+16
loop s0
mov ax,4c00h
int 21h
codesg ends
end start
将数据填入表格后如下所示: