关于jmp相对跳的一道程序分析

关于jmp相对跳的一道程序分析

夜深人静,嘿嘿   只有这个时候才有时间静下来看点东西

前几天在看 16 位汇编语言程序设计   王爽 老师写的   写得真的很好   呵呵   不是卖广告哈 资源共享嘛

遇到一个问题   通过这个问题发现能深刻理解到 jmp 指令很具内涵的一些内容

甚欢 乃著此文以记之

 

程序如下:

assume cs:codesg

codesg segment

   mov ax, 4c 00h

   int 21h

start :

   mov ax,0

s:

   nop

   nop

   mov di,offset s 这里应该是计算 s 对于 segment 处的偏移量,赋值给 di

   mov si,offset s2 计算 s2 对于 segment 处的偏移,保存到 si

   mov ax , cs:[si]  s 处的 1 个字节指令内容读入 ax (注意,基址是 cs ~ 不是 ds

   mov cs:[di],ax   ax 内容写到 s 处,也就是填充上边那 2 nop

s0:

   jmp short s ;跳到 s ,那么这个时候位于 s 处指令应该是 jmp s1 ;接着执行应该是 mov ax 0 然后 int 21

s1:

   mov ax,0

   int 21h  

   mov ax,0

s2: 

   jmp short s1

   nop

codesg ends

end start

 

 

结果发现我推测的跟执行的内容完全不一样 …… 晕厥 ING~

又过了一天 一觉醒来想了想这个结果 哈哈 恍然大悟

 

书上的例子用的是 windows 自带的 debug 调试 …… 我也只会用这个了 …… windbg 太麻烦 od 好像只能开 32 位的

只能截图看了

ab.bmp

jmp 指令在被编译器编译的时候会自动计算跳转时指针与目的地址的偏移量 然后通过加减 ip 这个数值实现跳转的

也就是说 jmp s 这指令实现的是相对位移跳转,跳到哪那是编译器编译的时候就计算好的了

我们来看看 1814 0016 这个地方的 jmp 指令 EBF0 这个指令对应的汇编语句应该是 jmp s

S 是在 1814 0008 所以反编译的结果是 jmp 0008  没错 跟我们的语句没出入

那么我们可以看看机器码 BEF0  BE jmp 指令 F0 代表相对位移 以补码形式保存

那么我们计算下发现 F0 对应的 10 进制是 -16 也就是说要往后跳 16 个字节(注意是字节, 8bit 一个字节哦 ~

1814 0016 这个是我们执行到 jmp cs ip 的地址,也就是取指令的地址

注意这个时候我们已经取出 jmp s 这个指令了 那么 IP 指针应该 +2 指向 1814 0018 这个位置了

往后跳 16 个字节 1814 0018 – 10 10 进制就是 16 咯) = 1814 0008

应该是跳到 0008 这个位置上了 正好就是 s 对应的位置

那么我们看看 1814 0020 这个指令 EBF 6   F 6 是跳转的相对位移 补码形式存放 换算成 10 进制就是 -10

想象下当程序执行到 s0 那个时候 s 处的那 2 nop 指令已经被填充成 EBF6   根据相对位移的计算

  这个时候程序运行的步骤应该是

通过 jmp s 跳转到 1814 0008 地址(这个时候下一个指令对应的机器码是 BEF0

取出下一个指令 IP+2  这个时候 IP 指向 1814 000a

执行 BEF6 这个指令(向后跳 10 个字节)

也就是应该跳到 1814 000a – a 10 16 进制表示) = 1814 0000

也就是说这个时候 jmp 指令应该是 jmp 0000 跳到 segment 开始处而不是跳到 s1 处了

接着应该是执行

   mov ax, 4c 00h

   int 21h

实际调试的结果也是这样的

如下图示

 

sa.bmp

看到没   执行 jmp 0008 也就是 jmp s 以后然后就是跳到 1814 0000 而不是跳到 s1 对应的那个偏移处

接着就是跟我们想的一样 执行了 mov ax 4c 00h 然后就 int 21h

aabb.bmp

 

也就是说我们 jmp 的地址记录的是相对偏移量 这个程序也说明了 jmp 的地址是在运行时计算出来的而不是编译器一开始就硬编码进去的

不过当然也有硬编码进去的跳转指令啦 ~~ 好像是 jmp far 地址吧 忘了的说 呵呵  

只不过小小阐明下 jmp 相对跳的执行流程和细节部分

这样也有个小小启示就是以后用相对跳的时候小心咯 貌似 shellcode 编写或者改内核代码的时候可以注意下 呵呵

跳转的相对地址最好计算出来表直接就来个偏移   一不小心机子就当掉了   哇咔咔 ~

 

你可能感兴趣的:(关于jmp相对跳的一道程序分析)