2015-04-23 7 views
7

ich mein Lehrbuch zu lesen und es hat Code für eine Swap-Funktion:Pointer Deferencing in x86-Assembler-Code

In C:

int exchange(int *xp, int y) { 
int x = *xp; 
*xp = y; 
return x; 
} 

In x86 Assembly mit Anmerkungen:

// xp is at %ebp + 8, y at %ebp + 12 
movl 8(%ebp), %edx  // get xp 
movl (%edx), %eax  // get x at xp 
movl 12(%ebp), %ecx  // get y 
movl %ecx, (%edx)  // store y at xp 

Wenn also int * xp auf ein int I an der Adresse A zeigt, speichert die erste Zeile des Assemblercodes A at% edx. Dann wird es in der zweiten Zeile dereferenziert und bei% eax gespeichert.

Wenn das wahr ist, frage ich mich, warum Linie 1 "8 (% ebp)" den Zeiger nicht dereferenziert und das int I in% edx statt der Adresse A speichert? Sind das nicht die Klammern in der Montage?

Oder bedeutet das, dass, wenn Zeiger auf den Stapel geschoben werden, die Adresse des Zeigers geschoben wird, anstatt den Wert, den es enthält, also 8 (% ebp) technisch & XP?

Ich wollte nur klären, ob mein Verständnis korrekt war.

+2

Ebp ist eine Adresse des Stapelrahmens, in der alle Argumente sind. Ebp + 8 ist eine Adresse des Wertes von xp (das ist die Adresse von int). Technisch ja - ebp + 8 == & xp. – user3125367

+0

* bedeutet das, dass, wenn Zeiger auf den Stapel geschoben werden, die Adresse des Zeigers angestoßen wird und nicht der Wert, den es enthält * - Und nein, ein Zeigerwert wird auf den Stapel geschoben. – user3125367

Antwort

5

xp ist ein Zeiger. Es hat einen Vier-Byte-Wert. Dieser Wert wird von der aufrufenden Funktion auf den Stack geschoben. Der Funktionsprolog, den Sie nicht angezeigt haben, baut einen Basiszeiger in ebp auf. Der Wert von xp wird bei Offset 8 relativ zu diesem Basiszeiger gespeichert.

So ist die erste Zeile des Codes dereferenziert den Basiszeiger, wie durch die Klammern angedeutet, mit einem von 8 versetzt die Wert von xp abzurufen (die eine Adresse ist, die zu einer int Punkte) und setzt es in edx .

Die zweite Codezeile verwendet die Adresse in edx, um den Wert der int abzurufen, und setzt diesen Wert in eax. Beachten Sie, dass der Rückgabewert der Funktion der Wert in eax ist. Die dritte Zeile dereferenziert den Basiszeiger mit einem Offset von 12, um den Wert y zu erhalten.

Die vierte Zeile verwendet die Adresse in edx, um y an der Stelle zu platzieren, die xp verweist.

2

%bp ist der Stack-Basiszeiger, der deferenziert werden muss, bevor ich auf irgendetwas auf dem Stack zugreifen kann. Also movl 8 (% bp),% edx` holt den Wert, der auf Offset 8 im aktuellen Stapelrahmen sitzt.

Dieser Wert ist ein Zeiger, also müssen wir ihn dereferenzieren, um auf seinen Inhalt zuzugreifen, egal ob zum Lesen oder Schreiben.

OTOH, y ist ein int, so dass es nur movl 12(%ebp), %ecx ist und keine weitere actoin erforderlich.

Also movl %ecx, (%edx) ist genau das Richtige: Setzen Sie den Wert, der in ecx gespeichert ist, auf den Speicher, auf den edx zeigt.