真是奇怪的 gcc 怪癖。看一下这个:
main() { int a[100]; a[0]=1; }
产生这个程序集:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 81 ec 18 01 00 00 sub $0x118,%rsp
b: c7 85 70 fe ff ff 01 movl $0x1,-0x190(%rbp)
12: 00 00 00
15: c9 leaveq
16: c3 retq
堆栈的顶部显然是 400,因为它是一个 100 * 4 的数组。因此,当它写入第一个条目时,它会执行 rbp - 400(“b”行)。好的。但是为什么它从堆栈(第'4'行)指针中减去280?那不是指向数组的中间吗?
如果我们之后添加一个函数调用,gcc 会做正确的事情:
b() {}
main() { int a[100]; a[0]=1; b(); }
产生这个程序集:
0000000000000000 <b>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c9 leaveq
5: c3 retq
0000000000000006 <main>:
6: 55 push %rbp
7: 48 89 e5 mov %rsp,%rbp
a: 48 81 ec 90 01 00 00 sub $0x190,%rsp
11: c7 85 70 fe ff ff 01 movl $0x1,-0x190(%rbp)
18: 00 00 00
1b: b8 00 00 00 00 mov $0x0,%eax
20: e8 00 00 00 00 callq 25 <main+0x1f>
25: c9 leaveq
26: c3 retq
在这里,它正确地减去了 400(行 'a')。
为什么添加函数调用时会发生变化?gcc 只是懒惰,因为没关系而没有做对吗?发生了什么?显然,这只发生在为 x86_64 编译时,而不是为普通 x86 编译时。这与 x86_64 的“redzone”有什么奇怪的关系吗?究竟发生了什么?