为了账号安全,请及时绑定邮箱和手机立即绑定

堆栈分配,填充和对齐

堆栈分配,填充和对齐

C
开满天机 2019-09-02 16:50:06
我一直在努力深入了解编译器如何生成机器代码,更具体地说是GCC如何处理堆栈。在这样做的过程中,我一直在编写简单的C程序,将它们编译成汇编并尽力理解结果。这是一个简单的程序及其生成的输出:asmtest.c:void main() {    char buffer[5];}asmtest.s:pushl   %ebpmovl    %esp, %ebpsubl    $24, %espleaveret让我感到困惑的是为什么要为堆栈分配24个字节。我知道由于处理器如何寻址内存,堆栈必须以4为增量进行分配,但如果是这种情况,我们应该只将堆栈指针移动8个字节而不是24个。作为参考,缓冲区为17 bytes产生一个移动40个字节的堆栈指针,并且根本没有缓冲区移动堆栈指针8. 1到16个字节之间的缓冲区移动ESP24个字节。现在假设8个字节是必要的常量(它需要什么?),这意味着我们分配16个字节的块。为什么编译器会以这种方式对齐?我正在使用x86_64处理器,但即使是64位字也只需要8字节对齐。为什么会出现差异?作为参考,我正在使用gcc 4.0.1运行10.5的Mac上进行编译,并且未启用任何优化。
查看完整描述

4 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

它是一个gcc功能,由-mpreferred-stack-boundary=n编译器试图保持堆栈上的项目对齐的位置控制2^n。如果更改n为2,则只会在堆栈上分配8个字节。默认值n是4ie它将尝试对齐到16字节边界。


为什么有“默认”的8个字节,然后24 = 8 + 16个字节是因为栈已经包含8个字节的leave和ret,所以编译后的代码必须是8个字节首先调整堆得到它对齐到2 ^ 4 = 16。


查看完整回答
反对 回复 2019-09-02
?
慕标琳琳

TA贡献1830条经验 获得超9个赞

SSEx系列指令要求打包128位向量以对齐16个字节 - 否则会出现尝试加载/存储它们的段错误。即如果你想安全地传递16字节向量以便在堆栈上使用SSE,则堆栈需要始终保持与16对齐。默认情况下,GCC会对此进行说明。


查看完整回答
反对 回复 2019-09-02
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

它在页面底部有一些关于堆栈可能更大的原因。将概念扩展到64位机器,它可能会解释您所看到的内容。


查看完整回答
反对 回复 2019-09-02
?
幕布斯7119047

TA贡献1794条经验 获得超8个赞

Mac OS X / Darwin x86 ABI需要16字节的堆栈对齐。在Linux,Win32,FreeBSD等其他x86平台上情况并非如此......


查看完整回答
反对 回复 2019-09-02
  • 4 回答
  • 0 关注
  • 620 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信