Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In den Listen in diesem Abschnitt sind anweisungen, die mit einem Sternchen (*) gekennzeichnet sind, besonders wichtig. Anweisungen, die nicht so gekennzeichnet sind, sind nicht kritisch.
Auf dem x86-Prozessor haben Anweisungen eine variable Größe, sodass das Disassemblieren nach hinten eine Übung beim Musterabgleich ist. Um von einer Adresse rückwärts zu disassemblieren, sollten Sie mit dem Disassemblieren zu einem Punkt beginnen, der weiter zurück ist, als Sie wirklich möchten, und dann nach vorne schauen, bis die Anweisungen sinnvoll sind. Die ersten Anweisungen machen möglicherweise keinen Sinn, da Sie möglicherweise mitten in einer Anweisung mit dem Disassemblieren begonnen haben. Es besteht leider die Möglichkeit, dass die Disassemblierung nie mit dem Anweisungsstream synchronisiert wird und Sie an einem anderen Ausgangspunkt disassemblieren müssen, bis Sie einen Ausgangspunkt gefunden haben, der funktioniert.
Bei gut gepackten Switch-Anweisungen gibt der Compiler Daten direkt in den Codestream aus, sodass das Disassemblieren über eine switch-Anweisung in der Regel auf Anweisungen stößt, die keinen Sinn ergeben (da es sich wirklich um Daten handelt). Suchen Sie das Ende der Daten, und fahren Sie dort mit der Disassemblierung fort.
Anweisungsnotation
Die allgemeine Schreibweise für Anweisungen besteht darin, das Zielregister auf der linken Seite und die Quelle auf der rechten Seite zu platzieren. Es kann jedoch einige Ausnahmen von dieser Regel geben.
Arithmetische Anweisungen bestehen in der Regel aus zwei Registern, wobei quell- und zielregister kombiniert werden. Das Ergebnis wird im Ziel gespeichert.
Einige der Anweisungen enthalten sowohl 16-Bit- als auch 32-Bit-Versionen, aber nur die 32-Bit-Versionen sind hier aufgeführt. Hier nicht aufgeführt sind Gleitkommaanweisungen, privilegierte Anweisungen und Anweisungen, die nur in segmentierten Modellen verwendet werden (die Microsoft Win32 nicht verwendet).
Um Platz zu sparen, werden viele der Anweisungen in kombinierter Form ausgedrückt, wie im folgenden Beispiel gezeigt.
* |
MOV |
r1, r/m/#n |
r1 = r/m/#n |
bedeutet, dass der erste Parameter ein Register sein muss, der zweite kann jedoch ein Register, ein Speicherverweis oder ein sofortiger Wert sein.
Um noch mehr Platz zu sparen, können Anweisungen auch wie im Folgenden dargestellt ausgedrückt werden.
* |
MOV |
r1/m, r/m/#n |
r1/m = r/m/#n |
Dies bedeutet, dass der erste Parameter ein Register oder ein Speicherverweis sein kann, und der zweite kann ein Register, ein Speicherverweis oder ein sofortiger Wert sein.
Sofern nicht anders angegeben, können Sie bei Verwendung dieser Abkürzung nicht den Arbeitsspeicher für Quelle und Ziel auswählen.
Darüber hinaus kann ein Bitgrößensuffix (8, 16, 32) an die Quelle oder das Ziel angefügt werden, um anzugeben, dass der Parameter diese Größe aufweisen muss. Beispielsweise bedeutet r8 ein 8-Bit-Register.
Arbeitsspeicher, Datenübertragung und Datenkonvertierung
Anweisungen zur Speicher- und Datenübertragung wirken sich nicht auf Flags aus.
Effektive Adresse
* |
LEA |
r, m |
Laden Sie die effektive Adresse. (r = Adresse von m) |
Beispielsweise bedeutet LEA eax, [esi+4]eax = esi + 4. Diese Anweisung wird häufig verwendet, um Arithmetik auszuführen.
Datenübertragung
MOV |
r1/m, r2/m/#n |
r1/m = r/m/#n |
|
MOVSX |
r1, r/m |
Verschieben mit Vorzeichenerweiterung. |
|
* |
MOVZX |
r1, r/m |
Verschieben mit der Erweiterung "Null". |
MOVSX und MOVZX sind spezielle Versionen der mov-Anweisung , die eine Vorzeichenerweiterung oder null-Erweiterung von der Quelle zum Ziel ausführen. Dies ist die einzige Anweisung, die die Größe von Quelle und Ziel erlaubt. (Und in der Tat müssen sie unterschiedliche Größen haben.
Stapelbearbeitung
Auf den Stapel zeigt das esp-Register . Der Wert bei esp ist der obere Rand des Stapels (zuletzt gepusht, zuerst eingeklallt); ältere Stapelelemente befinden sich an höheren Adressen.
PUSH |
r/m/#n |
Pushen sie den Wert auf den Stapel. |
|
POP |
r/m |
Pop-Wert aus Stapel. |
|
PUSHFD |
Pushen von Flags auf den Stapel. |
||
POPFD |
Popflags aus dem Stapel. |
||
PUSHAD |
Pushen aller ganzzahligen Register. |
||
POPAD |
Alle ganzzahligen Register auffüllen. |
||
EINGABETASTE |
#n, #n |
Buildstapelrahmen. |
|
* |
VERLASSEN |
Abreißen des Stapelrahmens |
Der C/C++-Compiler verwendet die Enter-Anweisung nicht. (Die Enter-Anweisung wird verwendet, um geschachtelte Prozeduren in Sprachen wie Algol oder Pascal zu implementieren.)
Die Leave-Anweisung entspricht:
mov esp, ebp
pop ebp
Datenkonvertierung
CBW |
Konvertieren Sie Byte (al) in Wort (ax). |
CWD |
Konvertieren von Wort (ax) in dword (dx:ax). |
CWDE |
Konvertieren von Wort (ax) in dword (eax). |
CDQ |
konvertieren Sie dword (eax) in qword (edx:eax). |
Alle Konvertierungen führen eine Vorzeichenerweiterung durch.
Arithmetik und Bitbearbeitung
Alle Anweisungen zur Arithmetik- und Bitbearbeitung ändern Flags.
Arithmetische
ADD |
r1/m, r2/m/#n |
r1/m += r2/m/#n |
|
ADC |
r1/m, r2/m/#n |
r1/m += r2/m/#n + carry |
|
SUB |
r1/m, r2/m/#n |
r1/m -= r2/m/#n |
|
SBB |
r1/m, r2/m/#n |
r1/m -= r2/m/#n + carry |
|
NEG |
r1/m |
r1/m = -r1/m |
|
INC |
r/m |
r/m += 1 |
|
DEC |
r/m |
r/m -= 1 |
|
CMP |
r1/m, r2/m/#n |
Compute r1/m – r2/m/#n |
Die cmp-Anweisung berechnet die Subtraktion und legt die Flags entsprechend dem Ergebnis fest, löst jedoch das Ergebnis aus. Auf sie folgt in der Regel eine bedingte Sprunganweisung , die das Ergebnis der Subtraktion testet.
MUL |
r/m8 |
Ax = Al * r/m8 |
|
MUL |
r/m16 |
dx:ax = ax * r/m16 |
|
MUL |
r/m32 |
edx:eax = eax * r/m32 |
|
IMUL |
r/m8 |
Ax = Al * r/m8 |
|
IMUL |
r/m16 |
dx:ax = ax * r/m16 |
|
IMUL |
r/m32 |
edx:eax = eax * r/m32 |
|
IMUL |
r1, r2/m |
r1 *= r2/m |
|
IMUL |
r1, r2/m, #n |
r1 = r2/m * #n |
Nicht signierte und signierte Multiplikation. Der Status von Flags nach der Multiplikation ist nicht definiert.
DIV |
r/m8 |
(ah, al) = (ax % r/m8, ax / r/m8) |
|
DIV |
r/m16 |
(dx, ax) = dx:ax / r/m16 |
|
DIV |
r/m32 |
(edx, eax) = edx:eax / r/m32 |
|
IDIV |
r/m8 |
(ah, al) = ax / r/m8 |
|
IDIV |
r/m16 |
(dx, ax) = dx:ax / r/m16 |
|
IDIV |
r/m32 |
(edx, eax) = edx:eax / r/m32 |
Nicht signierte und signierte Division. Das erste Register in der Pseudocodeerklärung empfängt den Rest und das zweite den Quotienten. Wenn das Ergebnis das Ziel überläuft, wird eine Bereichsüberlaufausnahme generiert.
Der Status von Flags nach der Division ist nicht definiert.
* |
SETcc |
r/m8 |
Legen Sie r/m8 auf 0 oder 1 fest. |
Wenn die Bedingung cc true ist, wird der 8-Bit-Wert auf 1 festgelegt. Andernfalls wird der 8-Bit-Wert auf 0 (null) festgelegt.
Binärcodierte Dezimalstellen
Diese Anweisungen werden nur angezeigt, wenn Sie Code debuggen, der in COBOL geschrieben wurde.
DAA |
Dezimalanpassung nach dem Hinzufügen. |
|
DAS |
Dezimalanpassung nach der Subtraktion. |
Diese Anweisungen passen das Al-Register an, nachdem eine gepackte binärcodierte Dezimaloperation ausgeführt wurde.
AAA |
ASCII-Anpassung nach dem Hinzufügen. |
AAS |
ASCII-Anpassung nach der Subtraktion. |
Diese Anweisungen passen das Al-Register an, nachdem ein entpackter binärcodierter Dezimalvorgang ausgeführt wurde.
AAM |
ASCII-Anpassung nach der Multiplikation. |
AAD |
ASCII-Anpassung nach der Division. |
Diese Anweisungen passen die Register al und ah an, nachdem ein entpackter binärcodierter Dezimalvorgang ausgeführt wurde.
Bits
UND |
r1/m, r2/m/#n |
r1/m = r1/m und r2/m/#n |
|
oder |
r1/m, r2/m/#n |
r1/m = r1/m oder r2/m/#n |
|
XOR |
r1/m, r2/m/#n |
r1/m = r1/m xor r2/m/#n |
|
NICHT |
r1/m |
r1/m = bitweise nicht r1/m |
|
* |
TEST |
r1/m, r2/m/#n |
Compute r1/m und r2/m/#n |
Die Testanweisung berechnet den logischen AND-Operator und legt Flags entsprechend dem Ergebnis fest, verschieft das Ergebnis jedoch. Es folgt in der Regel eine bedingte Sprunganweisung, die das Ergebnis des logischen AND testet.
SHL |
r1/m, cl/#n |
r1/m <<= cl/#n |
|
SHR |
r1/m, cl/#n |
r1/m >>= cl/#n zero-fill |
|
* |
SAR |
r1/m, cl/#n |
r1/m >>= cl/#n Sign-Fill |
Das letzte ausgelagerte Bit wird im Carry platziert.
SHLD |
r1, r2/m, cl/#n |
Doppelt umschalten. |
Verschieben Sie r1 links durch cl/#n, und füllen Sie die oberen Bits von r2/m. Das letzte ausgelagerte Bit wird im Carry platziert.
SHRD |
r1, r2/m, cl/#n |
Doppel umschalten nach rechts. |
Verschieben Sie r1 nach rechts durch cl/#n, und füllen Sie die unteren Bits von r2/m. Das letzte ausgelagerte Bit wird im Carry platziert.
ROL |
r1, cl/#n |
Rotieren Sie r1 links durch cl/#n. |
ROR |
r1, cl/#n |
Drehen Sie r1 nach rechts durch cl/#n. |
RCL |
r1, cl/#n |
Rotieren Sie r1/C links von cl/#n. |
RCR |
r1, cl/#n |
Rotieren Sie r1/C nach rechts durch cl/#n. |
Die Drehung ähnelt der Verschiebung, mit dem Unterschied, dass die bits, die verschoben werden, als die eingehenden Füllbits wieder angezeigt werden. In der C-Sprachversion der Drehanweisungen wird das Carry-Bit in die Drehung integriert.
BT |
r1, r2/#n |
Kopieren Sie bit r2/#n von r1 in carry. |
BTS |
r1, r2/#n |
Legen Sie bit r2/#n von r1 fest, kopieren Sie den vorherigen Wert in carry. |
BTC |
r1, r2/#n |
Löschen Sie bit r2/#n von r1, kopieren Sie den vorherigen Wert in carry. |
Ablaufsteuerung
Jcc |
Dest |
Branch bedingt. |
|
JMP |
Dest |
Direkt springen. |
|
JMP |
r/m |
Indirekter Sprung. |
|
CALL |
Dest |
Rufen Sie direkt an. |
|
* |
CALL |
r/m |
Indirekt aufrufen. |
Die Anrufanweisung pusht die Rückgabeadresse auf den Stapel und springt dann zum Ziel.
* |
RET |
#n |
Rückgabewert |
Die ret-Anweisung springt und springt zur Rückgabeadresse im Stapel. Ein nonzero #n in der RET-Anweisung gibt an, dass nach dem Poppen der Rückgabeadresse der Wert #n dem Stapelzeiger hinzugefügt werden soll.
SCHLEIFE |
Dekrementieren Sie ecx , und springen Sie, wenn das Ergebnis nicht zero ist. |
LOOPZ |
Dekrementieren Sie ecx , und springen Sie, wenn das Ergebnis nonzero ist und zr festgelegt wurde. |
LOOPNZ |
Dekrementieren Sie ecx und springen Sie, wenn das Ergebnis nicht zero und zr eindeutig ist. |
JECXZ |
Springen, wenn ecx 0 ist. |
Diese Anweisungen sind Reste des CISC-Erbes des x86 und sind in den letzten Prozessoren tatsächlich langsamer als die entsprechenden Anweisungen, die auf langem Weg geschrieben wurden.
Zeichenfolgenbearbeitung
MOVST |
Verschieben Sie T von esi zu edi. |
|
CMPST |
Vergleichen Sie T from esi mit edi. |
|
SCAST |
Scan T from edi for accT. |
|
LODST |
Laden Sie T von esi in gemäßT. |
|
STOST |
Store T to edi from accT. |
Nach der Ausführung des Vorgangs werden das Quell- und Zielregister entsprechend der Einstellung des Richtungsflags (nach oben oder unten) durch sizeof(T) erhöht oder dekrementiert.
Die Anweisung kann durch REP präfixiert werden, um den Vorgang in der vom ecx-Register angegebenen Anzahl von Zeiten zu wiederholen.
Die Rep mov-Anweisung wird verwendet, um Speicherblöcke zu kopieren.
Die Rep stos-Anweisung wird verwendet, um einen Speicherblock mit accT zu füllen.
Flaggen
LAHF |
Laden Sie ah aus Flags. |
SAHF |
Speichern Sie ah in Flags. |
STC |
Legen Sie "carry" fest. |
CLC |
Klares Tragen. |
CMC |
Komplement tragen. |
STD |
Legen Sie die Richtung auf nach unten fest. |
CLD |
Richten Sie die Richtung nach oben ein. |
STI |
Aktivieren Sie Interrupts. |
Befehlszeilenschnittstelle (CLI) |
Deaktivieren Sie Interrupts. |
Ineinandergreifen von Anweisungen
XCHG |
r1, r/m |
Tauschen Sie r1 und r/m aus. |
XADD |
r1, r/m |
Fügen Sie r1 zu r/m hinzu, und geben Sie den ursprünglichen Wert in r1 ein. |
CMPXCHG |
r1, r/m |
Bedingtes Vergleichen und Austauschen. |
Die cmpxchg-Anweisung ist die atomische Version der folgenden:
cmp accT, r/m
jz match
mov accT, r/m
jmp done
match:
mov r/m, r1
done:
Sonstige
INT |
#n |
Trap to Kernel. |
|
GEBUNDEN |
r, m |
Trap, wenn r nicht im Bereich liegt. |
|
* |
NOP |
Keine Operation. |
|
XLATB |
al = [ebx + al] |
||
BSWAP |
r |
Bytereihenfolge im Register austauschen. |
Hier ist ein Sonderfall der int-Anweisung .
INT |
3 |
Debugger-Breakpoint-Trap. |
Der Opcode für INT 3 ist 0xCC. Der Opcode für NOP ist 0x90.
Beim Debuggen von Code müssen Sie möglicherweise code patchen. Sie können dies tun, indem Sie die verletzenden Bytes durch 0x90 ersetzen.
Idiome
XOR |
r, r |
r = 0 |
|
TEST |
r, r |
Überprüfen Sie, ob r = 0 ist. |
|
* |
ADD |
r, r |
Verschieben Sie r um 1 nach links. |