Aquí está mi código fuente:
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 500 int main(int argc, char** argv) { if (argc != 2) exit(1); char str[MAX]; strcpy(str, argv[1]); return 0; } disas main usando gdb y obtuve el siguiente resultado:
Dump of assembler code for function main: 0x0000000000001145 <+0>: push %rbp 0x0000000000001146 <+1>: mov %rsp,%rbp 0x0000000000001149 <+4>: sub $0x210,%rsp . . . End of assembler dump.Aquí lo destacable es:
0x0000000000001149 <+4>: sub $0x210,%rsp
y mi pregunta es-
¿Por qué hay $0x210 (528 bytes), cuando debería ser $0x1f4 (500 bytes) como pedí?
Supongo que está usando gcc y compilando sin optimizaciones, como este (godbolt) .
Hay un par de cosas sucediendo aquí:
Primero, al compilar sin optimizaciones, el compilador intenta asegurarse de que cada variable local tenga una dirección en la memoria, de modo que un depurador pueda inspeccionarla o modificarla fácilmente. Esto incluye parámetros de función, que en x86-64 se pasan en registros. Por lo tanto, el compilador debe asignar espacio de pila adicional donde los parámetros argc y argv se pueden "derramar". Puede ver el derrame en las líneas 5 y 6 del ensamblaje:
movl %edi, -516(%rbp) movq %rsi, -528(%rbp) Si observa detenidamente, puede notar que el compilador desperdició 4 bytes al colocar argc (de %edi ) en la dirección -516(%rbp) cuando -520(%rbp) estaba disponible. No está del todo claro por qué, pero después de todo, ¡no está optimizando! Eso nos lleva a 516 bytes.
El otro problema es que la ABI x86-64 requiere una alineación de pila de 16 bytes; consulte ¿Por qué la ABI x86-64/AMD64 System V exige una alineación de pila de 16 bytes? . En este caso, para resumir, implica que nuestro ajuste de pila debe ser un múltiplo de 16 bytes. (La dirección de retorno y el rbp agregan 16 bytes adicionales que no perturban esta alineación). Por lo tanto, nuestro 516 debe redondearse al siguiente múltiplo de 16, que es 528.
Si el compilador hubiera sido más cuidadoso y no hubiera desperdiciado esos 4 bytes entre argc y argv , podríamos habernos quedado con solo 512 bytes. Sin embargo, un beneficio de usar 528 es que la str del búfer termina alineada en 16 bytes. Esto no es necesario para una matriz de char , cuya alineación mínima es solo 1, pero puede hacer que sea más eficiente para funciones de cadena como strcpy para usar algoritmos SIMD rápidos. No estoy seguro de si el compilador está haciendo esto deliberadamente o si es solo una coincidencia.