我试图了解如何在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;
}

我得到了序幕:
   0x0000000000400523 <+0>: push   %rbp
   0x0000000000400524 <+1>: mov    %rsp,%rbp
   0x0000000000400527 <+4>: sub    $0x8,%rsp

在这里,我不明白为什么rsp减少了8,因为我没有在toto中使用局部变量。此外,如果我确实使用局部变量:
void toto(int i, int j)
{
    int i=1
    return;
}

我得到以下序言:
   0x0000000000400523 <+0>: push   %rbp
   0x0000000000400524 <+1>: mov    %rsp,%rbp
   0x0000000000400527 <+4>: sub    $0x18,%rsp

在这里,我不明白为什么rsp会递减0x18(24个字节)。我期望有16个字节,因为我已经有一个神秘的偏移量8,再加上我需要4个字节的int。但是我的体系结构是64位,堆栈中的一个字不能少于8个字节,因此8 + 8 = 16。

最佳答案

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

更新。抱歉,每个人都对此表示支持,我欺骗了您。可以很容易地看出,每个push %rbp%始终与callcallq配对,后者给出0x10字节,因此从%rsp减去的额外值也必须是0x10的倍数。

关于第一个问题,您必须在没有优化的情况下进行编译。通过优化,您的所有函数都折叠为repz retq

关于c - rsp如何在X86-64架构的序言中递减,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25365893/

10-09 01:23