Pointer und 'lea' (Intel syntax)
-
Hallo,
desto mehr ASM-Code ich sehe, desto mehr verwirrt mich das [] um ausdrücken. Soweit ich weiß, bewirkt das [] eine dereferenzierung, d.h. wenn in eax z.b. 0x35F0 steht greift [eax] im RAM auf die adresse 0x35F0 zu. Soweit alles in ordnung. Allerdings lässt mich 'lea' etwas grübeln. Folgenden Code als beispiel:
global main extern printf section .data fmtStr: db 'hello, world',0xA,0 section .text main: sub esp, 4 ; Allocate space on the stack for one 4 byte parameter lea eax, [fmtStr] mov [esp], eax ; Arg1: pointer to format string call printf ; Call printf(3): ; int printf(const char *format, ...); add esp, 4 ; Pop stack once ret
Ich habe die Dokumentation zu 'lea' gelesen, verstehen tue ich es aber überhaupt nicht. Ich hätte in dem codebeispiel z.b. das
lea eax, [fmtStr]
durch
mov eax, fmtStr
ersetzt, soweit ich weiß 'beinhalten' labels die speicheraddresse, das mov müsste also die speicheradresse vom 'h' nach eax schieben. Das 'lea' hingegen läd die effektive adresse von [fmtStr], was meiner meinung nach eben genau 'fmtStr' ist. Wo ist da der unterschied?
-
Das mit der Dereferenzierung ist eine Vereinfachung, die nicht immer passt. Die eckigen Klammern stehen für effective addresses (http://www.nasm.us/doc/nasmdoc3.html#section-3.3). Im Prinzip ist der ganze Klammerausdruck eine berechnete Speicheradresse.
Wenn man sich nun die möglichen Quellparameter für mov anschaut, sieht man was passiert:
1. mov mit Konstante (dazu gehören auch Labeladressen) als Quelle => Konstante wird in Ziel geschrieben
2. mov mit Register als Quelle => Registerinhalt wird in Ziel kopiert
3. mov mit Speicheradresse als Quelle => Speicherinhalt von Adresse wird in Ziel kopiert=> [Konstante] und [Register] fallen unter Fall 3. Es wird auf Basis des Wert der Konstante oder dem Registerinhalt die Speicheradresse berechnet und dann der Inhalt der Adresse kopiert. Es sieht aus wie eine Dereferenzierung, aber eigentlich ändern wir den Typ der Quelle.
Der Unterschied von lea zu mov ist, dass die übergebene Speicheradresse ins Ziel geschrieben wird, statt der Inhalt der Adresse. In deinem Beispiel mit [fmtStr] also die Adresse die sich aus dem Wert der Labeladresse ergibt.
-
Der Unterschied ist dass eben
lea
stattmov
verwendet wird.
Beide Instruktionen wären möglich, beide Instruktionen würde das selbe machen.lea
gibt es, damit man Berechnungen die die CPU für Adressberechnungen "direkt" unterstützt auch verwenden kann ohne dann gleich auf die Speicherstelle mit dieser Adresse zuzugreifen.
z.B. kannst dulea eax, [ebx + 4 * ecx + 100]
sagen.
Mitmov
ginge das nicht, dennmov
kann nicht rechnen --mov eax, ebx + 4 * ecx + 100
gibt es einfach nicht.Dass man
lea
auch verwenden kann ohne zu rechnen kommt einfach nur daher dass es Addressierungsarten gibt wo nichts gerechnet wird.
-