Zrozumienie Rozmiary Intel Instruction

Original: http://www.swansontec.com/sintel.html


W niektórych typach programowania, takich jak 256-bajtowych intra, przestrzeń jest znacznie ograniczona. W rezultacie, rozmiaroptymalizacji kodu w asemblerze często jest konieczne. W tym artykule omówiono rozmiary maszynowego kod wspólnych Intel instrukcji architektury, z punktu widzenia optymalizacji kodu. Zrozumienie rozmiaru kodu maszynowego produkowanego przez montera jest niezbędne do podejmowania skutecznych decyzji optymalizacyjnych. Bez tej informacji, to możliwe do wyboru różnych opcji kodowania innych niż metodą prób i błędów, co jest czasochłonne i nie jest bardzo skuteczny.

Ten artykuł zawiera dwie sekcje.Pierwszy rozdział zawiera ogólny przegląd formacie Intel instrukcji, natomiast druga część zawiera dane kodowania każdej wspólnej instrukcji Intel.Pierwsza sekcja zawiera informacje dodatkowe niezbędne do zrozumienia drugiej części, a druga część ma być więcej odniesienie.

Ważne rozróżnienie między aplikacjami DOS i Windows jest wielkość słowa maszynowego. Intel zaprojektował oryginalne 8086 opcodes z 16-bitowego przetwarzania danych w pamięci. W rezultacie wykorzystują pojedynczy bit odróżnić 16-bitowych operandów a 8-bitowych operandów. Ponieważ jeden bit ma dwie wartości, zmusza to nowsze trybu 32-bitowego procesora mają tylko dwa rozmiary operandów, jak również. Tryb 32bit zmienia znaczenie bitu wielkości rozróżniania 32-bitowych argumentów i 8-bitowych argumentów. W wyniku tego, rozmiar A “mały” argumentu jest 8 bitów w obu trybach, ale wielkość duży” argumentu zależy od trybu pracy. Pod DOS, procesor pracuje w trybie 16-bitowym starszych. Oznacza to, że domyślny rozmiar “dużyargumentu jest 16 bitów. Okna, jednak działa w trybie 32-bitowym, co domyślnego rozmiaru “duży” Argument 32 bitów. Dla uproszczenia, w tym artykule użyto terminu “słowo” oznacza wielkość dużego argumentu. Jeśli aplikacja działa pod DOS-em, a “słowojest 16 bitów, ale jeśli aplikacja działa w systemie Windows, “słowo” jest 32 bitów.

Format instrukcji Intel

Chociaż instrukcje Intel różnią się wielkością od jednego aż do czternastu bajtów bajtów, wszystkie instrukcje Intel mają taką samą strukturę sześciu części. Zrozumienie cel każdej części jest pierwszym krokiem do nauki rozmiary różnych instrukcji Intel. Części instrukcji Intel formatu są wymienione poniżej, w kolejności, w jakiej występują w instrukcji:

Prefiksy: 0-4 bajty
Opcode: 1-2 bajtów
Modr / M 1 bajt
SIB: 1 bajt
Pojemność: 1 bajt lub słowo
Natychmiastowe: 1 bajt lub słowo

Wyjątkiem opcode wszystkie te części są opcjonalne. Są to jedynie wtedy, gdy ich szczególna instrukcja wymaga. Proste instrukcje takie jak NOP wymagają tylko kodu maszynowego. Skomplikowanych instrukcji, takie jak ADD [ES: my_data + EBX + ESI * 8], WORD 1003H, wymagają wszystkie pola. Poniższe akapity wyjaśniają, jak i kiedy każde pole instrukcja jest używana.

Prefiksy

Opcjonalne prefiksy pierwsza część instrukcji Intel. Prefiksy modyfikować zachowanie instrukcji na kilka różnych sposobów. Prefiksy można zmienić domyślną segment instrukcji, zastąpić domyślny rozmiar słowa maszynowego, kontrola pętli w instrukcji smyczkowych oraz kontrolować korzystanie z magistrali procesora. Każdy prefiks dodaje jeden bajt do instrukcji.Instrukcja może mieć jeden prefiks z każdej z czterech grup prefiksów, dla maksymalnie czterech bajtów prefiksów:

