我无法理解为什么编译器选择以我编写的代码的方式偏移堆栈空间。
我正在玩弄 Godbolt 的 Compiler Explorer 以研究 C 调用约定,这时我想出了一个简单的代码,它的选择让我感到困惑。
代码可在此链接中找到。我选择了 GCC 8.2 x86-64,但我的目标是 x86 处理器,这很重要。Bellow 是编译器资源管理器报告的 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 个字节吗?
我看到的另一件奇怪的事情是关于函数的 local char
s 的位置。testing
它们似乎在堆栈中每个占用 4 个字节,如第 7-8 行所示,但只有较低的字节被操作。为什么不每个只使用 1 个字节?
这些选择可能是出于好意,我真的很想了解它们的目的(或者是否没有目的)。或者,也许我只是感到困惑,并没有完全明白。