在进行 C 到 Intel x86 程序集转换时,堆栈上的数组分配占用的空间超过了所需的空间 [重复]
Posted
技术标签:
【中文标题】在进行 C 到 Intel x86 程序集转换时,堆栈上的数组分配占用的空间超过了所需的空间 [重复]【英文标题】:Array allocation on stack taking more space than required while doing C to Intel x86 Assembly Conversion [duplicate] 【发布时间】:2021-08-04 16:00:57 【问题描述】:我正在学习 C 和 intel x86 汇编。我使用了这个简单的 C 代码。
#include <stdio.h>
void function()
char c[1];
int main()
function();
return 0;
我用下面的命令编译它来获取程序集。
gcc -S -o code.s code.c
函数的预期输出汇编如下:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
我的理解是 1 个字符是 1 个字节,intel x86 中的 1 个字大小是 4 个字节,因为我们以字长进行分配,所以应该在堆栈上为 char 分配总共 4 个字节的内存长度为 1 的数组。但是为什么上面的程序集显示 24 字节的分配。
在玩了之后我发现如果 char 数组长度保持在 1-12 范围内,则汇编代码显示 24 个字节的分配,但如果它超过 12,假设它是 13,那么它显示 40 个字节。
对我来说很困惑..
【问题讨论】:
在这种情况下,这只是因为您没有启用优化(然后会删除整个函数,所以...)。在一般情况下,这是因为堆栈指针和数据本身对齐。 您能否请我参考任何文章或链接,因为我仍然没有得到它 gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/… @Jester:GCC 的 16 个额外字节的堆栈分配并不总是随着优化而消失,例如Why does GCC allocate more space than necessary on the stack, beyond what's needed for alignment?。 godbolt.org/z/nhrdGv7zb 表明 GCC-O3
执行 sub $28, %esp
(如果您创建数组 volatile
则它不会消失)。 -fstack-protector-strong
似乎是查询者默认 GCC 选项的一部分,因此在 Godbolt 上需要使用 -O0
重现 24
。
【参考方案1】:
用于 IA-32 (Intel386) 的原始 System V Unix ABI 要求堆栈指针在 4 字节边界上对齐。1 用于 IA-32 的(未发布的)Linux ABI 基于最初的 System V Unix ABI,但在 2015 年 2 月发布了更新的 Linux IA-32 ABI 1.0 版,要求在调用函数时堆栈指针对齐到 16(如果在堆栈上传递 __m256
,则为 32)字节边界.2(此 ABI 已于 2015 年 12 月更新至 1.1 版,3据我所知是撰写本文时的最新版本。)
函数调用的编译器前导代码通常假定堆栈在入口处已经对齐。它假定%esp+4
(+4
代表堆栈上的返回地址)与 16(或 32)字节边界对齐,并确保堆栈指针减少 16 的倍数(并与32 的倍数)调用另一个函数时。即使被调用的函数没有调用另一个函数,它也会这样做。
对于下面的序言:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
在第一条指令 (pushl %ebp
) 之前,%esp+4
与 16 字节边界对齐。在第一条指令之后,%esp+4+4
与 16 字节边界对齐。在第三条指令(subl $24, %esp
)之后,%esp+4+4+24
对齐到 16 字节边界,由于 4+4+24 是 16 的倍数,%esp
对齐到 16 字节边界。
编译器可能已将subl $24, %esp
替换为subl $8, %esp
并仍保持堆栈与16 字节边界对齐。我不知道分配额外 16 个字节的原因。
在修订 ABI 的 1.0 版发布之前,Linux 的 GCC 编译器已经假设堆栈已经与 16 字节边界对齐多年。这导致 GCC 4.4 破坏了几个二进制文件。 “修复”是更改 ABI,破坏现有的旧代码,而不是修复编译器以与现有代码兼容。4
脚注:
-
System V Application Binary Interface, Intel386™ Architecture Processor Supplement Fourth Edition — 图 3-15:标准堆栈框架。
System V Application Binary Interface Intel386 Architecture Processor Supplement Version 1.0 — 2.2.2 堆栈框架。
System V Application Binary Interface Intel386 Architecture Processor Supplement Version 1.1
Bug 40838 - gcc shouldn't assume that the stack is aligned — Comment 86 by H.J.Lu (2011-01-18 21:07:26 UTC):
我正在更新 i386 psABI 以指定 16 字节堆栈对齐。
【讨论】:
Why does GCC allocate more space than necessary on the stack, beyond what's needed for alignment? - 额外的 16 个字节是一个常见的 GCC 错误;有人应该报告它...请注意,这是一个叶函数,并且数组小于 16 字节,因此没有任何对齐要求。 (clang -O3
和 volatile
来阻止数组优化实际上做了一个疯狂的sub $1, %esp
;这可能不是一件好事。godbolt.org/z/Gcnqx8931)以上是关于在进行 C 到 Intel x86 程序集转换时,堆栈上的数组分配占用的空间超过了所需的空间 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
cmp 不工作 - Intel x86 (IA32) 程序集