call $+5 pop eax

有如下指令:

1
2
3
地址					HEX数据					反汇编
00413930 E8 00000000 call 00413935 ; call $+5
00413935 58 pop eax

在进行汇编语言分析时,经常看到标题中的指令流(E800000000 58,第二条肯定是pop指令,但是目的寄存器不一定是eax),这是干什么的呢?

看起来貌似很神秘,其实结合前后代码的意图可以知道(进行调试),最终eax中存放的数据是0x00413935,而这个0x00413935,恰好就是pop eax指令的地址。因此实际上这条指令流的作用就是获取执行call $+5时,eip的值,也可以简单认为是获取当前指令地址。

这条指令流的原理也很简单,E8call指令中的相对跳转指令,它可以带一个dword参数,指明相对跳转的距离(E8 dword offset),计算方式很简单:下一条指令地址+ offset ,便是call指令的目的地。下一条指令地址就是pop eax的地址啦。

具体分析如下:

  1. CPU执行到E8 00000000时,eip中此时存放的是下一条指令的地址,也就是0x00413935
  2. CPU执行call指令,将call指令的下一条指令地址push到栈中(也就是0x00413935push到栈中,这是用于函数调用后返回的);
  3. E8指令进行解析,offset = 0,计算call指令目的跳转地址:下一条指令地址+ offseteip被存入0x00413935
  4. 跳转到0x00413935执行(实际就是call的下一条指令),执行pop eax,从上面的分析可知,此时栈顶的值是0x00413935,因此eax就被赋值0x00413935

可能有人可能想,获取当前指令地址,直接mov eax,eip不就行了么?答案是不行的,因为没有指令将eip作为源操作数的。


call $+5 pop eax
https://equinox-shame.github.io/2022/06/24/call $+5 pop eax/
作者
梓曰
发布于
2022年6月24日
许可协议