gcc 4.7.2在Debian哮喘病中没有';不要总是正确对齐堆栈指针。这是虫子吗?

gcc 4.7.2在Debian哮喘病中没有';不要总是正确对齐堆栈指针。这是虫子吗?,c,gcc,calling-convention,C,Gcc,Calling Convention,在阅读示例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, %ea

在阅读示例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”)。
在系统V ABI,PAR。3.2.2,我读到:“值(%rsp− 8) 当控制转移到功能入口点时,始终是16的倍数。“
有人可以帮助我理解为什么gcc不把
subq$16,%rsp

先谢谢你

编辑: 我忘了提到我的操作系统和编译器版本:
Debian wheezy,gcc 4.7.2

假设在输入
func
时堆栈指针是16字节对齐的,那么

pushq %rbp              ; <- 8 bytes
movq  %rsp, %rbp
subq  $8, %rsp          ; <- 8 bytes

pushq%rbp;可能是因为让您到达那里的
callfunc
指令已经将某些内容推到了堆栈上,就像
pushq%rbp
一样。在调用
之前,可能还有其他指令推送参数等等……可能是16位?如中所示,16位的倍数,表示按字对齐(两个字节)。根据我的经验,堆栈指针必须是这样的。。。即使奇数值是正确的@洛尼克斯。否。对齐以字节为单位。您可以为编译器指定一个首选值(请参阅:或)。如果您尝试反汇编其他代码,您将注意到堆栈指针总是16字节的倍数。“我不明白为什么在我发布的简单示例中这不是真的。@特瓦尔伯格。否。main()的汇编程序列表显示堆栈指针在调用func()之前是16字节对齐的:“pushq%rbp”、“movq%rsp%rbp”、“movl$1、%edi”、“call func”。我假设在main()启动时rsp正确对齐(16字节)。@Burr。否:“call func”指令将rip(8字节)推送到堆栈上,然后“pushq%rbp”使rsp 16字节对齐。但下一个“subq$8,%rsp”使rsp没有正确对齐。尝试在foo()中添加“putchar('A');”,func()将更正为我现在看到的“subq$16,%rsp”。我认为现在发生的事情是,由于编译器知道
foo()
的实现,并且它是一个noop,所以它不需要考虑堆栈对齐。如果在另一个翻译单元中实现了
foo()
,您将看到预期的堆栈对齐。我不知道为什么即使在“非优化”代码中也会出现这种情况。