如何在X86-64架构的序言中减少rsp

Ger*_*har 5 c assembly function-calls disassembly

我试图理解如何在C中调用函数.当我反汇编这段代码(gcc -gdb;我在Linux上使用i5-3320M)来获取函数的序幕时toto:

void nop(){return ;}

void toto(int i, int j)
{
return;
}

int main(int argc, char **argv)
{
  int i = 1;
  int* pt;
  i = 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到了序幕:

   0x0000000000400523 <+0>: push   %rbp
   0x0000000000400524 <+1>: mov    %rsp,%rbp
   0x0000000000400527 <+4>: sub    $0x8,%rsp
Run Code Online (Sandbox Code Playgroud)

在这里我不明白为什么rsp会减少8,因为我没有使用局部变量toto.而且,如果我使用局部变量:

void toto(int i, int j)
{
    int i=1
    return;
}
Run Code Online (Sandbox Code Playgroud)

我得到以下序言:

   0x0000000000400523 <+0>: push   %rbp
   0x0000000000400524 <+1>: mov    %rsp,%rbp
   0x0000000000400527 <+4>: sub    $0x18,%rsp
Run Code Online (Sandbox Code Playgroud)

在这里,我不明白为什么rsp减少0x18(24字节).我希望有16个字节的东西,因为我已经有了8的神秘偏移量,而且我需要4个字节用于int.但我的架构是64位,堆栈中的一个字不能少于8个字节,所以8 + 8 = 16.

ach*_*ach 3

x86_64 ABI要求输入函数时%rsp始终为 16 的倍数。因此,在 后push %rbp%rsp必须减去 0x8、0x18、0x28 等值。

更新。对不起所有投票的人,我欺骗了你们。很容易看出,每个push %rbp%总是与给出 0x10 字节的callor配对callq,因此减去的额外值%rsp也必须是 0x10 的倍数。

至于你的第一个问题,你必须在没有优化的情况下进行编译。通过优化,您的所有功能都将简化为repz retq.