这个简单(反汇编)C程序中的堆栈指针是怎么回事?

时间:2016-06-26 14:31:52

标签: c assembly x86

通过学习汇编语言/计算机体系结构的更多信息,我编写了以下C代码:

int my_caller() {
    int a = my_callee(0xbaba);
    return a;
}

int my_callee(int a) {
    return a;
}

这会将(在我的机器上;添加一些评论)拆解为以下内容:

; my_caller function
push ebp
mov ebp,esp
sub esp,byte +0x18
sub esp,byte +0xc
push dword 0xbaba
call dword 0x1e
add esp,byte +0x10
mov [ebp-0xc],eax
mov eax,[ebp-0xc]
leave
ret

; my_callee function
push ebp
mov ebp,esp
mov eax,[ebp+0x8]
pop ebp
ret

关于espmy_caller的处理:

  1. 为什么我们sub esp乘以0x18然后是0xc;为什么不只是0x24的一个子?
  2. my_callee返回后,add esp,byte 0x10有什么意义?无论如何,leave指令将使用隐式mov esp,ebp
  3. 来取消此操作

    感谢。

1 个答案:

答案 0 :(得分:2)

您告诉编译器您希望快速编译,而不是编写好的代码,并使代码很容易与gdb之类的调试器进行交互。在-O0模式下,gcc在同一函数的不同部分之间没有太多优化,因此add esp, 0x10在调用后弹出堆栈,然后单独leave

-O0非常嘈杂(充满了商店/重新加载),所以读作人类很糟糕。

您可以更好地查看带有几个int args并返回int的函数。您可以在函数上使用__attribute__((noinline))来阻止它们进行内联。

例如,查看Godbolt compiler explorer上的简单函数。另请参阅标记wiki。