Grupa 1: LOCK, REPE / REPZ, REP, REPNE / REPNZ
Grupa 2: CS, DS, ES, FS, GS, SS, wskazówki Branch
Grupa 3: Argument wielkości stałe (16 bit vs 32 bit)
Grupa 4: Adres wielkości stałe (16 bit vs 32 bit)

Opcode

Kod operacji, lub kod operacji, przychodzi po opcjonalnych prefiksów.Kod operacji informuje procesor, którego wskazówki do wykonania. Ponadto, rozkazy zawierają bitowe pola określające wielkość i rodzaj argumentów, aby oczekiwać.Instrukcja nie, na przykład, ma 1111011w kodu operacji. W tym kodu maszynowego, w nieco określa, czy argument jest bajt lub słowo.Instrukcja OR ma 000010dw kodu operacji. W tym kodu maszynowego, nieco d określa, które argumenty są źródłowy i docelowy, a w nieco ponownie określa rozmiar. Niektóre instrukcje mieć kilka różnych opcodes. Na przykład, gdy OR jest używany z rejestru akumulatora (AX lub EAX) i stała, ma szczególną oszczędność miejsca opcodu 0000110w, co eliminuje potrzebę stosowania oddzielnego MODR / M bajta. Od rozmiaru kodowania perspektywie zapamiętywania dokładne bity kodu operacji, nie jest konieczne. Mając ogólny obraz, jaki rodzaj rozkazy dostępne dla konkretnej instrukcji jest ważniejsze.

Nie wszystkie rozkazy tej samej wielkości. Oryginalne instrukcje z 8088 mają opcodes jednobajtowe, podczas gdy nowe instrukcje od 386 mają zazwyczaj opcodes dwubitowych. Niektóre instrukcje SSE nawet opcodes trzy-bajtowych. Jest tak, ponieważ rozmiar bajtów ogranicza liczbę możliwych rozkazy. Jak Intel zabraknie niewykorzystanych rozkazy, jedynym sposobem, aby dodać więcej instrukcji jest dać im rozkazy większy niż jeden bajt.

MODR / M

Jeśli instrukcja wymaga, bajt MODR / M przychodzi po kodu maszynowego. Bajt ten informuje procesor, który rejestruje lub miejsc w pamięci do wykorzystania jako argumenty instrukcji znajduje.Bajt ma następującą strukturę:


Oba pola reg1 i reg2 potrwać od trzech-bitowe kody, zaznaczając, która zarejestruje się używać jako argumenty instrukcji znajduje. Domyślnie reg1 jest argument źródłowy i docelowy reg2 jest. Niektóre rozkazy, takie jak LUB opcode mowa powyżej, zawiera trochę kierunek które zastępują tę wartość. Inne instrukcje wymagają jeden argument. Jeśli instrukcja wymaga tylko jeden argument, niewykorzystane pola reg2 posiada dodatkowe fragmenty kodu operacji, a nie kod rejestracyjny. Jest to szczególnie prawdziwe w odniesieniu do instrukcji zmiennoprzecinkowych, które wykorzystują ST (0) jako domniemanych przeznaczenia.

Pole mod ustala znaczenie pola reg1. To może mieć następujące możliwe wartości:

Code Znaczenie kodu Zgromadzenie
00 [reg1] adres pamięci operandu jest w reg1.
01 [reg1 + byte] adres pamięci operandu jest reg1 + przemieszczenie bajt wielkości.
10 [reg1 + word] adres pamięci operandu jest reg1 + przemieszczenie słowo wielkości.
11 reg1 argument jest sama reg1.


