# 实验七
实验七
题目
Power idea公司从1975年成立一直到1995年的基本情况如下:
| 年份 | 收入(千美元) | 雇员(人) | 人均收入(千美元) |
|---|---|---|---|
| 1975 | 16 | 3 | ? |
| 1976 | 22 | 7 | ? |
| 1977 | 382 | 9 | ? |
| 1978 | 1356 | 13 | ? |
| 1979 | 2390 | 28 | ? |
| 1980 | 8000 | 38 | ? |
| ~~~ | |||
| 1995 | 5937000 | 17800 | ? |
下面已经定义好了这些数据:
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
end start
编程,将data段中的数据按如下格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中。

思路
碰到数据处理题,首先要弄清楚数据存放在哪里,大小是多少。
本题已知的数据类共三个,分别是年份,收入,雇员数。
-
年份:
共4个字节,从0B到3B,需要二重循环解决
-
收入
共4个字节,从5B到8B,需要二重循环解决
-
雇员数
共2个字节,从AB到BB,一个循环即可解决
table段地址怎么知道?
要想知道table段地址,首先要知道data段的长度,共21条记录,年份4个字节,收入4个字节,雇员数2个字节,共21*(4+4+2)=210个字节,16进制为00d2h,前文学过,段空间的基本单位为16字节一小节,不满补16字节,故虽然段空间大小为00d2h,但实际上为其分配了00e0h。
下面结合代码分析:
assume cs:codesg,ss:stacksg
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
stacksg segment
dw 10 dup(0); 定义一段栈空间,存放二重循环的cx和需要暂时更改的bx
stacksg ends
codesg segment
start:
mov ax,data
mov ds,ax
mov ax,stacksg
mov ss,ax
mov bx,00e0h; 定义table段地址,不需要定义data段,因为可以直接加ds得到想要的数据,其实可以用es存
push bx; 下面要对bx做法,故需存入栈中保存table段地址
mov cx,21
mov si,0
s1:
push cx
mov cx,2; 按字循环,每次加两个字节
mov di,0; di为目的段地址的偏移量,每次循环需要置零
s11:
mov ax,[si]; si为数据段地址,不断累加即可
mov [bx+di],ax
add si,2
add di,2
loop s11
pop cx; 注意出入栈的顺序
add bx,16; 通过加16,可以转到table下一行
loop s1
pop bx; 先出栈
push bx; 再入栈
mov cx,21
mov si,0
s2:
push cx
mov cx,2; 同s1循环,4个字节的传输
mov di,0
s21:
mov ax,[84+si]; 因为年份数据共4*21=84
mov [bx+5+di],ax; 位于table段的5B到8B
add si,2
add di,2
loop s21
pop cx
add bx,16
loop s2
pop bx
push bx
mov cx,21
mov si,0
s3:
mov ax,[168+si]; 在84基础上再加上4*21=168
mov [bx+10],ax
add si,2; 每次传一个字,不需要二重循环
add bx,16
loop s3
pop bx
mov cx,21
s4:
mov si,0
mov ax,[bx+5+si]; 传低位
mov dx,[bx+7+si]; 传高位
div word ptr [bx+10]
mov [bx+13],ax; 将商值传入对应内存单元
add bx,16
loop s4
pop bx
mov ax,4c00h
int 21h
codesg ends
end start
本次实验遇到了几个问题:
- 首先做本次实验,印象最深就是感觉寄存器不够用,不然一个循环就能搞定。但我写的这段代码也不够简洁,其实只要传输的数据大小一致就可以合并循环,因为可以共用一个偏移量,比如年份和收入都是4字节,就可以合并,同理雇员和人均收入都是两字节,也可以合并。
- 其次,本次实验我也犯了一些错误:
- mov 内存单元,内存单元 这种语法是错误,必须经过寄存器中介
- 还有 xxx segment:这里冒号是错误的,经常debug后错误,很难发现
- 不存在[ax+bx],[di+si] 这种寻址方式
- 一开始找table段我只是加上21*(4+4+2)=210个字节,但实际上数据段是16个字节一个小节分配的,不满16补16的
优化版:
assume cs:codesg,ss:stacksg
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
stacksg segment
dw 10 dup(0)
stacksg ends
codesg segment
start:
mov ax,data
mov ds,ax
mov ax,stacksg
mov ss,ax
mov bx,00e0h
push bx
mov cx,21
mov si,0
s1:
push cx
mov cx,2
mov di,0
s11:
mov ax,[si]
mov [bx+di],ax
mov ax,[84+si]
mov [bx+5+di],ax
add si,2
add di,2
loop s11
pop cx
add bx,16
loop s1
pop bx
; push bx
; mov cx,21
; mov si,0
; s2:
; push cx
; mov cx,2
; mov di,0
; s21:
; mov ax,[84+si]
; mov [bx+5+di],ax
; add si,2
; add di,2
; loop s21
; pop cx
; add bx,16
; loop s2
; pop bx
push bx
mov cx,21
mov si,0
s3:
mov ax,[168+si]
mov [bx+10],ax
add si,2
mov ax,[bx+5]
mov dx,[bx+7]
div word ptr [bx+10]
mov [bx+13],ax
add bx,16
loop s3
pop bx
; mov cx,21
; s4:
; mov ax,[bx+5]
; mov dx,[bx+7]
; div word ptr [bx+10]
; mov [bx+13],ax
; add bx,16
; loop s4
; pop bx
mov ax,4c00h
int 21h
codesg ends
end start

浙公网安备 33010602011771号