王爽老师的《汇编语言》是很好的一本汇编书,里面用通俗的例子讲清楚了很多让汇编初学者一直困惑的难点。比如寄存器分段寻址、各种寄存器的作用等等。
第八章是这本书的一个总结性的章节,后面也给出了一道比较综合的题目,完成这道题是对之前学习的检验,所以要继续往下学习,这道题是必须完成的。
经过半天时间的编程,本人也完成了这道综合的题目,在写代码的过程中,也搜索过一些参考的代码,但大多数网上的资料只是给出了代码,没有分析。所以我这里顺便给出一个分析的思路,
是对自己思路的总结,也希望能帮到其他一些要完成这道题目的朋友。下面就是完成这道题目的分析过程。
题目的要求:将一段内存里连续的数据,复制到另一段结构化了的内存里。具体的可以参看原书。
分析:
首先拿到了这道题目,就分析一下这两块数据地址的变化规律,毕竟我们的难点在于如何寻址嘛,这些地址的变化规律看一下,可以知道,第一块年数据地址之间相隔4,第二块收入数据地址之间相隔也是4,
第三块雇员数据地址之间相隔2,第一块数据和第二块数据地址之间相隔4*21=84=54H(因为一个年数据占了4个字节),第二块数据和第三块数据地址之间也是相隔84=54h(dword)。
如下图所示(懒得用工具作图了,直接用笔画了拍下来,多多包涵。。。):
图:原始数据地址规律
然后分析一下目的数据地址的规律,因为这块地址已经被格式化了,每一行占16个字节,然后有21行,行与行之间相差16,每一行的内容按字节数填就是了,很简单。如下图:
图:目的数据地址规律
有了上面的分析,我们来想想这块代码应该怎么写,一个最简单的办法是,一个个字节填,不用变址来寻,可行么?可行,但这样你可能要写21段差不多的代码。
看来王爽老师设计的这个题目,还是需要用到变址寻址,偷懒不得啊。。。
下面就想第二个办法,因为这些地址的变化都是有规律的,用变址也不难,再想想我们有什么资源,我们有几个变址寄存器:bx、bp、si、di。
再横向竖向的看看上面的图,哪里需要用到变址?如下图的1、2、3、4红笔处。
图:地址变化
那每一个红笔标注的地方我们都可以用到一个变址,那有没有必要呢,没有必要。我们尝试一下,先出动两个变址寄存器,bx和si。分别用于表示2和4红圈处。那我们就可以写出下面的代码来,
代码后有相应的注释,可以看看。
代码:
写了上面的代码之后,先编译一遍,通过了,然后再放脑子里跑一遍,这里发现有两个个地方不满足变化的规律,就是下面这两个地方:
1、
; 雇员数
mov ax, ds:[bx+168] ;****这里不满足
mov es:[si+0ah], ax
2、
; 算人均收入,这里小心高低位,
mov ax, ds:[bx+84]
mov dx, ds:[bx+86]
push cx ; 临时用一下cx,因为不可以 div ds:[bx+168]
mov cx, ds:[bx+168] ;*****这里同上,也不满足
div cx
pop cx
mov es:[si+0dh], ax
第一次bx为0的时候,是正确的,但第二次bx加了4之后,[bx+168]就变成了172了,正确的应该是170,所以这里是不满足的。那怎么办呢?
不着急,我们还有两个变址寄存器没出动呢,那我们现在就再出动 di 这个变址寄存器,来表示红笔3处的变址。上面两个不满足的地方也修改如下:
1、
; 雇员数
mov ax, ds:[di+168] ;****修改这里
mov es:[si+0ah], ax
2、
; 算人均收入,这里小心高低位,
mov ax, ds:[bx+84]
mov dx, ds:[bx+86]
push cx ; 临时用一下cx,因为不可以 div ds:[bx+168]
mov cx, ds:[di+168] ;*****也修改这里
div cx
pop cx
mov es:[si+0dh], ax
3、
; di还要记住在最后加上2
add si, 16
add bx, 4
add di, 2 ; 这里记住要加上2
loop s
做了上面这三步修改,就基本完成了,再在脑子里过一遍,好像也没什么问题了,那就打开DOS窗口,启动我们的debug大炮,一步步的跟踪,循环的第一次到第三次是比较关键的,需要慢慢调试,
调试到第四第五次、甚至21次都调试完了,我们发现,程序已经完成了。。。
以上就是我的分析解题思路,希望对你也有一定帮助。下面就贴出最终完成的代码: