【发布时间】:2014-04-11 15:27:00
【问题描述】:
所以我有这个示例 C 程序。
int worship(long john)
{
return 0 * john;
}
int main()
{
return worship(666);
}
程序集看起来(基本上)是这样的:
worship(long):
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
movl $0, %eax
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
movl $666, %edi
call worship(long)
popq %rbp
ret
我在阅读堆栈粉碎时遇到了这个问题。在程序集worship(long): 部分,它说movq %rdi, -8(%rbp) 我希望它使用pushq,基于我到目前为止所读的所有内容。这是 GCC 将参数推送到堆栈上的新方式吗?如果是,我可以使用编译器标志来切换它吗?
【问题讨论】:
-
哦,也许这是一种优化。据我所知 movq 不会改变堆栈指针的值
-
在 x86_64 中寄存器的数量翻了一番,所以calling convention 使用寄存器作为第一个参数,而不是堆栈
-
这是一个基本的代码优化。 PUSH 指令很笨拙,因为它进行两次 修改,它写入[ESP] 并 修改ESP 寄存器。这可以防止乱序执行,这是 MOV 没有的问题。
-
如果您使用的是 Linux,那么前 6 个整数参数将在 RDI、RSI、RDX、RCX、R8 和 R9 中传递。所以这就是函数中有 RDI 的原因。传递 6 个参数,你会看到它使用了 R8 和 R9,这是新的寄存器之一。尝试传递超过 7 个参数,然后将使用堆栈
标签: c gcc assembly compilation stack