Der LEA-Befehl (Load Effective Address) ist eine Möglichkeit, die Adresse zu erhalten, die sich aus einem der Speicheradressierungsmodi des Intel-Prozessors ergibt.
Das heißt, wenn wir eine Datenbewegung wie diese haben:
MOV EAX, <MEM-OPERAND>
verschiebt er den Inhalt des angegebenen Speicherplatzes in das Zielregister.
Wenn wir die MOV
por LEA
dann wird die Adresse des Speicherplatzes auf genau dieselbe Weise von der <MEM-OPERAND>
Ausdruck ansprechen. Aber statt des Inhalts der Speicherstelle erhalten wir die Stelle selbst als Ziel.
LEA
ist kein spezifischer arithmetischer Befehl, sondern eine Möglichkeit, die effektive Adresse abzufangen, die sich aus einem der Speicheradressierungsmodi des Prozessors ergibt.
Wir können zum Beispiel Folgendes verwenden LEA
mit einer einfachen Direktansprache. Es ist überhaupt keine Arithmetik beteiligt:
MOV EAX, GLOBALVAR ; fetch the value of GLOBALVAR into EAX
LEA EAX, GLOBALVAR ; fetch the address of GLOBALVAR into EAX.
Dies ist gültig; wir können es an der Linux-Eingabeaufforderung testen:
$ as
LEA 0, %eax
$ objdump -d a.out
a.out: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 8d 04 25 00 00 00 00 lea 0x0,%eax
Hier wird weder ein skalierter Wert noch ein Offset hinzugefügt. Null wird nach EAX verschoben. Wir könnten dies auch mit MOV mit einem unmittelbaren Operanden tun.
Dies ist der Grund, warum Menschen, die glauben, dass die Klammern in LEA
überflüssig sind, irren sich gewaltig; die Klammern sind nicht LEA
Syntax, sondern sind Teil des Adressierungsmodus.
LEA ist auf der Hardware-Ebene real. Der generierte Befehl kodiert den tatsächlichen Adressierungsmodus, und der Prozessor führt ihn bis zum Punkt der Adressberechnung aus. Dann verschiebt er diese Adresse an das Ziel, anstatt eine Speicherreferenz zu erzeugen. (Da die Adressberechnung eines Adressierungsmodus in einem beliebigen anderen Befehl keine Auswirkungen auf CPU-Flags hat, LEA
hat keine Auswirkung auf CPU-Flags).
Im Gegensatz zum Laden des Wertes von Adresse Null:
$ as
movl 0, %eax
$ objdump -d a.out | grep mov
0: 8b 04 25 00 00 00 00 mov 0x0,%eax
Es ist eine sehr ähnliche Kodierung, sehen Sie? Nur die 8d
de LEA
hat sich geändert in 8b
.
Natürlich ist dies LEA
Kodierung ist länger als das Verschieben einer unmittelbaren Null in EAX
:
$ as
movl $0, %eax
$ objdump -d a.out | grep mov
0: b8 00 00 00 00 mov $0x0,%eax
Es gibt keinen Grund für LEA
Ich möchte diese Möglichkeit nicht ausschließen, nur weil es eine kürzere Alternative gibt; sie wird nur auf orthogonale Weise mit den verfügbaren Adressierungsarten kombiniert.
8 Stimmen
Siehe auch LEA auf Werte anwenden, die keine Adressen/Zeiger sind? : LEA ist nur ein Shift-and-Add-Befehl. Er wurde wahrscheinlich zum 8086 hinzugefügt, weil die Hardware bereits vorhanden ist, um Adressierungsmodi zu dekodieren und zu berechnen, nicht weil er nur für die Verwendung mit Adressen "gedacht" ist. Denken Sie daran, dass Zeiger in Assembler nur ganze Zahlen sind.