Jak odczytać notację Intel Opcode

Czytam materiał o Opcodach Intela instrukcji montażu, ale nie mogę zrozumieć, co to znaczy, że podąża za bajtem opcode. Na przykład: cw, cd, /2, cp, /3.

Proszę dać mi podpowiedź co to znaczy lub Gdzie mogę znaleźć pełne odniesienie ?

E8 cw CALL rel16 Call near, relative, displacement relative to next instruction
E8 cd CALL rel32 Call near, relative, displacement relative to next instruction
FF /2 CALL r/m16 Call near, absolute indirect, address given in r/m16
FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32
9A cd CALL ptr16:16 Call far, absolute, address given in operand
9A cp CALL ptr16:32 Call far, absolute, address given in operand
FF /3 CALL m16:16 Call far, absolute indirect, address given in m16:16
FF /3 CALL m16:32 Call far, absolute indirect, address given in m16:32
Author: phuclv, 2013-02-22

3 answers

Moim ulubionym źródłem jest sam Intel: Intel® 64 i IA-32 Architectures Software Developer Manuals. W przeciwieństwie do poprzednich wersji, wszystkie tomy są teraz ładnie zapakowane w jeden (3044 strona) PDF.

Wygląda na to, że sekcja, która najbardziej Ci pomoże, to 3.1.1.1 w Rozdziale 3 tomu 2 (strona 432 najnowszego PDF z dnia, w którym to piszę).

 19
Author: DocMax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-22 05:48:07

3.1.1.1 Kolumna Opcode w tabeli podsumowania instrukcji (instrukcje bez prefiksu VEX)

Kolumna "Opcode" w powyższej tabeli pokazuje kod obiektowy wytworzony dla każdej formy instrukcji. Jeśli to możliwe, kody są podawane w postaci szesnastkowych bajtów w tej samej kolejności, w jakiej pojawiają się w pamięci. Definicje zapisów innych niż szesnastkowe są następujące:

• REX.W - wskazuje użycie prefiksu REX, który wpływa na rozmiar operandu lub instrukcji semantyka. Kolejność prefiksu REX i innych opcjonalnych / obowiązkowych prefiksów instrukcji omówiono w rozdziale 2. Zauważ, że prefiksy REX, które promują starsze instrukcje do zachowania 64-bitowego, nie są wyraźnie wymienione w kolumnie kod opcode.

• /digit - cyfra od 0 do 7 oznacza, że bajt ModR / m instrukcji używa tylko operandu R / M (rejestru lub pamięci). Pole reg zawiera cyfrę, która stanowi rozszerzenie instrukcji kod opcode.

• /r - wskazuje, że bajt ModR / m instrukcji zawiera operand rejestru i operand r / m.

• CB, CW, cd, CP, co, ct - wartość 1-bajtowa (cb), 2-bajtowa (cw), 4-bajtowa (cd), 6-bajtowa (cp), 8-bajtowa (co) lub 10-bajtowa (ct) po kodzie opcode. Wartość ta jest używana do określenia offsetu kodu i ewentualnie nowej wartości dla rejestru segmentów kodu.

• ib, iw, id, io - A 1-bajtowy (ib), 2-bajtowy (iw), 4-bajtowy (id) lub 8-bajtowy (io) operand do instrukcji podążającej za kodem opcode, bajtami ModR/m lub bajtami indeksującymi skalę. Kod opcode określa, czy operand jest podpisaną wartością. Wszystkie słowa, doublewords i quadwords są podane najpierw z bajtem niskiego rzędu.

• +Rb, +rw, +rd, +ro - wskazuje, że dolne 3 bity bajtu opcode są używane do kodowania operandu rejestru bez bajtu modR/M. Instrukcja wyświetla odpowiadającą jej wartość szesnastkową bajtu kodu opcode z niskimi 3 bitami jako 000b. w trybie nie-64-bitowym, kod rejestru, od 0 do 7, jest dodawany do szesnastkowej wartości bajtu kodu opcode. W trybie 64-bitowym wskazuje 4-bitowe pole REX.pole B i opcode[2:0] koduje operand rejestru instrukcji. "+ro " Ma zastosowanie tylko w trybie 64-bitowym. Kody znajdują się w tabeli 3-1.

