【发布时间】:2014-04-08 15:24:38
【问题描述】:
偶然地,在阅读示例 C 程序的汇编程序列表时,我注意到在调用函数 foo 之前堆栈指针不是 16 位对齐的:
void foo() { }
int func(int p) { foo(); return p; }
int main() { return func(1); }
func:
pushq %rbp
movq %rsp, %rbp
subq $8, %rsp ; See here
movl %edi, -4(%rbp)
movl $0, %eax
call foo
movl -4(%rbp), %eax
leave
ret
subq $8, %rsp 指令使 RSP 在调用 foo 之前未对齐(它应该是“subq $16, %rsp”)。
在 System V ABI 中,par。 3.2.2,我读到:“当控制转移到函数入口点时,值 (%rsp - 8) 始终是 16 的倍数”。
有人可以帮我理解为什么 gcc 不放 subq $16, %rsp 吗?
提前谢谢你。
编辑:
我忘了提及我的操作系统和编译器版本:
Debian wheezy,gcc 4.7.2
【问题讨论】:
-
也许是因为让你到达那里的
call func指令已经将一些东西压入了堆栈,pushq %rbp也是如此。在call之前可能还有其他指令推送参数等... -
也许它应该是 16 位?如,16 位的倍数,表示按字对齐(两个字节)。根据我的经验,这就是堆栈指针必须......甚至。奇数就出来了!
-
@lornix。编号对齐以字节为单位。您可以为编译器指定首选值(请参阅:msdn.microsoft.com/en-us/library/83ythb65.aspx 或 gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html)。如果您尝试反汇编其他代码,您会注意到堆栈指针始终是 16 字节的倍数。我不明白为什么在我发布的简单示例中这是不正确的。
-
@twalberg。不。 main() 的汇编程序列表显示堆栈指针在调用 func() 之前是 16 字节对齐的:“pushq %rbp”、“movq %rsp, %rbp”、“movl $1, %edi”、“call func” .我假设 main() 启动时 rsp 正确(16 字节)对齐。
标签: c gcc calling-convention