Verwenden Sie spezielle Kurzformkodierungen für AL / AX / EAX sowie andere Kurzformen und Einzelbyte-Anweisungen
Bei den Beispielen wird der 32/64-Bit-Modus angenommen, bei dem die Standardoperandengröße 32 Bit beträgt. Ein Präfix mit Operandengröße ändert den Befehl in AX anstelle von EAX (oder umgekehrt im 16-Bit-Modus).
inc/decein Register (außer 8-Bit): inc eax/ dec ebp. (Nicht x86-64: Die 0x4xOpcode-Bytes wurden als REX-Präfixe verwendet. Dies inc r/m32ist die einzige Codierung.)
8-Bit - inc bl2 Byte, unter Verwendung des inc r/m8opcode + ModR / M - Operanden kodieren . So verwenden inc ebxzu erhöhen bl, wenn es sicher ist. (zB wenn Sie das ZF-Ergebnis nicht benötigen, wenn die oberen Bytes möglicherweise nicht Null sind).
scasd: e/rdi+=4, erfordert, dass das Register auf einen lesbaren Speicher zeigt. Manchmal nützlich, auch wenn Sie sich nicht für das FLAGS-Ergebnis interessieren (wie cmp eax,[rdi]/ rdi+=4). Und im 64-Bit-Modus scasbkann als 1-Byte arbeiteninc rdi , wenn lodsb oder stosb nicht nützlich sind.
xchg eax, r32: Hier wird von 0x90 NOP kam: xchg eax,eax. Beispiel: 3 Register mit zwei xchgBefehlen in einer cdq/ idiv-Schleife für GCD in 8 Bytes neu anordnen, wobei die meisten Befehle Einzelbytes sind, einschließlich eines Missbrauchs von inc ecx/ loopanstelle von test ecx,ecx/jnz
cdq: Vorzeichenerweiterung von EAX in EDX: EAX, dh Kopieren des hohen EAX-Bits in alle EDX-Bits. Um eine Null mit bekannten nicht-negativen Werten zu erstellen, oder um eine 0 / -1 zu erhalten, mit der / sub oder maskiert wird. x86-Geschichtsstunde: cltqvs.movslq , und auch AT & T vs. Intel-Mnemonics für diese und die verwandten cdqe.
lodsb / d : like mov eax, [rsi]/ rsi += 4without clobbering flags. (Angenommen, DF ist klar, welche Standardaufrufkonventionen für die Funktionseingabe erforderlich sind.) Außerdem stosb / d, manchmal scas und seltener movs / cmps.
push/ pop reg. ZB im 64-Bit-Modus ist push rsp/ pop rdi2 Byte, mov rdi, rspbenötigt aber ein REX-Präfix und ist 3 Byte.
xlatbexistiert, ist aber selten nützlich. Eine große Nachschlagetabelle sollte vermieden werden. Ich habe auch noch nie eine Verwendung für AAA / DAA oder andere gepackte BCD- oder 2-ASCII-Ziffern-Anweisungen gefunden.
1 Byte lahf/ sahfsind selten nützlich. Sie könnten lahf / and ah, 1als Alternative zu setc ah, aber es ist in der Regel nicht nützlich.
Und speziell für CF gibt sbb eax,eaxes eine 0 / -1 oder sogar eine nicht dokumentierte, aber universell unterstützte 1-Byte-Größe salc(setze AL von Carry), die effektiv keine sbb al,alAuswirkung auf Flags hat. (In x86-64 entfernt). Ich habe SALC in der User Appreciation Challenge # 1 verwendet: Dennis ♦ .
1-Byte cmc/ clc/ stc(Flip ("Komplement"), Clear oder Set CF) sind selten nützlich, obwohl ich eine Verwendung für einecmc Addition mit erweiterter Genauigkeit mit Basis 10 ^ 9-Chunks gefunden habe. Um CF bedingungslos zu setzen / löschen, lassen Sie dies normalerweise als Teil eines anderen Befehls geschehen, z. B. xor eax,eaxCF und EAX löschen. Es gibt keine entsprechenden Anweisungen für andere Bedingungsflags, nur DF (Zeichenfolgenrichtung) und IF (Interrupts). Das Carry Flag ist speziell für viele Anweisungen. Shifts setzen es, adc al, 0können es in 2 Byte zu AL hinzufügen, und ich erwähnte zuvor die undokumentierte SALC.
std/ cldScheinen selten wert . Insbesondere im 32-Bit-Code ist es besser, nur deceinen Zeiger und einen movoder einen Speicherquellenoperanden für einen ALU-Befehl zu verwenden, anstatt DF so zu setzen lodsb/ stosbnach unten statt nach oben zu gehen. Normalerweise , wenn Sie nach unten überhaupt brauchen, haben Sie noch einen anderen Zeiger geht nach oben, so dass Sie mehr brauchen würden als eine stdund cldin der gesamten Funktion Verwendung lods/ stosfür beide. Verwenden Sie stattdessen einfach die Zeichenfolgenanweisungen für die Aufwärtsrichtung. (Die Standardaufrufkonventionen garantieren DF = 0 bei der Funktionseingabe, sodass Sie davon ausgehen können, dass dies ohne Verwendung von kostenlos ist cld.)
8086 history: Warum gibt es diese Kodierungen?
Im Original 8086 war AX ganz Besonderes: Anweisungen wie lodsb/ stosb, cbw, mul/ divund andere implizit verwenden. Das ist natürlich immer noch der Fall; Der aktuelle x86 hat keinen der 8086-Opcodes gelöscht (zumindest keinen der offiziell dokumentierten). Spätere CPUs fügten neue Anweisungen hinzu, die bessere / effizientere Möglichkeiten boten, Dinge zu erledigen, ohne sie zuerst in AX zu kopieren oder zu tauschen. (Oder zu EAX im 32-Bit-Modus.)
Zum Beispiel fehlten bei 8086 spätere Zusätze wie movsx/ movzxzum Laden oder Verschieben + Vorzeichen-Erweitern oder 2- und 3-Operanden imul cx, bx, 1234, die kein High-Half-Ergebnis liefern und keine impliziten Operanden haben.
Auch 8086 Haupt Engpass war Befehl holen, so die Optimierung für die Code-Größe wichtig war für die Leistung damals . Der ISA-Designer von 8086 (Stephen Morse) hat viel Opcode -Code für Sonderfälle für AX / AL ausgegeben, einschließlich spezieller (E) AX / AL-Ziel-Opcodes für alle grundlegenden ALU-Anweisungen von src , nur opcode + instant ohne ModR / M-Byte. 2 Byte add/sub/and/or/xor/cmp/test/... AL,imm8oder AX,imm16oder (im 32-Bit-Modus) EAX,imm32.
Es gibt jedoch keinen Sonderfall für EAX,imm8, sodass die reguläre ModR / M-Codierung add eax,4kürzer ist.
Es wird davon ausgegangen, dass Sie einige Daten in AX / AL bearbeiten möchten. Daher sollten Sie ein Register mit AX tauschen, vielleicht sogar öfter, als ein Register mit AX zu kopierenmov .
Alles, was mit der 8086-Befehlskodierung zu tun hat, unterstützt dieses Paradigma, angefangen von Befehlen lodsb/wüber alle Sonderfallkodierungen für Direktbefehle mit EAX bis hin zur impliziten Verwendung auch für Multiplikationen / Divisionen.
Lass dich nicht mitreißen; Es ist nicht automatisch ein Gewinn, alles zu EAX zu tauschen, besonders wenn Sie Sofort mit 32-Bit-Registern anstelle von 8-Bit verwenden müssen. Oder wenn Sie Operationen mit mehreren Variablen in Registern gleichzeitig verschachteln müssen. Oder wenn Sie Anweisungen mit 2 Registern verwenden, nicht sofort.
Aber denken Sie immer daran: Tue ich irgendetwas, das in EAX / AL kürzer wäre? Kann ich neu anordnen, damit ich dies in AL habe, oder nutze ich derzeit AL besser mit dem, wofür ich es bereits benutze?
Mischen Sie 8-Bit- und 32-Bit-Operationen frei, um die Vorteile zu nutzen, wann immer dies sicher ist (Sie müssen nicht in das vollständige Register oder was auch immer übertragen).
push 200; pop edxzu initialisieren, verwenden Sie zB - 3 Byte für die Initialisierung.