¿Por qué GCC resta el valor incorrecto al puntero de la pila al asignar una gran matriz sin llamadas a funciones posteriores?
Capricho de gcc realmente extraño. Mira esto
main() { int a[100]; a[0]=1; }
produce esta asamblea:
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
La parte superior de la pila es claramente 400, ya que es una matriz de 100 * 4. Entonces, cuando escribe en la primera entrada, hace rbp - 400 (línea 'b'). Bueno. Pero, ¿por qué resta 280 del puntero de la pila (línea '4')? ¿Eso no apunta al centro de la matriz?
Si agregamos una llamada de función después, gcc hace lo correcto:
b() {}
main() { int a[100]; a[0]=1; b(); }
produce esta asamblea:
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
quí, resta correctamente 400 (línea 'a').
¿Por qué el cambio cuando agrega una llamada de función? ¿Es gcc vago y no lo hace bien porque no importa? ¿Qué esta pasando? Evidentemente, esto solo ocurre cuando se compila para x86_64, pero no para x86 simple. ¿Tiene esto algo extraño que ver con la "zona roja" de x86_64? ¿Qué está pasando precisamente?