汇编语言(王爽第三版)实验8 分析一个奇怪的程序

实验8 分析一个奇怪的程序

 题目:分析下面程序,在运行前思考:这个程序可以正确返回吗?

运行后思考:为什么是这样的结果?

通过这个程序加深对相关内容的理解.

代码如下:

assume cs:codesg

codesg segment

        mov ax, 4c00H

        int 21H

   

start:  mov ax, 0

    s:  nop

        nop

       

        mov di, offset s

        mov si, offset s2

        mov ax, cs:[si]

        mov cs:[di], ax

       

    s0: jmp short s

 

    s1: mov ax, 0

        int 21H

        mov ax, 0

       

    s2: jmp short s1

        nop

       

codesg ends

end start

       程序分析:

1. 看懂程序从何处入口?有start标号的地方(当然是和end start匹配的)。

2. s:标号语句nop作用,在运行时在代码段分配一个字节的空间。(机器码90,在内存中就是90H),它的作用是方便在程序运行时代码段分配空间,在此写入代码(实际是机器码)。执行二次nop后,在cs段中分配了2个字节空间,内容都是90H。(这个空间目前是空的,CPU遇到这2个字节,就不执行,顺序执行下面的机器码了。)

3.       mov di, offset s        ;将s标号处的偏移地址赋值给di,di指向了s

        mov si, offset s2       ;将s2标号处的偏移地址赋值给si,si指向了s2

        mov ax, cs:[si]         ;将cs:si指向的内存单元的内容赋值给ax(内容为机器码)

        mov cs:[di], ax         ;将机器码赋值给s标号处

       这四条语句的作用是将s2处的机器码赋值给s标号开始的2个连续空间中(也就是说将jmp short s1这个指令的机器码这个内容赋值给了s标号后面2个字节)。在汇编语言层面上,我们不必去关心offset s和offset s2的值他们到底是多少,但我们要明白,他们代表了标号开始处的ip值,他们是偏移地址值(也就是指针)。

       (这里我们要搞清楚赋值的是机器码这个内容,而不是代码:jmp short s1,千万不要凭字面意思去生硬的将代码搬到s标号处。)    

       jmp short s1机器码到底是多少?(理解jmp指令偏移的是相对位移),它应该是从si标号偏移地址- jmp指令后的第一个字节偏移地址。我们所说的偏移地址就是ip。我们计算下。mov ax,0 ==3个字节; int 21H ==2个字节;mov ax,0 ==3个字节;jmp short s1==2字节,那么我们可以计算出此代码位移的偏移量是10个字节,也就是说IP变化了10,由于s1处标号(IP值)-s2标号后的第一个字节地址(ip值)是-10,转换成16进制(补码方式存储)00001010(源码10)>> 11110101(取反)>>11110110(加一)==F6H;故这个机器代码是:EBF6,(EB代表jmp指令,F6代表了自此偏移地址开始,向前偏移10个字节)。

       那么在标号S处存储的是EBF6这二个字节。它就代表了一个jmp指令,无条件向前移动10个字节的内存单元处,然后执行此处的代码。

       程序一直自顶向下执行着,直到遇到S0标号。

       s0: jmp short s 程序运行到此处。表示跳转到s标号处,此处有代码是EBF6,执行它,向前偏移10个字节,正好是codesg segment(s标号占2个字节(此处也是jmp指令,占2个字节,jmp指令后面的第一个字节地址,也就是从这个地址开始偏移,偏移量是10,简单画图);mov ax,0 ==3byte; int 21H==2byte; mov ax 4c00H==3byte)也就是程序从mov ax 4c00H开始执行了,直到int 21H正常结束程序。

       测试程序:我们编译连接后,测试这个程序。

-d cs:0             ;执行到最后时,看看代码段内存的变化

0B65:0000  B8 00 4C CD 21 B8 00 00-EB F6 BF 08 00 BE 20 00   ..L.!........

0B65:0010  2E 8B 04 2E 89 05 EB F0-B8 00 00 CD 21 B8 00 00   ............!

0B65:0020  EB F6 90

       总结:

       1. jmp XXXX,我们在汇编语言中,你不必去考虑位移的问题,那是编译器的事情,要不我们累死啦。它自动计算位移(偏移量)。

       2. 如果涉及到了jmp指令的机器码问题。我们必须考虑位移的问题。

       3. jmp指令的位移的计算方式,在机器码中,位移是按照补码方式存储的;也就是说向下移动EB代码后面是正整数(正数,补码是原码);如果是向上移动EB代码后面是负整数(原码取反+1)。EB代码后边跟随的数值,是jmp的偏移位移,这个位移是按照字节作为移动单位的。

       4. 我们发现,标号s1及以后的汇编代码,程序就没有执行。为什么?使用jmp跳转到前边了。虽然没有执行,但是在编译过程中,它们的机器码也被编译并存储在了代码段了。

      

 

posted @ 2017-05-21 09:00  筑基2017  阅读(2557)  评论(2编辑  收藏  举报