Znaczenie pola reg1 komplikuje się w trybie 16-bitowym. Gdy mod specifes adres pamięci (mod = 00, 01 lub 10), reg1 nie zawiera prosty kod rejestracyjny. Zamiast tego, to określa jeden z następujących kombinacji rejestru:

Code Rejestracja Połączenie
000 BX + SI
001 BX + DI
010 BP + SI
011 BP + DI
100 SI
101 DI
110 BP
111 BX

Oba tryby 16-bitowe i 32-bitowe mają dodatkowe komplikacje. W systemie powyżej, MODR / M zapewnia żadnej oczywistej sposób określić stałą lokalizację w pamięci jako argumentu. Wszystkich kombinacji dla mod i reg1 to rejestr jako część adresu pamięci. Aby rozwiązać ten problem, Intel arbitralnie określa połączenie mod = 00, reg = BP / EBP oznacza, że adres argumentu jest prosty [słowo] przemieszczenia. Ponieważ kody do [BP] i [EPB] mieć ten nowy sens, nie istnieje prosty sposób na dostęp do pamięci w rejestrze danego wskaźnika bazy. Gdy kompilator widzi jeden z tych argumentów, to automatycznie tworzy formę [BP + 00] lub [EBP + 00], która wymaga dodatkowego przemieszczenia bajt.

Wreszcie, trybie 32-bitowym posiada własny komplikacji. Gdy mod oznacza adres pamięci (mod = 00, 01 lub 10), gdy reg1 oznacza ESP rejestracji dodatkowy bajt następuje Modr / M bajt. Ten bajt nazywany byte SIB jest używany zamiast reg1 celu określenia adresu pamięci operandu jest.Struktura bajtu SIB jest omówione później.

Nie wszystkie rozkazy wymagają bajt MODR / M. Niektóre czynności, takie jak AAM, mają stałe źródłowych i docelowych. Inne instrukcje, jak PUSH i POP, kodowanie źródła lub przeznaczenia bezpośrednio do kodu maszynowego. Wiedza, które instrukcje potrzebujesz MODR / M bajt, a które nie jest instrukcja najtrudniejsza część nauki rozmiary Intel instrukcji.

SIB

Gdy MODR / M zawiera poprawną kombinację mod i reg1, bajt SIB następuje bajt MODR / M. SIB jest skrótem pochodzącym od Skala * Główna + Base. Jest to potężne rozwiązanie Format dostępne tylko w trybie 32-bitowym. W SIB, połączenie dwóch rejestrów i współczynnik skalowania zastępuje reg1 na adres operandu jest. Format SIB Byte jest pokazany poniżej:


W bajcie SIB, zarówno indeks i podstawa trzy-bitowe kody rejestru, a skala jest numerem dwabit. Aby obliczyć wartość SIB, procesor używa następującego wzoru: (Indeks * 2 ^ skali) + bazy. (Oczywiście, procesor wykorzystuje przesunięcie bitowe wykonać power-of-dwóch mnożenie.) Gdy procesor znajdzie wartość SIB, używa go w miejsce wartości reg1 przez MODR / M Byte w obliczeniach adresowej pamięci.

SIB bajt pozwala skomplikowane adresy takie jak [ebx * 4 + ESI my_table]. W tym przykładzie pola przez MODR / M i SIB bajtów, mają następujące wartości:

     Modr / M.mod = 10 (innymi słowy, tryb [reg1 + słowo]).
MODR / M.reg2 = Cokolwiek (Zazwyczaj rejestr docelowy, ale zależy od kodu maszynowego.)
MODR / M.reg1 = ESP (ESP Intel redefiniuje kod do oznaczać SIB w 32-bitowych adresów pamięci.)
SIB.scale = 2 (Bo 2 ^ 2 = 4)
SIB.index = EBX
SIB.base = ESI

SIB bajt nie jest zwykle obecny. Jest potrzebny tylko wtedy, gdy instrukcja używa formatu adresowania Scale * Strona główna + bazowa.

Przemieszczenie