• +i- Liczba używana w instrukcjach zmiennoprzecinkowych, gdy jednym z operandów jest ST(i) ze stosu rejestru FPU. Liczba i (która może wynosić od 0 do 7) jest dodawana do bajtu szesnastkowego podany po lewej stronie znaku plus tworzy pojedynczy bajt kodu OPC.

3.1.1.3 Kolumna instrukcji w tabeli podsumowującej Kod Opcode

Kolumna "Instruction" podaje składnię instrukcji tak, jak wyglądałaby w programie ASM386.

Poniżej znajduje się lista symboli używanych do reprezentowania operandów w instrukcjach:

• rel8- względny adres w zakresie od 128 bajtów przed końcem instrukcji do 127 bajtów po zakończeniu nauki.

• rel16, rel32- względny adres w obrębie tego samego segmentu kodu co złożona Instrukcja. Symbol rel16 ma zastosowanie do instrukcji z atrybutem operand-size wynoszącym 16 bitów; symbol rel32 ma zastosowanie do instrukcji z atrybutem operand-size wynoszącym 32 bity.

• ptr16: 16, ptr16: 32- daleki wskaźnik, zazwyczaj do segmentu kodu innego niż instrukcja. Zapis 16:16 wskazuje, że wartość wskaźnik ma dwie części. Wartość po lewej stronie dwukropka jest 16-bitowym selektorem lub wartością przeznaczoną dla rejestru segmentów kodu. Wartość po prawej odpowiada przesunięciu w segmencie docelowym. Symbol ptr16:16 jest używany, gdy atrybut operand-size instrukcji wynosi 16 bitów; symbol ptr16: 32 jest używany, gdy atrybut operand-size wynosi 32 bity.

• r8- jeden z bajtów rejestrów ogólnego przeznaczenia: AL, CL, DL, BL, AH, CH, DH, BH, BPL, SPL, Dil i SIL; lub jeden z rejestrów bajtowych (R8L - R15L) dostępny przy użyciu systemu REX.R i tryb 64-bitowy.

• r16 - jeden ze słownych rejestrów ogólnego przeznaczenia: AX, CX, DX, BX, SP, BP, SI, DI; lub jeden ze słownych rejestrów (R8-R15) dostępnych przy użyciu REX.R i tryb 64-bitowy.

• R32- jeden z rejestrów ogólnego przeznaczenia doubleword: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI; lub jeden z rejestrów doubleword (R8D - R15D) dostępnych podczas korzystania z REX.R w trybie 64-bitowym.

• r64- jeden z czworokątnych rejestrów ogólnego przeznaczenia: RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8–R15. Są one dostępne podczas korzystania z REX.R i tryb 64-bitowy.

• imm8- natychmiastowa wartość bajtu. Symbol imm8 jest liczbą podpisaną w przedziale od -128 do +127 włącznie. W przypadku instrukcji, w których imm8 jest łączone z operandem word lub doubleword, wartość natychmiastowa jest rozszerzana o znak, tworząc słowo lub doubleword. Górny bajt słowa wypełniony jest najwyższym bitem wartość natychmiastowa.

• imm16- natychmiastowa wartość słowa używana dla instrukcji, których atrybut operand-size wynosi 16 bitów. Jest to liczba od -32,768 do +32,767 włącznie.

• imm32- natychmiastowa wartość doubleword używana dla instrukcji, których atrybut operand-size wynosi 32 bity. Pozwala na użycie liczby od +2,147,483,647 do -2,147,483,648 włącznie.

• imm64- natychmiastowa wartość quadword używana dla instrukcji, których rozmiar operandu atrybut to 64 bity. Wartość pozwala na użycie liczby między +9,223,372,036,854,775,807 i -9,223,372,036,854,775,808 włącznie.

