§ Общая схема
Процессор x86 это процессор семейства CISC, характеризуются сложными инструкциями, причем разной длины. Обычно такие инструкции выполняются с помощью микрокода.Секция | Префиксы | Опкод | Байт ModRM | Байт SIB | Смещение | Непосредственное значение |
---|---|---|---|---|---|---|
Размер | 0-5 и выше | 1-2 | 1 | 1 | 0-4 | 0-8 |
§ Префиксы
Существуют несколько типов префиксов - это сегментные, строковые, префиксы расширения, и еще совершенно не нужный и не актуальный сейчас префикс LOCK.- Сегментные префиксы ES: CS: SS: DS: FS: и GS: указывают, что будет обязательным образом при обращении в память браться данные из указанного сегмента вместо DS: или SS:
- Строковые префиксы REPZ и REPNZ указывают, что STOSx, LODSx, MOVSx, CMPSx, INSx, OUTSx, SCASx инструкции могут повторяться согласно значению в регистре eCX или флагу Z, для инструкции SCASx, CMPSx
- Префикс LOCK был нужен для эксклюзивной блокировки шины процессором на время исполнения этой инструкции и работает только перед арифметически-логическими инструкциями
- Префикс расширения операнда (66h) указывает, что 16-битные регистры или 16-битные immediate будут увеличены до 32-х битных
- Расширение адреса (67h) указывает, что вместо механизма modrm16 будет взят механизм modrm32+sib для вычисления эффективного адреса в память
- Префикс 0Fh расширяет опкод, включая дополнительные 256-512 кодов операции. Строго говоря, префикс 0Fh считается частью 2х-байтного опкода.
§ Байт ModRM 16
Байт mod/rm предназначен для того, чтобы задавать операнды, обычно их два, и один либо указывает на память, другой на регистр, либо же оба указывают на регистр. В некоторых инструкциях регистровая часть выбирает некоторое действие.Формат байта
Имя | MOD | REG | R/M |
---|---|---|---|
Биты | 7:6 | 5:3 | 2:0 |
Байт mod определяет то, каким образом будет извлечено значение из rm-части (биты 0-2):
- mod=0, то тогда на основе значения rm вычислится эффективный адрес, откуда будет взят операнд для работы. Бывают инструкции, которые извлекают только один операнд - первый, второй операнд (reg-часть) используется для определения кода операции, а второй берется из непосредственного значения (immediate) после разбора.
- mod=0 и rm=6, то будет извлечено 16-битное значение offset вместо вычисления суммы регистров. В случае если участвует в вычислении эффективного адреса регистр bp, то по умолчанию будет взято значение из памяти с сегментом SS: вместо DS:
- mod=1, то к эффективному адресу добавится +1 знаковый байт индекса (-128..127)
- mod=2, то добавится +2 знаковый байт индекса (-32768..32767)
- mod=3, вместо операнда из памяти будет использован регистр
- [bx+si], al
- [bp], ax
- [bx], eax
- [bx+di-1], dl
- [di+127], dx
- [bp-128], edx
- [bx+2356], cl
- [si-32768], cx
- [di+32767], ecx
- ah, al
- bx, sp
- esi, edi
§ Байт 32-х modrm
Этот байт, как и 16-битный, предназначен для кодирования операндов, но он отличается достаточно сильно от своего предшественника. Во-первых, для вычисления эффективного адреса там уже используются все 8 регистров общего назначения, во-вторых, там можно складывать два регистра, в-третьих, регистры можно еще и масштабировать, умножая один на 2,4,8, что обеспечивает SIB-байт, который может идти после modrm (но может и не быть).Также как и в modrm16, если выбран mod=0, то не используется смещение, кроме случая rm=5 (не 6), так что при mod=0, rm=5 эффективный адрес будет 32-х битный абсолютный адрес disp32. Если mod=1, то в качестве смещения используется 1 знаковый байт (-128..127), если же mod=2, то будет использован 32-х битный адрес смещения. Так же как и ранее, mod=3 дает регистр.
Если mod=0,1 или 2, и rm=4 то прочитается байт SIB, который расширяет возможности адресации операнда, который находится в r/m-части. Второй операнд - регистр, остается без изменений. Байт SIB только расширяет адресацию эффективного адреса: он позволяет использовать сумму двух регистров общего назначения.
Как можно отметить, адресации по ESP не существует в данной схеме, поэтому необходимо пользоваться регистром EBP. Адресация по ESP возможна только при использовании байта SIB.
§ Формат байта MODRM32
r8(/r) | AL | CL | DL | BL | AH | CH | DH | BH | ||
r16(/r) | AX | CX | DX | BX | SP | BP | SI | DI | ||
r32(/r) | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI | ||
mm(/r) | MM0 | MM1 | MM2 | MM3 | MM4 | MM5 | MM6 | MM7 | ||
xmm(/r) | XMM0 | XMM1 | XMM2 | XMM3 | XMM4 | XMM5 | XMM6 | XMM7 | ||
sreg | ES | CS | SS | DS | FS | GS | res. | res. | ||
eee | CR0 | invd | CR2 | CR3 | CR4 | invd | invd | invd | ||
eee | DR0 | DR1 | DR2 | DR3 | DR41 | DR51 | DR6 | DR7 | ||
(In decimal) /digit (Opcode) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
(In binary) REG = | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | ||
Effective Address | Mod | R/M | Value of ModR/M Byte (in Hex) | |||||||
[EAX] | 00 | 000 | 00 | 08 | 10 | 18 | 20 | 28 | 30 | 38 |
[ECX] | 001 | 01 | 09 | 11 | 19 | 21 | 29 | 31 | 39 | |
[EDX] | 010 | 02 | 0A | 12 | 1A | 22 | 2A | 32 | 3A | |
[EBX] | 011 | 03 | 0B | 13 | 1B | 23 | 2B | 33 | 3B | |
[sib] | 100 | 04 | 0C | 14 | 1C | 24 | 2C | 34 | 3C | |
disp32 | 101 | 05 | 0D | 15 | 1D | 25 | 2D | 35 | 3D | |
[ESI] | 110 | 06 | 0E | 16 | 1E | 26 | 2E | 36 | 3E | |
[EDI] | 111 | 07 | 0F | 17 | 1F | 27 | 2F | 37 | 3F | |
[EAX]+disp8 | 01 | 000 | 40 | 48 | 50 | 58 | 60 | 68 | 70 | 78 |
[ECX]+disp8 | 001 | 41 | 49 | 51 | 59 | 61 | 69 | 71 | 79 | |
[EDX]+disp8 | 010 | 42 | 4A | 52 | 5A | 62 | 6A | 72 | 7A | |
[EBX]+disp8 | 011 | 43 | 4B | 53 | 5B | 63 | 6B | 73 | 7B | |
[sib]+disp8 | 100 | 44 | 4C | 54 | 5C | 64 | 6C | 74 | 7C | |
[EBP]+disp8 | 101 | 45 | 4D | 55 | 5D | 65 | 6D | 75 | 7D | |
[ESI]+disp8 | 110 | 46 | 4E | 56 | 5E | 66 | 6E | 76 | 7E | |
[EDI]+disp8 | 111 | 47 | 4F | 57 | 5F | 67 | 6F | 77 | 7F | |
[EAX]+disp32 | 10 | 000 | 80 | 88 | 90 | 98 | A0 | A8 | B0 | B8 |
[ECX]+disp32 | 001 | 81 | 89 | 91 | 99 | A1 | A9 | B1 | B9 | |
[EDX]+disp32 | 010 | 82 | 8A | 92 | 9A | A2 | AA | B2 | BA | |
[EBX]+disp32 | 011 | 83 | 8B | 93 | 9B | A3 | AB | B3 | BB | |
[sib]+disp32 | 100 | 84 | 8C | 94 | 9C | A4 | AC | B4 | BC | |
[EBP]+disp32 | 101 | 85 | 8D | 95 | 9D | A5 | AD | B5 | BD | |
[ESI]+disp32 | 110 | 86 | 8E | 96 | 9E | A6 | AE | B6 | BE | |
[EDI]+disp32 | 111 | 87 | 8F | 97 | 9F | A7 | AF | B7 | BF | |
AL/AX/EAX/ST0/MM0/XMM0 | 11 | 000 | C0 | C8 | D0 | D8 | E0 | E8 | F0 | F8 |
CL/CX/ECX/ST1/MM1/XMM1 | 001 | C1 | C9 | D1 | D9 | E1 | E9 | F1 | F9 | |
DL/DX/EDX/ST2/MM2/XMM2 | 010 | C2 | CA | D2 | DA | E2 | EA | F2 | FA | |
BL/BX/EBX/ST3/MM3/XMM3 | 011 | C3 | CB | D3 | DB | E3 | EB | F3 | FB | |
AH/SP/ESP/ST4/MM4/XMM4 | 100 | C4 | CC | D4 | DC | E4 | EC | F4 | FC | |
CH/BP/EBP/ST5/MM5/XMM5 | 101 | C5 | CD | D5 | DD | E5 | ED | F5 | FD | |
DH/SI/ESI/ST6/MM6/XMM6 | 110 | C6 | CE | D6 | DE | E6 | EE | F6 | FE | |
BH/DI/EDI/ST7/MM7/XMM7 | 111 | C7 | CF | D7 | DF | E7 | EF | F7 | FF |
§ Формат байта SIB
r32 | EAX | ECX | EDX | EBX | ESP | →1 | ESI | EDI | ||
(In decimal) Base = | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
(In binary) Base = | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 | ||
Scaled Index | SS | Index | Value of SIB Byte (in Hexadecimal) | |||||||
[EAX] | 00 | 000 | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 |
[ECX] | 001 | 08 | 09 | 0A | 0B | 0C | 0D | 0E | 0F | |
[EDX] | 010 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | |
[EBX] | 011 | 18 | 19 | 1A | 1B | 1C | 1D | 1E | 1F | |
none | 100 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | |
[EBP] | 101 | 28 | 29 | 2A | 2B | 2C | 2D | 2E | 2F | |
[ESI] | 110 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | |
[EDI] | 111 | 38 | 39 | 3A | 3B | 3C | 3D | 3E | 3F | |
[EAX*2] | 01 | 000 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
[ECX*2] | 001 | 48 | 49 | 4A | 4B | 4C | 4D | 4E | 4F | |
[EDX*2] | 010 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | |
[EBX*2] | 011 | 58 | 59 | 5A | 5B | 5C | 5D | 5E | 5F | |
none | 100 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | |
[EBP*2] | 101 | 68 | 69 | 6A | 6B | 6C | 6D | 6E | 6F | |
[ESI*2] | 110 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | |
[EDI*2] | 111 | 78 | 79 | 7A | 7B | 7C | 7D | 7E | 7F | |
[EAX*4] | 10 | 000 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
[ECX*4] | 001 | 88 | 89 | 8A | 8B | 8C | 8D | 8E | 8F | |
[EDX*4] | 010 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | |
[EBX*4] | 011 | 98 | 99 | 9A | 9B | 9C | 9D | 9E | 9F | |
none | 100 | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | |
[EBP*4] | 101 | A8 | A9 | AA | AB | AC | AD | AE | AF | |
[ESI*4] | 110 | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | |
[EDI*4] | 111 | B8 | B9 | BA | BB | BC | BD | BE | BF | |
[EAX*8] | 11 | 000 | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 |
[ECX*8] | 001 | C8 | C9 | CA | CB | CC | CD | CE | CF | |
[EDX*8] | 010 | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 | |
[EBX*8] | 011 | D8 | D9 | DA | DB | DC | DD | DE | DF | |
none | 100 | E0 | E1 | E2 | E3 | E4 | E5 | E6 | E7 | |
[EBP*8] | 101 | E8 | E9 | EA | EB | EC | ED | EE | EF | |
[ESI*8] | 110 | F0 | F1 | F2 | F3 | F4 | F5 | F6 | F7 | |
[EDI*8] | 111 | F8 | F9 | FA | FB | FC | FD | FE | FF |
Mod bits | base |
00 | disp32 |
01 | EBP+disp8 |
10 | EBP+disp32 |
Имя | SS | INDEX | BASE |
---|---|---|---|
Биты | 7:6 | 5:3 | 2:0 |
[eax + ebx]
. Если index=4, то он выбран не будет, получается что будет только одно лишь значение из базы, например [ebx]
. Это является синонимом того, что можно было бы сделать и без байта SIB. В случае если base=5, то есть должен быть ebp, то тут появляются некоторые исключения.- mod=0, base=5, выбирается вместо ebp смещение 32-х бит
- mod=1, base=5, выбирается
ebp + смещение 8 бит
- mod=2, base=5, выбирается
ebp + смещение 32 бит
При ss=1 индексный регистр домножается на 2, например
[2*ecx]
, ss=2 - домножение на 4, ss=3 - на 8.