2010-05-03 18 views
12

Pytaniex86 CMP Instrukcja Różnica

Jaki jest (nietrywialne) różnica między dwiema następującymi instrukcjami x86?

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

Tło

Buduję asembler Java, który będzie używany przez mojego języka pośredniego kompilatora produkować Windows 32 wykonywalnych.

Obecnie mam następujący kod:

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(); 

Do wyjścia prawidłowy plik wykonywalny, który zawiera dwa instrukcji CMP w tekście poprzecznym. Plik wykonywalny wypisany na "text.exe" nie zrobi nic ciekawego, ale nie o to chodzi. Klasa Compare jest opakowaniem instrukcji CMP.

Powyższy kod tworzy (kontroli z OllyDbg):

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

Różnica jest subtelna: jeśli używam 39 bajt opcodu:

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

co sprawia, że ​​zastanawiam się o ich synonymity i dlaczego to nawet istnieje.

Odpowiedz

18

Nie ma znaczenia, którego opodu użyjesz do porównania dwóch rejestrów. Jedyna różnica polega na porównaniu rejestru z operandem pamięci, ponieważ używany kod operacyjny określa, od którego będzie odjęty.

Co do tego, dlaczego tak się dzieje: Format instrukcji x86 używa bajtu ModR/M do oznaczenia adresu pamięci lub rejestru. Każda instrukcja może mieć tylko jedną wartość ModR/M, co oznacza, że ​​może uzyskać dostęp tylko do jednego adresu pamięci (bez specjalnych instrukcji, takich jak MOVSB). Oznacza to, że nie może istnieć ogólna instrukcja cmp r/m32, r/m32 i potrzebujemy dwóch różnych kodów operacji: cmp r/m32, r32 i cmp r32, r/m32. Jako efekt uboczny tworzy to pewną redundancję podczas porównywania dwóch rejestrów.

+7

Te 1-bitowe stopnie swobody zapewniają również ukryty kanał dla kompilatorów do "telefonu domowego" - mogą "znakować" "binariami, które produkują, a sprzedawca kompilatorów może poprosić cię o wyjaśnienie, czy znajdują twoje oprogramowanie z ich znakiem wodnym, ale bez licencji na plik. –

2

CMP ECX, EAX to ECX-EAX i CMP EAX, ECX to EAX-ECX. Flagi ustawiane są różnie w zależności od tego, do którego argumentu jest porównywany operand. Oczywiście prawdopodobnie uda ci się uciec z jednym z nich, gdyby nie struktura mod/r-m instrukcji x86.

+1

Chodzi o to, że można kodować ten sam mnemoniczną na dwa różne sposoby, bo tam jest inny kod operacji dla 'CMP R/m, r 'i' cmp r, r/m'. Pytanie brzmi, czy operand w MOD/RM, który może być operandem pamięci, to src1 lub src2, a to zależy od kodu operacyjnego. –

3

Jest to redundancy of x86. Jest o wiele więcej takich przypadków. Kompilator/asembler może używać dowolnych z poprawnych kodów operacji. Niektóre asemblery pozwalają wybrać, który opcode ma być emitowany. Na przykład na gaz można dołączyć „.S”, aby korzystać z innych kodującego dyspozycję

10 de adcb %bl,%dh 
12 f3 adcb.s %bl,%dh 
Powiązane problemy