• r / M8 - bajtowy operand, który jest albo zawartością bajtowego rejestru ogólnego przeznaczenia (AL, CL, DL, BL, AH, CH, DH, BH, BPL, SPL, Dil i SIL) albo bajtem z pamięci. Rejestry bajtowe R8L-R15L są dostępne przy użyciu systemu REX.R w trybie 64-bitowym.

• r / M16 - Słowo rejestr ogólnego przeznaczenia lub operand pamięci używany do instrukcji którego atrybut operand-size wynosi 16 bitów. Słowa rejestry ogólnego przeznaczenia to: AX, CX, DX, BX, SP, BP, SI, DI. Zawartość pamięci znajduje się pod adresem podanym przez efektywne obliczenia adresowe. Rejestry słów R8W-R15W są dostępne za pomocą systemu REX.R w trybie 64-bitowym.

• r / M32 - dwukierunkowy rejestr ogólnego przeznaczenia lub operand pamięci używany dla instrukcji, których atrybut rozmiaru operandu wynosi 32 bity. Rejestry podwójnego zastosowania to: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI. Zawartość pamięci znajduje się pod adresem podanym przez efektywne obliczenia adresowe. Rejestry Doubleword R8D - R15D są dostępne podczas korzystania z systemu REX.R w trybie 64-bitowym.

• r / M64 - quadword operand ogólnego przeznaczenia lub operand pamięci używany dla instrukcji, których atrybut operand-size wynosi 64 bity podczas używania REX.W. rejestry ogólnego przeznaczenia Quadword to: RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP, R8-R15; są one dostępne tylko w trybie 64–bitowym. Zawartość pamięć znajduje się pod adresem podanym przez efektywne obliczenia adresowe.

• m - 16 -, 32-lub 64-bitowy operand w pamięci.

• M8 - operand bajtowy w pamięci, zwykle wyrażany jako nazwa zmiennej lub tablicy, ale wskazywany przez rejestry DS:(E)SI lub ES:(E)DI. W trybie 64-bitowym jest wskazywany przez rejestry RSI lub RDI.

• M16 - operand wyrazowy w pamięci, zwykle wyrażany jako nazwa zmiennej lub tablicy, ale wskazywany przez DS:(E)SI lub ES: e) DI registres. Ta nomenklatura jest używana tylko z instrukcjami typu string.

• M32 - Podwójny operand w pamięci, zwykle wyrażany jako nazwa zmiennej lub tablicy, ale wskazywany przez rejestry DS:(E)SI lub ES:(E)DI. Ta nomenklatura jest używana tylko z instrukcjami typu string.

• m64- operand pamięci quadword w pamięci.

• m128- Podwójny quadword w pamięci.

• m16:16, m16:32 & M16:64- A operand pamięci zawierający wskaźnik daleki złożony z dwóch liczb. Liczba po lewej stronie dwukropka odpowiada selektorowi segmentów wskaźnika. Liczba po prawej odpowiada jej przesunięciu.

• m16&32, m16&16, M32&32, M16&64 - operand pamięci składający się z par pozycji danych, których rozmiary są wskazane Po Lewej i prawej stronie ampersand. Dozwolone są wszystkie tryby adresowania pamięci. Operandy m16 i 16 oraz M32 i 32 są używane przez instrukcję BOUND, aby zapewnić operand zawierający górną i dolną granicę indeksów tablicy. Operand m16 i 32 jest używany przez LIDT i LGDT do dostarczania słowa, za pomocą którego można załadować pole graniczne, oraz podwójnego słowa, za pomocą którego można załadować pole podstawowe odpowiednich rejestrów GDTR i IDTR. Operand m16 i 64 jest używany przez LIDT i LGDT w trybie 64-bitowym, aby dostarczyć słowo, za pomocą którego można załadować pole graniczne, oraz quadword, za pomocą którego można załadować pole podstawowe odpowiednich rejestrów GDTR i IDTR.