Gdy mod jest albo 01 albo 10, przemieszczenie jest częścią adresu operandu jest. Przesunięcie to jest zaraz po MODR / M oraz opcjonalnym SIB bajt. Dending na polu mod, przemieszczenie jest albo bajt lub słowo.

Na przykład, tutaj jest pełny kod maszynowy dla instrukcji 32bitowych lub EAX, [ECX + EDX * 2 + 406080A0h]:

Opcode ModR/M SIB skokowa
00001011 10 000 100 01 010 001 10100000 10000000 01100000 01000000

W trybie 32-bitowym, przemieszczenie słowo wielkości zajmuje cztery bajty. To jest ogromna ilość przestrzeni. Gdy instrukcja zawiera przesunięcie czterech bajtów, to zwykle dobry pomysł, aby spojrzeć na inne formy rozwiązywania może być mniejsze, takie jak przy użyciu stosu, lub rejestr plus mniejszą wyporność.

Natychmiastowy

Jeśli instrukcja używa natychmiastowego wartość jako argument, takie jak ADD AX, 0xF00F, wartość bezpośrednia jest ostatnia część instrukcji. Jak adresowanie przemieszczeń, immediates może być bajt lub słowo maszyna.

Aby zilustrować, tutaj jest kod maszynowy dla instrukcji 16bitowych, i SI, 0420h:

Opcode ModR/M Natychmiastowe
10000001 11 100 110 00100000 00000100

Tylko z adresowania przemieszczeń, 32-bitowy słowo wielkości natychmiastowe wymaga dużej ilości miejsca. Wielkie immediates zazwyczaj kompresują lepiej niż przemieszczeń, jednak, ponieważ zawierają zazwyczaj więcej immediates bajtów zerowych.
Szczegółowe Kodowanie instrukcji

Bezpośrednio zapamiętywania rozmiary Intel instrukcji nie jest to możliwe, ponieważ rozmiar instrukcji zależy od jej argumentów. Zamiast tego, lepiej jest, aby zapamiętać, które pola obsługi zawiera. Dodając rozmiary różnych dziedzinach, znalezienie rozmiar instrukcji jest łatwe. Ta sekcja zawiera listę rozmiarów OPCODE, wymagania MODR / m, a dosłowne rozmiary wspólnych instrukcji Intel.

Integer Instrukcje

Dla uproszczenia, w tej sekcji jest zorganizowany w formie tabeli.Pierwsza kolumna tabeli można znaleźć instrukcje w kolejności alfabetycznej.Druga kolumna pokazuje różne kombinacje argumentów każda instrukcja może podjąć, a trzecia kolumna zawiera pola wymagane do kodowania każdej kombinacji.Tabeli zastosowano następujące skróty:

m – pamięć
r – zarejestruj
* Pamięci lub rejestr
i – natychmiastowa
disp przemieszczenie
ac akumulator (AL, AX lub EAX)
cc – kod stanu
op – jeden bajt kodu operacji
mod MODR / M [+ opcjonalnie SIB] [+ opcjonalnie disp]

Pokazać rozmiar każdego argumentu zastosowano następujące przyrostki:

b bajt
w – maszyny słowo
1, 2, 3, 4, 6, 8 – liczba bajtów

Jeśli tabela nie wykazuje wielkość około operandów operandy może być bajt lub słowo, tak długo jak są tej samej wielkości. To dlatego, że rozkazy użyć nieco rozmiar, aby określić rozmiary operandów.

