Différence d'instruction x86 CMP
-
02-10-2019 - |
Question
Question
Quelle est la (non trivial) différence entre les deux instructions suivantes x86?
39 /r CMP r/m32,r32 Compare r32 with r/m32
3B /r CMP r32,r/m32 Compare r/m32 with r32
Historique
Je construis un assembleur Java, qui sera utilisé par le langage intermédiaire de mon compilateur pour produire des exécutables Windows 32.
Actuellement, j'ai code suivant:
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();
Pour fournir en sortie un fichier exécutable valide, qui contient deux instruction CMP dans un texte de section. L'exécutable émis vers « text.exe » fera intéressant rien, mais ce n'est pas le point. La Compare
de classe est une enveloppe autour de l'instruction CMP
.
Le code ci-dessus produit (inspection avec OllyDbg):
Address Hex dump Command
0040101F |. 3BC8 CMP ECX,EAX
00401021 |. 3BC1 CMP EAX,ECX
La différence est subtile: si j'utilise l'octet de code opération 39
:
Address Hex dump Command
0040101F |. 39C1 CMP ECX,EAX
00401021 |. 39C8 CMP EAX,ECX
Ce qui me fait me demande au sujet de leur synonymie et pourquoi cela existe.
La solution
Il n'a pas d'importance que vous utilisez opcode si vous comparez deux registres. La seule différence est lorsque l'on compare un registre avec un opérande de mémoire, comme l'opcode utilisé détermine qui sera soustrait à partir de laquelle.
Quant à savoir pourquoi cela existe: Le format d'instruction x86 utilise l'octet ModR / M pour désigner soit une adresse mémoire ou un registre. Chaque instruction ne peut avoir qu'une seule valeur ModR / M, ce qui signifie qu'il ne peut accéder d'une adresse mémoire (non compris les instructions spéciales comme MOVSB). Cela signifie donc qu'il ne peut y avoir une instruction de cmp r/m32, r/m32
générale, et nous avons besoin de deux opcodes différents: cmp r/m32, r32
et cmp r32, r/m32
. Comme un effet secondaire, ce qui crée une certaine redondance lorsque l'on compare deux registres.
Autres conseils
redondance x86 . Il y a beaucoup plus de cas comme celui-ci. Un compilateur / assembleur est libre d'utiliser l'une quelconque des opcodes valides
Certains assembleur vous permet de choisir opcode d'émettre. Par exemple sur GAS vous pouvez attacher « .s » d'utiliser l'autre encodage d'instructions
10 de adcb %bl,%dh
12 f3 adcb.s %bl,%dh
CMP ECX, EAX est ECX-EAX et CMP EAX, ECX est EAX-ECX. Les indicateurs sont définis différemment selon opérande est comparée à qui. Bien sûr, vous pourriez probablement avec seulement un d'entre eux, s'il n'y avait pas la structure m r mod / x86 instructions.