2010-05-03 15 views
12

Fragex86 CMP Instruction Difference

Was ist der (nicht-triviale) Unterschied zwischen den folgenden zwei x86-Befehle?

39 /r CMP r/m32,r32 Compare r32 with r/m32 
3B /r CMP r32,r/m32 Compare r/m32 with r32 

Hintergrund

Ich baue eine Java-Assembler, die von meinem Compiler Zwischensprache verwendet werden, wird Windows-32 ausführbaren Dateien zu erzeugen.

Zur Zeit habe ich folgenden Code:

final ModelBase mb = new ModelBase(); // create new memory model 
mb.addCode(new Compare(Register.ECX, Register.EAX)); // add code 
mb.addCode(new Compare(Register.EAX, Register.ECX)); // add code 

final FileOutputStream fos = new FileOutputStream(new File("test.exe")); 
mb.writeToFile(fos); 
fos.close(); 

Zur Ausgabe einer gültige ausführbare Datei, die in einem TEXT-Abschnitt zwei CMP-Befehl enthält. Die ausführbare Datei, die an "text.exe" ausgegeben wird, wird nichts Interessantes tun, aber das ist nicht der Punkt. Die Klasse Compare ist ein Wrapper um die CMP Anweisung.

Der obige Code erzeugt (Inspektion mit OllyDbg):

Address Hex dump     Command 
0040101F |. 3BC8     CMP ECX,EAX 
00401021 |. 3BC1     CMP EAX,ECX 

Der Unterschied ist subtil: wenn ich den 39 Byte-Opcode:

Address Hex dump     Command 
0040101F |. 39C1     CMP ECX,EAX 
00401021 |. 39C8     CMP EAX,ECX 

Was ich über ihren synonymity macht mich fragen und warum das überhaupt existiert.

Antwort

18

Es spielt keine Rolle, die Sie Opcode verwenden, wenn Sie zwei Register vergleichen. Der einzige Unterschied ist, wenn ein Register mit einem Speicheroperanden verglichen wird, da der verwendete Opcode bestimmt, welche davon subtrahiert wird.

Was, warum diese vorhanden ist: Das x86-Befehlsformat des ModR/M-Byte verwendet entweder eine Speicheradresse oder ein Register zu bezeichnen. Jeder Befehl kann nur einen ModR/M-Wert haben, dh er kann nur auf eine Speicheradresse zugreifen (ohne spezielle Anweisungen wie MOVSB). Dies bedeutet also, dass es nicht um eine allgemeine cmp r/m32, r/m32 Anweisung sein kann, und wir brauchen zwei verschiedene Opcodes: cmp r/m32, r32 und cmp r32, r/m32. Als Nebeneffekt erzeugt dies eine gewisse Redundanz beim Vergleich von zwei Registern.

+7

Diese 1-Bit-Freiheitsgrade bieten auch einen verborgenen Kanal für Compiler zum "Telefonieren nach Hause" - sie können die von ihnen produzierten Binärdateien "markieren", und der Compiler-Anbieter kann Sie bitten, zu erklären, ob sie Ihre Software mit ihrem Wasserzeichen finden, aber ohne Lizenz in Datei. –

2

CMP ECX, EAX ist ECX-EAX und CMP EAX, ECX ist EAX-ECX. Die Flags werden abhängig davon, mit welchem ​​Operanden verglichen wird, unterschiedlich gesetzt. Natürlich könntest du wahrscheinlich nur mit einem von ihnen davonkommen, wenn es nicht die mod/r-m-Struktur von x86-Instruktionen gäbe.

+1

Der Punkt ist, dass Sie die gleiche mnemonic auf zwei verschiedene Arten kodieren, können verwendet werden, weil es für 'cmp r/m, r eine andere Opcode ist 'und' cmp r, r/m'. Die Frage ist, ob der Operand in MOD/RM, der ein Speicheroperand sein kann, src1 oder src2 ist, und das hängt vom Opcode ab. –

3

Es ist redundancy of x86. Es gibt viel mehr Fälle wie dieses. Ein Compiler/Assembler ist frei auf alle gültigen Opcodes Sie die Opcode zu emittieren zu wählen

Einige Assembler erlaubt zu verwenden. Zum Beispiel auf GAS können Sie „.s“ Die anderen Befehlscodierung

10 de adcb %bl,%dh 
12 f3 adcb.s %bl,%dh