王爽《汇编语言》实验8:分析一个奇怪的程序

时间:2021-10-21 19:22:29
;分析下面的程序,在运行前仔细思考:这个程序可以正确的返回马?运行后在思考:为什么是这样的结果?
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


程序执行流程:


start: mov ax,0开始执行,到mov cs:[di],ax,就把s2:处jmp short s1拷贝到s处,dubug 命令jmp short s1,共占两个字节,恰好占据原本2个nop的内存空间(nop指令占据一个字节)


jmp short s1 在s2处,可以计算一下需要往上编译10个字节(3(jmp short s1)+3*2(mov ax,0)+2(int 21H)),debug可以看到机器码为EBF6,F6是补码,转换一下即10,也即是向上偏移10个字节,这样的话s:处的2个nop的代码修改成EBF6。

程序接着往下运行,跑到s0:jmp short s,这样又s:处,执行EBF6,即往上偏移10字节,计算一下就知道,IP这个时候指向0,跑到codesg段起始位置,即执行mov ax,4c00H;int 21H,也就是返回操作。



;AX=0000  BX=0000  CX=0023  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000
;DS=0BA7  ES=0BA7  SS=0BB7  CS=0BB7  IP=0005   NV UP EI PL NZ NA PO NC
;0BB7:0005 B80000        MOV     AX,0000

assume cs:codeseg


codeseg segment

 mov ax, 4c00h ;IP = 0000 E8004C

 int 21h             ;IP = 0003 CD21

start:    

 mov ax, 0  ;程序入口,IP = 0005 B80000


s:        nop ;IP = 0008 80

 nop ;IP = 0009 90

 mov di, offset s   ;IP = 000A  机器码为BF0800      mov di, 0008

 mov si, offset s2 ;IP = 000D  机器码为BE20000    mov si, 0020

 mov ax, cs:[si]     ;IP = 0010  机器码为8B04          将CS:0020内容传给AX 

 mov cs:[di], ax    ;IP = 0013 

     ;这4条指令是将s2处指令(EBF6)传到CS:0008处,正好覆盖了两个NOP字节

     ;CPU执行到这里,CS:0008 0009的内容是s2的偏移地址,为EBF6.继续往下执行


s0:      jmp short s       ;IP = 0016  机器码为EBF0  (IP位移) = 0008H - 0018H = -16D(-10H)

             ;跳到CS:0008(s处)执行.由于CS:0008处内容为EBF6,故跳转后就执行EBF6(s2处)

     ;EBF6执行后,IP = 000A.但EBF6作用为将IP向前移10个字节,即跳转到mov ax,4c00h处

     

s1:     mov ax, 0  ;IP = 0018

 int 21h      ;IP = 000B  机器码为 CD21,占2个字节

 mov ax, 0  ;IP = 000C


s2:     jmp short s1 ; IP = 0020  (IP位移) = 0018H - 0022H = -10D 机器码为EBF6

 nop              ; IP = 0022


codeseg ends

end start   ;end伪指令通知汇编程序的结束,start标号说明程序从标号start处开始


参考资料:

http://blog.chinaunix.net/uid-10537496-id-462605.html

http://blog.csdn.net/superway117/article/details/1362863