J'ai décidé que ce serait amusant pour apprendre l'assemblage x86 pendant les vacances d'été. J'ai donc commencé avec un programme très simple de hello world, en empruntant sur des exemples gratuits gcc -S
pourrait me donner. J'ai fini avec ceci:i386 question d'assemblage: pourquoi dois-je me mêler du pointeur de la pile?
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!
Il compile et fonctionne même! Et je pense que je comprends le plus de celui-ci. Cependant, la magie se produit à l'étape 3. Si je supprime cette ligne, mon programme va mourir entre l'appel à puts
et xor
à partir d'une erreur de pile mal alignée. Et devrais-je changer $20
à une autre valeur, il se bloque trop. Je suis donc arrivé à la conclusion que cette valeur est very
important.
Le problème est, je ne sais pas ce qu'il fait et pourquoi il est nécessaire.
Quelqu'un peut-il m'expliquer? (Je suis sur Mac OS, cela importerait-il un jour?)
Les valeurs de retour sont donc passées dans '% eax'? Je pensais que ça irait toujours sur la pile puisqu'ils peuvent potentiellement être plus gros que 32 bits. Et aussi, pourquoi ai-je besoin d'allouer 24 octets si je n'utilise que 4 d'entre eux? (__EDIT__ ça fonctionne aussi avec 4. Donc je suppose que la pile doit être alignée sur une certaine limite.) – zneak
On dirait que ça plante à cause d'un problème d'alignement, pas de débordement de pile. Les valeurs sont renvoyées dans edx: eax, eax ou une tranche de celle-ci, ou un registre FPU. –
Je suis assez sûr que le pointeur de la pile doit être aligné sur des multiples d'un DWORD (4 octets) sur x86 parce qu'il est 32 bits. – erjiang