Ich habe das ausgezeichnete Buch Programming Ground Up verfolgt, wollte Assembly lernen. Obwohl ich an dieser Stelle nicht im Buch war, wollte ich meine Assembly-Funktion von C. auf einer 32-Bit-Maschine aufrufen, das funktioniert so wie beim Arbeiten aus dem Buch.C zu Assembly Anrufkonvention 32bit vs 64bit
Was ich hier mache, speichert das erste Argument in %ebx
und das zweite in %ecx
.
.type power, @function
.globl power
power:
pushq %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
ich diese (und den Rest der Funktion) in eine Objektdatei kompilieren, eine main.c erstellen, wo ich den Funktionsprototyp und es nennen, so etwas wie dieses:
int power(int b, int x);
int a = power(2, 1);
jedoch Wenn ich das auf einer 64-Bit-Maschine kompiliere, erhalte ich sehr unerwartete Ergebnisse. Ich habe das Offensichtliche modifiziert, wie die Tatsache, dass %esp
und %epb
durch %rsp
und %rpb
ersetzt werden müssen, aber das Graben mit GDB zeigt, dass die Argumente nirgendwo auf dem Stack zu finden sind!
Auschecken, was passiert, indem Sie die Option -S
zu GCC verwenden, kann ich sehen, dass GCC die Argumente in den Registern speichert, anstatt die Variablen auf dem Stapel zu schieben.
movl $1, %esi
movl $2, %edi
call power
Auf der 32-Bit-Maschine, tut es das, was ich erwarte, und drücken Sie die Argumente auf dem Stack:
movl $1, 4(%esp)
movl $2, (%esp)
call power
Nun, was ist hier los? Warum übergibt GCC die Argumente in Registern auf 64 Bit und auf dem Stack auf 32 Bit? Das ist sehr verwirrend! Und ich kann nirgendwo eine Erwähnung finden. Gibt es jemanden, der mich über diese Situation aufklären kann?
x64 Aufrufkonventionen unterscheiden sich von x86 Einsen. In den meisten Fällen werden aufgrund der zusätzlichen Register die ersten vier Argumente in Registern übergeben. – wj32