本当に奇妙な 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
100 * 4 の配列であるため、スタックのトップは明らかに 400 です。したがって、最初のエントリに書き込むときは、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 の「レッドゾーン」と関係がありますか? 正確に何が起こっているのですか?