call $+5 pop eax
有如下指令:
1 |
|
在进行汇编语言分析时,经常看到标题中的指令流(E800000000 58
,第二条肯定是pop指令,但是目的寄存器不一定是eax
),这是干什么的呢?
看起来貌似很神秘,其实结合前后代码的意图可以知道(进行调试),最终eax
中存放的数据是0x00413935
,而这个0x00413935
,恰好就是pop eax
指令的地址。因此实际上这条指令流的作用就是获取执行call $+5
时,eip
的值,也可以简单认为是获取当前指令地址。
这条指令流的原理也很简单,E8
是call
指令中的相对跳转指令,它可以带一个dword
参数,指明相对跳转的距离(E8 dword offset
),计算方式很简单:下一条指令地址+ offset
,便是call指令的目的地。下一条指令地址就是pop eax
的地址啦。
具体分析如下:
CPU
执行到E8 00000000
时,eip
中此时存放的是下一条指令的地址,也就是0x00413935
;CPU
执行call
指令,将call
指令的下一条指令地址push
到栈中(也就是0x00413935
被push
到栈中,这是用于函数调用后返回的);- 对
E8
指令进行解析,offset = 0
,计算call
指令目的跳转地址:下一条指令地址+ offset
,eip
被存入0x00413935
; - 跳转到
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/