我正在拆解一些用GCC编译的x86汇编代码以进行赋值。
在调用函数之前,我有:
$esp = 0xffffdbd0
在被调用函数的第一行(甚至在push
之前)设置断点:
$esp = 0xffffdbcc
推后:
$esp = 0xffffdbc8
那么为什么$esp
会改变呢?从理论上讲,只是去一个函数不应该改变堆栈指针,然后它会在push
之后改变?发生了什么事?
我有一个猜测,它与对齐有关,并且在某种程度上,使用call
和push
汇编指令在我背后进行某种对齐。但这是一个猜测;我不知道。
知道澄清的人可以吗?
答案 0 :(得分:4)
执行CALL
指令时,紧跟CALL
之后的指令地址被压入堆栈。这样,当您执行RET
指令时,程序可以跳回到正确的地址并继续执行指令。将此地址压入堆栈意味着您可以嵌套CALL
并且在每个RET
返回正确的地址时没有问题。
由于这是一个32位系统,因此将4个字节压入堆栈:
0xffffdbd0 - 0xffffdbcc = 0x4
答案 1 :(得分:3)
call
指令在跳转到目标位置之前将第一条指令的地址推送到堆栈。这样,ret
知道函数返回后的去向。
答案 2 :(得分:2)
你的假设
理论上,只是去一个函数不应该改变堆栈 指针
是完全错误的。转到一个函数就是这样:它改变了堆栈指针,特别是它推送了返回地址。在x86中(以及几乎所有其他拱门中)“推送”总是意味着隐式递减堆栈指针并存储要在其上推送的值。