J'ai suivi l'excellent livre Programming Ground Up, voulant apprendre l'assemblage. Bien que n'étant pas dans le livre à ce stade, je voulais appeler ma fonction d'assemblage de C. sur une machine 32 bits, cela fonctionne comme lorsque vous travaillez à partir du livre.C à assembler convention d'appel 32bit vs 64bit
Ce que je fais ici est de stocker le premier argument en %ebx
et le second en %ecx
.
.type power, @function
.globl power
power:
pushq %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
je compile ce (et le reste de la fonction) dans un fichier objet, créer un main.c, où je prototype la fonction et l'appeler, quelque chose comme ceci:
int power(int b, int x);
int a = power(2, 1);
Cependant , quand je compile ceci sur une machine 64 bits, j'obtiens des résultats très inattendus. J'ai modifié l'évidence, comme le fait que %esp
et %epb
doit être remplacé par %rsp
et %rpb
, mais creuser avec GDB révèle que les arguments ne sont nulle part sur la pile!
Vérifier ce qu'il se passe en utilisant l'option -S
pour GCC Je vois qu'au lieu de pousser les variables sur la pile, GCC stocke les arguments dans les registres.
movl $1, %esi
movl $2, %edi
call power
Sur la machine 32 bits, il fait ce que je pense et pousser les arguments sur la pile:
movl $1, 4(%esp)
movl $2, (%esp)
call power
Maintenant, ce qui se passe ici? Pourquoi GCC passe-t-il les arguments dans les registres sur 64 bits et sur la pile sur 32 bits? C'est très déroutant! Et je ne trouve aucune mention à ce sujet nulle part. Y a-t-il quelqu'un qui peut m'éclairer sur cette situation?
Les conventions d'appel x64 sont différentes des conventions x86. Dans la plupart des cas, en raison des registres supplémentaires, les quatre premiers arguments sont passés dans les registres. – wj32