实验7
题目要求
工具
dosbox+masm5.0
问题分析
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, 475, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
1.
年份 总收入 人数 人均收入 分别为
4 4 2 2 字节,中间用空格隔开 由于在定义table的时候已经给好了格,所以之后没有必要再循环中添加空格多此一举
2.循环问题
一共21组数据,外循环21次,年份总收入都为4字节,内循环4次。用al执行
人数 人均为2字节 直接放在外循环里以字传输
由于嵌套循环 引入栈
stack segment
dw 2 dup (0)
stack ends
3.偏移地址
每个年份4B,21个数据共84 = 54H
所以收入的偏移地址开始为54h 同样的54H+54H=A8H
所以偏移地址分别为 0H 54H A8H
代码
assume cs:codeseg,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, 475, 778, 1001, 1442, 2258, 2793, 4037, 5635, 8226
dw 11542, 14430, 15257, 17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
stack segment
DW 2 dup (0)
stack ends
codeseg segment
start:
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
MOV AX,STACK
MOV SS,AX
MOV SP,4
mov bx,0
mov di,0
mov cx,21
mov si,0
s:
push cx ;控制外循环cx的值
mov cx,4h
push di ;在s2循环中,di控制一行数据写到第九个字节 循环结束永远为4
mov di,0 ;所以在总人数的时候需要恢复其值
s2:
mov al,ds:[si]
mov es:[bx+di],al ;年份
mov al,ds:[si+54h]
mov es:[bx+di+5H],al ;收入
inc si
inc di
loop s2
pop di
mov ax,ds:[di+0a8h]
mov es:[bx].0ah,ax ;总人数
mov ax,es:[bx+5h]
mov dx,es:[bx+7h]
div word ptr es:[bx+0ah] ;人均
mov es:[bx].0dh,ax
add bx,10h
add di,2h
pop cx
LOOP S
mov ax,4c00h
int 21h
codeseg ends
end start
结果
一些问题
1.bx应该用来控制纵向的值 而不是依照前面学习的经验横向操作
因为si+di是非法操作,所以就没法定位table(ES)中某排某列的位置
2.栈的操作 在改变值前push 需要用到再pop 利用后进先出的特性不要乱了顺序
3.写代码前认真思考循环结束后 一个值是否还是所需要的结果,虽然通过debug能够发现,但还是应该提前发现减少时间为好
比如di的值 整个循环中di控制ds中总人数据,而在S2循环中控制的是es写入到第几个字节中,循环结束为4
mov es:[BX].0AH,AX这段为什么不用si控制呢
因为ds中 总人数只占2个字节,用si控制第二次就出现问题4+A4 8+A4比数据实际所在位置多了两个字节
这里就要清楚分辨寄存器在某个循环里的作用 万不可混淆
其实后面的传人数本来想用传字节 因为被必须用嵌套循环的思维束缚了(刚学完)
后面也是直接改成直接传递一个字
那么问题就在这了 其实4个字节也不多 为什么非要按字节传4次呢
直接两个字各传一次不就好了
不过巩固了栈的用法吧