关于汇编语言(第3版)书中实验七:
寻址方式在结构化数据访问中的应用
问题:
Power idea公司从1975年成立一直到1978年的基本情况如下:
年份 收入(千美元) 雇员(人) 人均收入(千美元)
1975 16 3 ?
1976 22 7 ?
1977 382 9 ?
1978 1356 13 ?
下面的程序中,已经定义好了这些数据:
assume cs:codesg
datasg segment
db ‘1975’,‘1976’,‘1977’,‘1978’
dd 16,22,382,1356
dw 3,7,9,13
datasg ends
table segment
db 21 dup('year summ ne ?? ')
table ends
编程,将data段中的数据按如下格式写入到table段中,并计算21年中的人均收入(取整),结果也按照下面的格式保存在table段中。
上述题目原文链接:https://blog.csdn.net/chczy1/article/details/80374023
思想:
db是声明以字节形式存储在内存中,在汇编编译软件中反映出来就是占两个位置00(这里特殊的是存的是字符,即一个字符是一个字节,所以一个年份是占四个字节);
dd是声明以两个字(四个字节)的形式存储在内存,反映在软件就是占四个位置00-00-00-00
dw是声明以一个字(两个字节)的形式存储在内存,反映在软件中就是占00-00
整体思路:题目是将书中内容数据按格式写入到table段,并计算21年中的人均收入(取整),结果也按格式保存在table段。
ds 1.所以table段作为整体,所有的东西都要放进table段,所以table可以绑定ds寄存器,存入ds段来作为table段。
es 2.由于内存中已经定义了三种不同的数据,但是都放在了data段,所以data段要绑定一个寄存器来存取数据到table段中,之前table段已经绑定了ds段,所以将data段绑定es段,通过变换地址来取三种定义的不同的数据,
1.年份地址0-f
2.公司对应年份的总收入10-1f
3.公司对应年份的雇员人数20-27
3.放的地方确定了,拿数据的地方也确定了,接下来是怎么取数据的问题,首先先放在table段的年份,占四个字节,我们可以选择先把年份放完,这就需要进行四次行变化,然后再放收入,雇员数等,但有个麻烦就是,我们还得在每一行的最后算出来人均收入,若是按之前说到的方法放置数据的话,我们要写列变化的代码,列变化的代码,最后还得再写单独一行的进行计算人均收入,这就麻烦了。在此我们采用另一种方法,即是单独先放置一行的数据,然后进行计算一行的人均收入,然后我们再进行下一行的相同操作。这样看来,只要写好一行的具体操作即可,其他三行可以用循环来执行,这就大大减小了复杂度。那具体一行的操作怎么做到呢?
首先
先放年份,通过es寄存器来取放入ds即可,对于放第一个年份(在内存中是0-3的内存(在DOSbox即是占了八个0),执行完该步骤,下一步是进行列变化,然后进行放入收入操作,唯一与前一个步骤不同的就是进行列变化,那怎么列变化呢,这里我们可以发现每一行有固定同样的列变化,所以我们只需要在行地址首位时再加上固定的常数转到该行固定的位置即可(这里需要注意一点就是我们的内存是依次递增的,并没有我们现在所说的有行,有列,只是我们可以将内存中一个范围的内存看作是一行,这样就有助于我们理解问题了)这就是列变化,然后就是人均收入的计算,这个只需要我们把刚才对应放在table中存的收入和人数取出进行除法即可,唯独需要注意的是这个除法通过dev指令来完成,当然也需要注意它的特性,即进行16位除法,和进行32位出发(一个字节八个位),我们要进行的除法是32位除法(因为年收入有四个字节)然后被除数低位放在ax中,高位放在dx中,算出来的商放在ax中,余数放在dx中,题目告诉取整,所以只需要取出ax的值就行了。
完成一行的具体操作之后,进行下一行的同样操作,但是在同样的操作之前,还有一个问题就是怎么用es取data段中的数据呢,之前说过一个问题就是真正的内存是递增的,但我们可以将一段内存看作是一行来操作,那怎么来每次移动固定的字节数来改变取的数据呢,我们发现取年份和取年收入都是四个字节的取出,所以我们可以用一个si寄存器来存储移动的列地址来取这两种数据(变化是同步的),然后用bi来存储雇员数的列的移动数据,这样就可以实现每换一行都可以改变取的数据了。具体思想就是这些,接下来是具体代码实现。
附注:(还有一种方法就是实现循环怎么实现,由于我们要进行行和列的变化,所以需要用到两个循环,一个行变化,一个列变化,如果用到loop指令的话,就得用到cx,两个循环用到两个loop,则需要用到两次cx,为了避免行变化内部列变化是cx的改变影响到行变化的cx,我们需要将行变化的cx在列变化之前保护起来,所以这里我们还需要用到栈来保护现场,等到一行的列变化执行完后,再将栈中保护的行变化次数的cx取出,然后下一次列变化又继续存入栈中。)
循环的行变化用bx实现。
代码如下:
assume cs:code
data segment
db '1975','1976','1977','1998'
dd 16,22,382,1356
dw 3,7,9,13
data ends
table segment
db 4 dup('year summ ne ??')
table ends
code segment
start: mov ax,table
mov ds,ax
mov ax,data
mov es,ax
mov si,0
mov di,32
mov cx,4
mov bx,0
s:
mov ax,es:[si]
mov ds:[bx+0],ax
mov ax,es:[si+2]
mov ds:[bx+2],ax
mov ax,es:[si+16]
mov ds:[bx+5],ax
mov ax,es:[si+18]
mov ds:[bx+7],ax
mov ax,es:[di]
mov ds:[bx+10],ax
mov dx,es:[si+18]
mov ax,es:[si+16]
div word ptr es:[di]
mov ds:[bx+13],ax
add bx,16
add si,4
add di,2
loop s
mov ax,4c00h
int 21h
code ends
end start
新手所写,如有不足或者冒犯之处请多多包涵,感谢!