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 statt mov 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 du lea eax, [ebx + 4 * ecx + 100] sagen.
    Mit mov ginge das nicht, denn mov 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.




Anmelden zum Antworten