x86-32与x64汇编中固定大小缓冲区栈分配差异(GCC未优化C)
x64与x86-32汇编栈空间分配差异的原因
问题背景
同样的未优化C代码(定义500字节char buffer[500]),用GCC编译的x64汇编会为缓冲区分配额外空间,而x86-32汇编仅分配准确的500字节,仅架构不同,差异原因如下:
我的C代码
#include <stdio.h> #include <string.h> int main (int argc, char** argv){ char buffer[500]; strcpy(buffer, argv[1]); return 0; }
编译后的x64汇编片段
0x0000000000001139 <+0>: push %rbp 0x000000000000113a <+1>: mov %rsp,%rbp 0x000000000000113d <+4>: sub $0x210,%rsp // 分配528字节栈空间 0x0000000000001144 <+11>: mov %edi,-0x204(%rbp) // 保存argc(4字节) 0x000000000000114a <+17>: mov %rsi,-0x210(%rbp) // 保存argv(8字节) 0x0000000000001151 <+24>: mov -0x210(%rbp),%rax 0x0000000000001158 <+31>: add $0x8,%rax 0x000000000000115c <+35>: mov (%rax),%rdx 0x000000000000115f <+38>: lea -0x200(%rbp),%rax // buffer起始地址:rbp-512 0x0000000000001166 <+45>: mov %rdx,%rsi 0x0000000000001169 <+48>: mov %rax,%rdi 0x000000000000116c <+51>: call 0x1030 <strcpy@plt> 0x0000000000001171 <+56>: mov $0x0,%eax 0x0000000000001176 <+61>: leave 0x0000000000001177 <+62>: ret
差异原因分析
栈对齐规则不同:
x64平台遵循System V AMD64 ABI,要求调用任何函数前栈指针(rsp)必须是16字节的整数倍。进入main函数时,push %rbp会让rsp减少8字节(从调用前的16对齐变为8对齐),因此需要额外分配空间调整rsp回到16对齐状态。500字节不是16的倍数(500 ÷ 16 = 31余4),必须补充空间满足对齐要求。而x86-32通常仅要求4字节对齐,500刚好是4的整数倍(500 ÷ 4 = 125),无需额外空间。寄存器宽度与参数存储差异:
x64的通用寄存器是8字节宽度,保存argv(8字节指针)需要8字节栈空间,而argc(4字节整数)为了对齐到8字节边界,会额外占用4字节填充空间;x86-32的寄存器是4字节,argc和argv各占4字节,总共8字节,无需额外填充。这部分差异也会导致x64分配的栈空间比x86-32多。
内容的提问来源于stack exchange,提问作者JamesMcC
相关产品推荐
相关产品推荐

