【问题标题】:ARM - Why does gcc allocate 12 bytes for a single char?ARM - 为什么 gcc 为单个字符分配 12 个字节?
【发布时间】:2016-03-15 04:11:49
【问题描述】:

我有以下代码:

int main()
{
    volatile char a;

    return 0;
}

当我用arm-linux-gnueabihf-gcc -o align.txt -O0 -S align.c 反汇编它时,我得到以下信息:

push    {r7}
sub sp, sp, #12
...

现在,我知道 ARM EABI 要求堆栈是 8 字节对齐的,这可以解释 gcc 分配的空间比a 所需的单个字节多一些。但是,我原以为它会分配 4 个字节来为 a 和 3 个填充字节腾出空间。

看起来它分配了 4 个字节以使推送的 r7 对齐,然后再分配 8 个字节(1 个用于 a,7 个用于填充)。如果我改为定义一个 9 成员 char 数组,它将分配 20 个字节。

为什么推送的 r7 需要自己的填充?

【问题讨论】:

  • 愚蠢的问题,暗中刺探:如果您删除“易失性”,并使用a,这样它就不会被编译掉,是一样的吗?
  • 请注意,当您不启用优化时,gcc 会做很多非常幼稚的事情。
  • 是的,您应该使用-O3,然后将return 0; 更改为return a;,这样它就不会被优化掉。您将看到分配了 8 个字节。
  • @MarcusMüller 是的。我还尝试了 Jester 的建议,它只是编译为 movs r0, #0。通过优化,gcc 似乎变得更加智能。
  • -Os 会发生什么?

标签: c assembly stack arm


【解决方案1】:

在 C/C++ 中,在 32/64 位机器上,8 位或 16 位参数作为 32 位参数传递(在某些 64 位机器上可能是 64 位)。然后被调用的函数只使用 32 位参数的低 8 位或 16 位。一些(或大多数)32/64 位处理器没有或不使用 push 字节或 push short 来进行堆栈操作。如果使用快速调用 API,那么前几个参数将使用 32 位或 64 位寄存器。

示例汇编代码可能将堆栈对齐到 16 字节边界,或者它可能对局部变量或调试器使用堆栈进行默认分配。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 2020-09-08
    • 1970-01-01
    • 2020-05-24
    相关资源
    最近更新 更多