2010-05-03 21 views
12

Questionx86 CMP Différence d'instructions

Quel est le (non trivial) différence entre les deux instructions x86 suivantes?

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

Contexte

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 le 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 produire un fichier exécutable valide, qui contient deux instructions CMP dans un texte de section. L'exécutable sorti en "text.exe" ne fera rien d'intéressant, mais ce n'est pas le but. La classe Compare est un wrapper autour de l'instruction CMP.

Le code ci-dessus produit (inspectait avec OllyDbg):

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

La différence est subtile: si j'utilise le 39 octet opcode:

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 même.

Répondre

18

Peu importe l'opcode que vous utilisez si vous comparez deux registres. La seule différence est lors de la comparaison d'un registre avec un opérande de mémoire, car l'opcode utilisé détermine lequel sera soustrait de laquelle. Pour savoir pourquoi cela existe: Le format d'instruction x86 utilise l'octet ModR/M pour désigner une adresse mémoire ou un registre. Chaque instruction ne peut avoir qu'une seule valeur ModR/M, ce qui signifie qu'elle ne peut accéder qu'à une seule adresse mémoire (sans inclure les instructions spéciales comme MOVSB). Cela signifie donc qu'il ne peut y avoir une instruction générale cmp r/m32, r/m32, et nous avons besoin de deux opcodes différents: cmp r/m32, r32 et cmp r32, r/m32. Comme effet secondaire, cela crée une redondance lors de la comparaison de deux registres.

+7

Ces degrés de liberté de 1 bit fournissent également un canal caché pour que les compilateurs puissent "téléphoner à la maison" - ils peuvent "filigraner" les binaires qu'ils produisent, et le fournisseur du compilateur peut vous demander s'il trouve votre logiciel avec son filigrane, mais sans licence dans le fichier. –

2

CMP ECX, EAX est ECX-EAX et CMP EAX, ECX est EAX-ECX. Les drapeaux sont définis différemment en fonction de l'opérande qui est comparé à quoi. Bien sûr, vous pourriez probablement vous en passer avec un seul d'entre eux s'il n'y avait pas la structure mod/r-m des instructions x86.

+1

Le point est que vous pouvez coder la même mnémonique de deux façons différentes parce qu'il ya un autre opcode pour 'cmp r/m, r 'et' cmp r, r/m'. La question est de savoir si l'opérande dans MOD/RM qui peut être un opérande de mémoire est src1 ou src2, et cela dépend de l'opcode. –

3

C'est redundancy of x86. Il y a beaucoup plus de cas comme celui-ci. Un compilateur/assembleur est libre d'utiliser l'un des opcodes valides

Certains assembleurs vous permettent de choisir quel opcode émettre. Par exemple sur GAS vous pouvez attacher « .s » d'utiliser l'autre instruction de codage

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