Instrukcja Argumenty Kodowanie
AAA none op
AAD none op i.b
AAM none op i.b
AAS none op
ADC *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
AND *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
ADD *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
BOUND r.w, m.w op mod
BSF r.w, *.w op op mod
BSR r.w, *.w op op mod
BSWAP r.w op op mod
BT *.w, r.w
*.w, i.b
op op mod
op op mod i.b
BTC *.w, r.w
*.w, i.b
op op mod
op op mod i.b
BTR *.w, r.w
*.w, i.b
op op mod
op op mod i.b
BTS *.w, r.w
*.w, i.b
op op mod
op op mod i.b
CALL disp.w
*.w
op disp.w
op mod
CBW none op
CDQ none op
CLC none op
CLD none op
CLI none op
CMC none op
CMOVcc *.w, *.w op op mod
CMP *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
CMPS none op
CMPXCHG *, r op op mod
CMPXCHG8B m.8 op op mod
CPUID none op op
CWD none op
CWDE none op
DAA none op
DAS none op
DEC *
r.w
op mod
op
DIV * op mod
ENTER i.16, i.8 op i.3
HLT none op
IDIV * op mod
IMUL *
r.w, *.w
r.w, i
r.w, *.w, i
op mod
op op mod
op mod i
op mod i
IN ac, i.b
ac, DX
op i.b
op
INC *
r.w
op mod
op
INS none op
INT i.b
3
op i.b
op
INTO none op
IRET none op
Jcc disp.b
disp.w
op disp.b
op op disp.w
JCXZ disp.b op disp.b
JMP disp
*.w
op disp
op mod
LAHF none op
LDS r.w, m.w op mod
LEA r.w, m op mod
LEAVE none op
LES r.w, m.w op mod
LFS r.w, m.w op mod
LGS r.w, m.w op mod
LSS r.w, m.w op mod
LODS none op
LOOP disp.b op disp.b
LOOPZ disp.b op disp.b
LOOPNZ disp.b op disp.b
MOV *, *
*, i
r, i
ac, [disp.w]
op mod
op mod i
op i
op disp.w
MOVS none op
MOVSX r.w, *.b op op mod
MOVZX r.w, *.b op op mod
MUL * op mod
NEG * op mod
NOP none op
NOT * op mod
OR *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
OUT ac, i.b
OUT ac, DX
op i.b
op
OUTS none op
POP *
r
FS
GS
op mod
op
op op
op op
POPA none op
POPF none op
PUSH *
r
i
FS
GS
op mod
op
op i
op op
op op
PUSHA none op
PUSHF none op
RCR *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
RCL *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
RET none
i.2
op
op i.2
ROL *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
ROR *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
SAHF none op
SAL *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
SAR *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
SBB *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
SCAS none op
SETcc *.b op op mod
SHL *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
SHLD *.w, r.w, CL
*.w, r.w, i.b
op op mod
op op mod i.b
SHR *, 1
*, CL
*, i.b
op mod
op mod
op mod i.b
SHRD *.w, r.w, CL
*.w, r.w, i.b
op op mod
op op mod i.b
STC none op
STD none op
STI none op
STOS none op
SUB *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i
TEST *, r
*, i
ac, i
op mod
op mod i
op i
WAIT none op
XADD *, r op op mod
XCHG *, r
ac, r
op mod
op
XLAT none op
XOR *, *
*, i
*.w, i.b
ac, i
op mod
op mod i
op mod i.b
op i

Wiele instrukcji w powyższym wykazie mają specjalne opcodes oszczędność miejsca, które nie wymagają dodatkowego MODR / M bajt. Te instrukcje są:

Grudnia, INC, POP lub PUSH używany z rejestru ogólnego wyrazu wielkości.
ADC, ADD, I, CMP, OR, SBB, SUB, test, lub XOR używany z akumulatorem i natychmiastowe.
MOV używany z dowolnym rejestru ogólnego i natychmiastowe.
MOV używany z akumulatorem i prostego przemieszczenia słowa.
XCHG używany z akumulatora i rejestru słowo.

Aby zaoszczędzić miejsce, instrukcje arytmetyczne binarny ADC, ADD, I, CMP, OR, SBB, SUB, a XOR może użyć bajt wielkości natychmiastowym z miejsca tekstu wielkości. Aby to zrobić, te instrukcje przed użyciem go w operacji logowania rozszerzyć do rozmiaru dosłowne miejsce przeznaczenia. Jest to szczególnie cenne w przypadku kodu 32-bitowego, ponieważ oszczędza trzy bajty na instrukcji. Niestety, NASM, dość popularne asemblera, nie używać przedłużacza logowania kodowanie domyślnie. Aby użyć tego kodowania, poprzedzić słowem kluczowym natychmiastowym BYTE.

