我无法理解为什么编译器选择以我编写的代码的方式偏移堆栈空间。
我在玩弄 Godbolt 的编译器资源管理器以研究 C 调用约定,当我想出一个简单的代码时,我对它的选择感到困惑。
代码在 this link 中找到.我选择了 GCC 8.2 x86-64,但我的目标是 x86 处理器,这很重要。下面是编译器资源管理器报告的 C 代码和生成的程序集的转录。
// C code
int testing(char a, int b, char c) {
return 42;
}
int main() {
int x = testing('0', 0, '7');
return 0;
}
; Generated assembly
testing(char, int, char):
push ebp
mov ebp, esp
sub esp, 8
mov edx, DWORD PTR [ebp+8]
mov eax, DWORD PTR [ebp+16]
mov BYTE PTR [ebp-4], dl
mov BYTE PTR [ebp-8], al
mov eax, 42
leave
ret
main:
push ebp
mov ebp, esp
sub esp, 16
push 55
push 0
push 48
call testing(char, int, char)
add esp, 12
mov DWORD PTR [ebp-4], eax
mov eax, 0
leave
ret
从现在开始看汇编专栏,据我了解,第15行负责为局部变量保留堆栈空间。问题是我只有一个本地 int
并且偏移量是 16 个字节而不是 4 个字节。这感觉像是浪费了空间。
这和单词对齐有关系吗?但即使是,如果通用寄存器的大小是 4 个字节,这种对齐不应该是关于 4 个字节吗?
我看到的另一件奇怪的事情是关于 testing
函数的本地 char
的放置。它们似乎在堆栈中各占用 4 个字节,如第 7-8 行所示,但仅操作了较低的字节。为什么不每个只使用 1 个字节?
这些选择可能是出于好意,我很想了解它们的目的(或者是否没有目的)。或者,也许我只是感到困惑,没有完全理解。
最佳答案
因此,根据评论,我可以弄清楚堆栈增长问题是由于 i386 SystemV ABI 要求引起的,如@PeterCordes 所述。
字符按字对齐的原因可能是由于 GCC 提高速度的默认行为,这可能是从 @Ped7g 的评论中推断出来的。虽然不确定,但这对我来说已经足够好了。
关于c - 当我只有一个 4 字节的局部变量时,为什么堆栈在反汇编中增长了 16 个字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54210828/