为什么在64位架构上对齐是16字节?

时间:2011-04-04 11:54:37

标签: c alignment x86-64

(gdb) disas foo
Dump of assembler code for function foo:
0x00000000004004a8 <foo+0>: push   %rbp
0x00000000004004a9 <foo+1>: mov    %rsp,%rbp
0x00000000004004ac <foo+4>: mov    0x13c(%rip),%eax        # 0x4005ee <__dso_handle+30>
0x00000000004004b2 <foo+10>:    mov    %eax,-0x10(%rbp)
0x00000000004004b5 <foo+13>:    lea    -0x10(%rbp),%rax
0x00000000004004b9 <foo+17>:    add    $0x18,%rax
0x00000000004004bd <foo+21>:    mov    %rax,%rdx
0x00000000004004c0 <foo+24>:    mov    $0x400498,%eax
0x00000000004004c5 <foo+29>:    mov    %eax,(%rdx)
0x00000000004004c7 <foo+31>:    leaveq 
0x00000000004004c8 <foo+32>:    retq   
(gdb) l foo
8   void foo() {
9       char overme[4] = "WOW";
10      *(int*)(overme+24) = (int)bad;
11  }

为什么不只是8个字节?

2 个答案:

答案 0 :(得分:10)

gcc没有将此空间“分配”给变量。相反,x86_64 abi要求堆栈指针在函数调用时始终为16字节对齐,以防被调用者使用向量化SSE数学运算。这是一个非常愚蠢和浪费的要求(如果需要,被调用者应确保对齐),但这是标准,gcc遵循标准。您可以使用-mpreferred-stack-boundary=3(8字节对齐,64位的最小值)修复它。

答案 1 :(得分:0)

它是8个字节,而不是16. LEA指令没有显示任何对齐相关,-0x10只是应用于RBP寄存器值的偏移量。可能生成一个小型本地数组的地址。如果代码生成器使用任何SIMD指令,那么16可能是相关的。在双线问题中没有一个是可见的。