【问题标题】:how rsp is decremented in prologue on a X86-64 architecture在 X86-64 架构的序言中如何减少 rsp
【发布时间】:2014-08-18 14:34:50
【问题描述】:

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

【问题讨论】:

  • sub 8 很明显,因为在调用函数之前有两个 4 字节变量被压入堆栈(函数参数 ij)。
  • @barakmanos:不!在 64 位模式下,第一个参数在寄存器中传递。
  • @GerardBouchar:我无法复制您的程序集(Debian Wheezy 的 GCC 4.7.2-5)。请发布您的步骤以获取该程序集(完整的命令行)。

标签: c assembly disassembly function-calls


【解决方案1】:

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

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

至于您的第一个问题,您必须在没有优化的情况下进行编译。通过优化,您的所有功能都可以折叠成repz retq

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2021-07-30
    • 1970-01-01
    • 2022-08-24
    相关资源
    最近更新 更多