Decidí que sería diversión para aprender a ensamblar x86 durante las vacaciones de verano. Así que comencé con un programa hello world muy simple, pidiendo prestado en ejemplos gratuitos gcc -S
podría darme. Terminé con esto:i386 pregunta de ensamblaje: ¿por qué necesito mezclarme con el puntero de la pila?
HELLO:
.ascii "Hello, world!\12\0"
.text
.globl _main
_main:
pushl %ebp # 1. puts the base stack address on the stack
movl %esp, %ebp # 2. puts the base stack address in the stack address register
subl $20, %esp # 3. ???
pushl $HELLO # 4. push HELLO's address on the stack
call _puts # 5. call puts
xorl %eax, %eax # 6. zero %eax, probably not necessary since we didn't do anything with it
leave # 7. clean up
ret # 8. return
# PROFIT!
compila e incluso funciona! Y creo que entiendo más de él.
Sin embargo, la magia sucede en el paso 3. ¿Eliminaría esta línea, mi programa moriría entre la llamada a puts
y la xor
de un error de pila desalineada. Y cambiaría $20
a otro valor, se bloqueará también. Entonces llegué a la conclusión de que este valor es very
importante.
El problema es que no sé qué es y por qué es necesario.
¿Alguien me puede explicar? (Estoy en Mac OS, ¿alguna vez importaría?)
¿Los valores de retorno se pasan en '% eax'? Pensé que siempre iría a la pila, ya que potencialmente pueden ser más grandes que 32 bits. Y también, ¿por qué tengo que asignar 24 bytes si solo voy a usar 4 de ellos? (__EDIT__ también funciona con 4. Así que supongo que la pila tiene que estar alineada en un cierto límite). – zneak
Parece que está fallando debido a un problema de alineación, no a un desbordamiento de la pila. Los valores se devuelven en edx: eax, eax o una porción de los mismos, o un registro FPU. –
Estoy bastante seguro de que el puntero de pila debe alinearse en múltiplos de un DWORD (4 bytes) en x86 porque es de 32 bits. – erjiang