• moffs8, moffs16, moffs32, moffs64- prosta zmienna pamięci (przesunięcie pamięci) typu byte, word lub doubleword używana przez niektóre warianty instrukcji MOV. Rzeczywisty adres jest podawany przez proste przesunięcie względem bazy segmentu. W instrukcji nie jest używany żaden bajt ModR/M. Liczba pokazana za pomocą moffs wskazuje jej rozmiar, który jest określony przez atrybut address-size instrukcji.

• Sreg- rejestr segmentów. Przypisania bitów rejestru segmentów to ES = 0, CS = 1, SS = 2, DS = 3, FS = 4 i GS = 5.

• m32fp, m64fp, m80fp- operand zmiennoprzecinkowy o pojedynczej precyzji, podwójnej precyzji i podwójnej rozszerzonej precyzji (odpowiednio) w pamięci. Symbole te oznaczają wartości zmiennoprzecinkowe, które są używane jako operandy instrukcji zmiennoprzecinkowych FPU x87.

• m16int, m32int, m64int - a word, doubleword i quadword integer (odpowiednio) operand w pamięci. Symbole te oznaczają liczby całkowite, które są używane jako operandy dla Instrukcja FPU x87.

• ST lub ST (0) - górny element stosu rejestrów FPU.

• ST (i) - I-ty element od góry stosu rejestru FPU (i ← 0 do 7).

• mm - rejestr MMX. 64-bitowe rejestry MMX to: MM0 do MM7.

• mm / M32 - niski rozkaz 32 bitów rejestru MMX lub 32-bitowego operandu pamięci. 64-bitowe rejestry MMX to: MM0 do MM7. Zawartość pamięci znajduje się na adres podany przy efektywnym obliczaniu adresu.

• mm / M64 - rejestr MMX lub 64-bitowy operand pamięci. 64-bitowe rejestry MMX to: MM0 do MM7. Zawartość pamięci znajduje się pod adresem podanym przez efektywne obliczenia adresowe.

• XMM - rejestr XMM. 128-bitowe rejestry XMM to: XMM0 do XMM7; xmm8 do XMM15 są dostępne przy użyciu systemu REX.R w trybie 64-bitowym.

• XMM / M32- rejestr XMM lub 32-bitowa pamięć operand. 128-bitowe rejestry XMM to XMM0 do XMM7; xmm8 do XMM15 są dostępne za pomocą systemu REX.R w trybie 64-bitowym. Zawartość pamięci znajduje się pod adresem podanym przez efektywne obliczenia adresowe.

• XMM / M64 - rejestr XMM lub 64-bitowy operand pamięci. 128-bitowe rejestry zmiennoprzecinkowe SIMD to XMM0 do XMM7; xmm8 do XMM15 są dostępne za pomocą systemu REX.R w trybie 64-bitowym. Zawartość pamięci znajduje się pod adresem podanym przez efektywny adres obliczenia.

• XMM / M128 - rejestr XMM lub 128-bitowy operand pamięci. 128-bitowe rejestry XMM to XMM0 do XMM7; xmm8 do XMM15 są dostępne za pomocą systemu REX.R w trybie 64-bitowym. Zawartość pamięci znajduje się pod adresem podanym przez efektywne obliczenia adresowe.

• - wskazuje na domniemane użycie rejestru XMM0. Gdy istnieje niejednoznaczność, xmm1 wskazuje pierwszy operand źródłowy za pomocą rejestru XMM, a xmm2 drugi operand źródłowy za pomocą Rejestr XMM. Niektóre instrukcje używają rejestru XMM0 jako Trzeciego operandu źródłowego, wskazanego przez . Użycie trzeciego operandu rejestru XMM jest niejawne w kodowaniu instrukcji i nie wpływa na kodowanie ModR / M.

• YMM - rejestr YMM. 256-bitowe rejestry YMM to: YMM0 do YMM7; ymm8 do YMM15 są dostępne w trybie 64-bitowym.

