¿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?

Respuestas a la pregunta(4)

Su respuesta a la pregunta