Alineamiento de memoria hoy y hace 20 años

En el famoso artículo "Smashing the Stack for Fun and Profit", su autor toma una función C

void function(int a, int b, int c) {
  char buffer1[5];
  char buffer2[10];
}

y genera la salida del código de ensamblaje correspondiente

pushl %ebp
movl %esp,%ebp
subl $20,%esp

El autor explica que, dado que las computadoras direccionan la memoria en múltiplos de tamaño de palabra, el compilador reservó 20 bytes en la pila (8 bytes para el buffer1, 12 bytes para el buffer2).

Traté de recrear este ejemplo y obtuve lo siguiente

pushl   %ebp
movl    %esp, %ebp
subl    $16, %esp

Un resultado diferente! Intenté varias combinaciones de tamaños para el buffer1 y el buffer2, y parece que el gcc moderno ya no rellena los tamaños del buffer a múltiplos de tamaño de palabra. En cambio, cumple con el-mpreferred-stack-boundary opción.

Como ilustración, usando las reglas aritméticas del papel, para buffer1 [5] y buffer2 [13] obtendría 8 + 16 = 24 bytes reservados en la pila. Pero en realidad obtuve 32 bytes.

El periódico es bastante viejo y desde entonces sucedieron muchas cosas. Me gustaría saber, ¿qué motivó exactamente este cambio de comportamiento? ¿Es el movimiento hacia máquinas de 64 bits? ¿O algo mas?

Editar

El código se compila en una máquina x86_64 usando gcc versión 4.8.2 (Ubuntu 4.8.2-19ubuntu1) así:

$ gcc -S -o example1.s example1.c -fno-stack-protector -m32