• m256 - 32-bajtowy operand w pamięci. Ta nomenklatura jest używana tylko z instrukcjami AVX.

• YMM / M256 - rejestr YMM lub 256-bitowy operand pamięci.

• - wskazuje użycie rejestru ymm0 jako domyślnego argumentu.

• bnd- 128-bitowy rejestr granic. Bnd0 do BND3.

• mib- operand pamięci wykorzystujący adresację SIB, gdzie rejestr indeksu nie jest używany w obliczeniach adresów, Skala jest ignorowana. Tylko baza i przemieszczenie są używane w efektywnym obliczaniu adresów.

• m512 - 64-bajtowy operand w pamięć.

• zmm /M512 - rejestr ZMM lub 512-bitowy operand pamięci.

• {k1}{z}- rejestr maski używany jako instrukcja writemask. 64-bitowe rejestry k to: k1 do k7. Specyfikacja Writemask jest dostępna wyłącznie poprzez prefiks EVEX. Maskowanie może być wykonywane jako maskowanie scalające, gdzie stare wartości są zachowane dla elementów maskujących lub jako maskowanie zerujące. Rodzaj maskowania określa się za pomocą EVEX.z bit.

• {k1} - Bez {z}: rejestr mask używany jako instrukcja writemask dla instrukcji, które nie pozwalają zerować maskowania, ale wspierają scalanie-maskowanie. Odpowiada to instrukcjom, które wymagają, aby wartość pola aaa była inna niż 0 (np. gather) oraz instrukcjom typu store, które umożliwiają tylko scalanie-maskowanie.

• k1- rejestr maski używany jako zwykły operand (cel lub źródło). 64-bitowe rejestry k to: k0 do k7.

• mV - wektor operand pamięci; rozmiar operandu zależy od instrukcji.

• vm32{X,y, z} - wektorowa tablica operandów pamięci określona przy użyciu adresowania pamięci VSIB. Tablice adresów pamięci są określone za pomocą wspólnego rejestru bazowego, stałego współczynnika skali i rejestru indeksów wektorowych z pojedynczymi elementami o 32-bitowej wartości indeksu w rejestrze XMM( vm32x), rejestrze YMM (vm32y) lub rejestrze ZMM (vm32z).

• vm64{x,y, z} - wektorowa tablica pamięci operandów określonych przy użyciu adresowania pamięci VSIB. Tablice adresów pamięci są określone za pomocą wspólnego rejestru bazowego, stałego współczynnika skali i rejestru wektorowego z pojedynczymi elementami 64-bitowej wartości indeksu w rejestrze XMM (vm64x), rejestrze YMM (vm64y) lub rejestrze ZMM (vm64z).

• zmm / M512 /m32bcst - operand, który może być rejestrem ZMM, 512-bitową lokalizacją pamięci lub 512-bitowym wektorem ładowanym z 32-bitowej lokalizacji pamięci.

• zmm / M512 /m64bcst - operand, który może być rejestrem ZMM, 512-bitową lokalizacją pamięci lub 512-bitowym wektorem załadowanym z 64-bitowej lokalizacji pamięci.

• - wskazuje użycie rejestru ZMM0 jako domyślnego argumentu.

• {er} - wskazuje obsługę wbudowanej kontroli zaokrąglania, która ma zastosowanie tylko do formularza Rejestrowego instrukcji. Oznacza to również wsparcie dla SAE (eliminuje wszystkie wyjątki).

• {sae} - oznacza wsparcie dla SAE (Wyłącz wszystkie wyjątki). Jest to używane w przypadku instrukcji obsługujących SAE, ale nie obsługujących wbudowanej kontroli zaokrąglania.

• SRC1 - oznacza pierwszy operand źródłowy w składni instrukcji zakodowanej z prefiksem VEX / EVEX i posiadający dwa lub więcej operandów źródłowych.

• SRC2 - oznacza drugi argument źródłowy w składni instrukcji zakodowanej z prefiksem VEX / EVEX i posiadającej dwa lub więcej źródeł operands.