Dwa znaczące wskazówki w powyższej liście AAD i AAM. W starych podręcznikach Intel instrukcje te mają opcodes dwubitowych. Nowe Intel Instrukcje wskazują obecnie te instrukcje z opcodes jednobajtowych następnie natychmiastowe równa 0x0A.Instrukcja AAD mnoży AH poprzez natychmiastowe i dodaje produkt do AL. AAM dzieli AL poprzez natychmiastowe i przechowuje resztę w AL i iloraz w AH. Możliwe jest, aby zmienić wartość bezpośrednim bajtu kodując instrukcje w języku maszynowym, tworząc dwa nowe, bezimiennych instrukcje szybko się dzielą i pomnożenie przez bajt stałej.Kod operacji dla AAD jest 0xD5 oraz kod operacji dla AAM jest 0xD4.

Należy również zauważyć, że ENTER, CALL FAR i JMP FAR oraz postać natychmiastowego RET wyjątki od reguły, że przemieszczenie dyspozycję i literały musi być natychmiastowe albo bajt lub słowo. ENTER trwa trzy-bajtowy natychmiastowe, a CALL FAR i JMP FAR podjąć albo czterysześć bajtów lub bajt przemieszczenia, w zależności od tego, czy procesor jest w trybie 16 lub 32-bitowej. Bezpośrednią formą RET wymaga dwubajtowa dosłowne, niezależnie od wielkości tego słowa maszyny.

Pływające Instrukcje Point

Ze względów historycznych, wszystkie instrukcje zmiennoprzecinkowe mają opcodu jedną bajtowy bajt MODR / M. Jeśli instrukcja zmiennoprzecinkowa nie ma dostępu do pamięci, cała MODR / M bajt przechowuje bity kodu operacji, więc kodowanie jest efektywnie kod operacji dwóch bajtów.

Oryginalny procesor PC, 8088, nie zawiera instrukcji zmiennoprzecinkowych.Opcjonalnie koprocesor matematyczny, 8087, pod warunkiem, pływający punkt wsparcia dla 8088. Do komunikacji z koprocesor arytmetyczny, 8088 zawierał osiem instrukcji ewakuacyjnych o MODR / M bajtów. Gdy procesor główny otrzymał polecenie ewakuacji, odczytać pamięć zidentyfikowany przez MODR / M bajt, a następnie wykonał no-działanie. Tymczasem, koprocesor matematyczny rejestrowane zawartość kodu operacji ewakuacyjnej, bajt MODR / M i adres pamięci ROM.Koprocesor matematyczny używany opcodu escape i bajt MODR / M określa operację do wykonania, a używany adres pamięci jako cel tej operacji.

Wszystkie procesory Intela od czasu 486 mają zintegrowane jednostki zmiennoprzecinkowe, więc już nie używać mechanizmu ucieczki. Niemniej jednak, format czynności przy 8087 pozostaje.

Inne Instrukcje

Instrukcje MMX posiadają opcodes dwubitowych plus bajt MODR / M, z wyjątkiem zmiany-bystałych instrukcji, które zawierają jeden bajt natychmiastowej, jak również.

Ludzie, którzy planują skorzystać SSE lub 3DNow! Prawdopodobnie guru kod już, więc mogą patrzeć praca rozmiary siebie.

Istnieje wiele kwestii związanych z wielkości optymalizacja kodu; na artykuł na temat ich wszystkich jest niemożliwe. Mamy nadzieję, że zrozumienie rozmiarów instrukcji Intel zapewnia użyteczną podstawę do odkrywania i lepsze zrozumienie tych technik optymalizacyjnych.

Źródło może być z wami.