• SRC3 - oznacza trzeci operand źródłowy w składni instrukcji zakodowanej z prefiksem VEX / EVEX i posiadający trzy operandy źródłowe.

• SRC- źródło w instrukcji jednego źródła.

• DST- miejsce docelowe w instrukcji. To pole jest kodowane przez reg_field.

 24
Author: Markus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-06 01:31:15

Wiele opcodów do natychmiastowych wersji instrukcji, w tym 83, używa 3-bitowego pola /r w bajcie ModR/M jako 3 dodatkowe bity opcode . Intel ' s vol.2 Podręcznik dokumentuje to, a tabela kodów opcode w załączniku zawiera to, myślę.

Dlatego większość oryginalnych instrukcji-8086, takich jak and r/m, imm nadal zezwala tylko na 2 operandy, w przeciwieństwie do shrd eax, edx, 4 lub imul edx, [rdi], 12345, gdzie oba pola ModRM są używane do kodowania operandów DST / src, jak również kod opcode sugerujący natychmiastowe operand.

Shrd / SHLD i zostały dodane z 386, a imul-immediate został dodany z 186. To może niefortunne, że copy-and-AND (and eax, edx, 0xf) nie jest kodowalne, ale przynajmniej x86 może używać LEA do bardzo powszechnych operacji kopiowania i dodawania lub pod-operacji.

Ale gdyby każda natychmiastowa i jednooperandowa instrukcja (jak push lub not) wymagała pełnego kodu dla siebie, 8086 skończyłoby się 1-bajtowymi kodami opcodów. (Zwłaszcza, że projektant zdecydował się poświęcić dużo miejsca na kodowanie na krótkie formaty bez bajtów modrm dla AL i AX, jak cmp ax, 12345 jest tylko 3 bajty zamiast 4 w trybie 16-bitowym, lub cmp eax, imm32 jest tylko 5 bajtów zamiast 6 dla cmp r/m32, imm32 w trybie 32-bitowym. Oraz dla jednobajtowego rejestru xchg-with-ax i jednobajtowego rejestru inc / dec.)


Przykład: dekodowanie 48 83 C4 38. (z jak jeden bajt opcode dekoduje się do różnych instrukcji w zależności od pola "register / opcode"? Co to jest?, duplikat tego Q)

48 to REX.Przedrostek W (REX with tylko ustawiony bit W, więc wskazuje 64-bitowy rozmiar operandu, ale bez wysokich rejestrów).

Opcode 83 mówi, że może to być 7 różnych instrukcji w zależności od pola o nazwie "register / opcode field"

Każda instrukcja ma własne dokumenty, np. add (html extract of the vol2 manual) , pokazuje kodowanie jak
REX.W + 83 /0 ib dla ADD r/m64, imm8, czyli to, co masz.

Diagram pól bitowych ModRM z wiki.osdev.org

  7                           0
+---+---+---+---+---+---+---+---+
|  mod  |    reg    |     rm    |
+---+---+---+---+---+---+---+---+

0xc4 = 0b11000100, czyli pole reg = 0. Tak więc nasz kod opcode to 83 /0, w notacji Intela.

Reszta pól ModRM to:

  • mode = 0b11, więc pole rm koduje operand rejestru, a nie rejestr bazowy dla trybu adresowania.
  • rm = 0b100. reg # 4 = SPL / SP / ESP / RSP. (W tym przypadku RSP, ponieważ jest to 64-bitowy rozmiar operandu). Zobacz instrukcję Intela, lub https://wiki.osdev.org/X86-64_Instruction_Encoding#Registers do tabel.

Więc instrukcja jest add rsp, 0x38

ndisasm -b64 zgadza się:

$ cat > foo.asm
db 0x48, 0x83, 0xC4, 0x38
$ nasm foo.asm     # create a flat binary with those bytes, not an object file
$ ndisasm -b64 foo
00000000  4883C438          add rsp,byte +0x38
 9
Author: Peter Cordes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-05 21:03:59