Tabele Kodowania Rozkazów x86 (16-bit AT&T)

Rozpoznawanie formatu rozkazu na podstawie pierwszych bitów bajtu 1

Analiza rozkazu x86 (16-bitowa składnia AT&T) rozpoczyna się od weryfikacji początkowych bitów pierwszego bajtu, co determinuje format rozkazu oraz jego długość:

  • Rozkazy 1-bajtowe z rejestrem:
    • 01000xxx01000xxx: INC rejestr (np. inc%BXinc \, \%BX), długość: 11 bajt.
    • 01001xxx01001xxx: DEC rejestr (np. dec%CXdec \, \%CX), długość: 11 bajt.
    • 01010xxx01010xxx: PUSH rejestr (np. push%DXpush \, \%DX), długość: 11 bajt.
    • 01011xxx01011xxx: POP rejestr (np. pop%AXpop \, \%AX), długość: 11 bajt.
  • Rozkazy 1-bajtowe bez operandu:
    • 1001000010010000: NOP (No Operation), długość: 11 bajt.
    • 1100001111000011: RET (Return), długość: 11 bajt.
    • 1111100011111000: CLC (Clear Carry Flag), długość: 11 bajt.
  • Rozkazy 2-bajtowe (typu rejestr-rejestr):
    • 000000DW000000 DW: ADD (np. add%BX,%CXadd \, \%BX, \%CX), długość: 22 bajty.
    • 001010DW001010 DW: SUB (np. sub%DX,%BXsub \, \%DX, \%BX), długość: 22 bajty.
    • 000010DW000010 DW: OR (np. or%CX,%DXor \, \%CX, \%DX), długość: 22 bajty.
    • 001000DW001000 DW: AND (np. and%AX,%BXand \, \%AX, \%BX), długość: 22 bajty.
    • 001100DW001100 DW: XOR (np. xor%BX,%CXxor \, \%BX, \%CX), długość: 22 bajty.
    • 001110DW001110 DW: CMP (np. cmp%AX,%BXcmp \, \%AX, \%BX), długość: 22 bajty.
    • 100010DW100010 DW: MOV (np. mov%CX,%DXmov \, \%CX, \%DX), długość: 22 bajty.
    • 100001DW100001 DW: XCHG (np. xchg%BX,%CXxchg \, \%BX, \%CX), długość: 22 bajty.
  • Rozkazy rozszerzone:
    • 1111111W1111111 W: Rozszerzony INC/DEC pamięci, długość: 22 do 44 bajtów (np. inc0x20(%BX)inc \, 0x20(\%BX)).
    • 1111011W1111011 W: Rozszerzone operacje MUL, DIV, NEG, NOT, długość: 22 lub więcej bajtów (np. mul%BXmul \, \%BX).
    • 100000SW100000 SW: Operacje z operandem natychmiastowym, długość: 33 do 66 bajtów (np. add$5,%BXadd \, \$5, \%BX).

Kody rejestrów w polach REG i R/M

Kodowanie rejestrów zależy od wartości bitu szerokości WW oraz kontekstu pola (REG lub R/M przy mod=11mod=11).

  • Tabela kodowania rejestrów (8-bit i 16-bit):

    • 000000: W=1AX;W=0ALW=1 \rightarrow AX; W=0 \rightarrow AL
    • 001001: W=1CX;W=0CLW=1 \rightarrow CX; W=0 \rightarrow CL
    • 010010: W=1DX;W=0DLW=1 \rightarrow DX; W=0 \rightarrow DL
    • 011011: W=1BX;W=0BLW=1 \rightarrow BX; W=0 \rightarrow BL
    • 100100: W=1SP;W=0AHW=1 \rightarrow SP; W=0 \rightarrow AH
    • 101101: W=1BP;W=0CHW=1 \rightarrow BP; W=0 \rightarrow CH
    • 110110: W=1SI;W=0DHW=1 \rightarrow SI; W=0 \rightarrow DH
    • 111111: W=1DI;W=0BHW=1 \rightarrow DI; W=0 \rightarrow BH
  • Kody rejestrów dla 1-bajtowych wersji INC/DEC/PUSH/POP (tylko 16-bit):

    • 000000: AXAX
    • 001001: CXCX
    • 010010: DXDX
    • 011011: BXBX
    • 100100: SPSP
    • 101101: BPBP
    • 110110: SISI
    • 111111: DIDI

Tryby adresowania pamięci (Pole MOD i R/M)

Jeśli pole MOD11MOD \neq 11, połączenie MODMOD oraz R/MR/M określa tryb adresowania pamięci zamiast bezpośredniego wyboru rejestru.

  • Kombinacje pola R/M dla poszczególnych wartości MOD:
    • 000000:
      • mod=00[BX+SI]mod=00 \rightarrow [BX+SI]
      • mod=01[BX+SI+disp8]mod=01 \rightarrow [BX+SI+disp8]
      • mod=10[BX+SI+disp16]mod=10 \rightarrow [BX+SI+disp16]
    • 001001:
      • mod=00[BX+DI]mod=00 \rightarrow [BX+DI]
      • mod=01[BX+DI+disp8]mod=01 \rightarrow [BX+DI+disp8]
      • mod=10[BX+DI+disp16]mod=10 \rightarrow [BX+DI+disp16]
    • 010010:
      • mod=00[BP+SI]mod=00 \rightarrow [BP+SI]
      • mod=01[BP+SI+disp8]mod=01 \rightarrow [BP+SI+disp8]
      • mod=10[BP+SI+disp16]mod=10 \rightarrow [BP+SI+disp16]
    • 011011:
      • mod=00[BP+DI]mod=00 \rightarrow [BP+DI]
      • mod=01[BP+DI+disp8]mod=01 \rightarrow [BP+DI+disp8]
      • mod=10[BP+DI+disp16]mod=10 \rightarrow [BP+DI+disp16]
    • 100100:
      • mod=00[SI]mod=00 \rightarrow [SI]
      • mod=01[SI+disp8]mod=01 \rightarrow [SI+disp8]
      • mod=10[SI+disp16]mod=10 \rightarrow [SI+disp16]
    • 101101:
      • mod=00[DI]mod=00 \rightarrow [DI]
      • mod=01[DI+disp8]mod=01 \rightarrow [DI+disp8]
      • mod=10[DI+disp16]mod=10 \rightarrow [DI+disp16]
    • 110110:
      • mod=00disp16mod=00 \rightarrow disp16 (Adres bezpośredni - przypadek specjalny, brak rejestru bazowego)
      • mod=01[BP+disp8]mod=01 \rightarrow [BP+disp8]
      • mod=10[BP+disp16]mod=10 \rightarrow [BP+disp16]
    • 111111:
      • mod=00[BX]mod=00 \rightarrow [BX]
      • mod=01[BX+disp8]mod=01 \rightarrow [BX+disp8]
      • mod=10[BX+disp16]mod=10 \rightarrow [BX+disp16]
    • Adresowanie rejestrowe (mod=11mod=11): Rejestr wskazany przez R/MR/M (według tabeli rejestrów dla W=0W=0 lub W=1W=1).

Rozszerzone kody operacji w bajcie 2 (Pole OP)

W niektórych formatach (np. gdy bajt 1 kończy się prefiksem rozszerzenia), 3-bitowe pole REG w drugim bajcie służy jako rozszerzenie kodu operacji (pole op).

  • Dla bajtu 1 = 1111111x1111111x (INC/DEC/CALL/JMP/PUSH memoriałowe):

    • 000000: INC
    • 001001: DEC
    • 010010: CALL (pośredni)
    • 011011: CALL (daleki)
    • 100100: JMP (pośredni)
    • 101101: JMP (daleki)
    • 110110: PUSH
    • 111111: Rezerwacja
  • Dla bajtu 1 = 1111011x1111011x (Operacje arytmetyczne i logiczne):

    • 000000: TEST (z operandem natychmiastowym)
    • 001001: Rezerwacja
    • 010010: NOT
    • 011011: NEG
    • 100100: MUL (bez znaku)
    • 101101: IMUL (ze znakiem)
    • 110110: DIV (bez znaku)
    • 111111: IDIV (ze znakiem)
  • Dla bajtu 1 = 100000xx100000xx (Operacje z operandem natychmiastowym):

    • 000000: ADD
    • 001001: OR
    • 010010: ADC
    • 011011: SBB
    • 100100: AND
    • 101101: SUB
    • 110110: XOR
    • 111111: CMP

Znaczenie pól bitowych D, W oraz S

  • Bit W (Width):
    • W=0W=0: Operandy 8-bitowe (np. AL,BL,CL,DL,AH,BH,CH,DHAL, BL, CL, DL, AH, BH, CH, DH).
    • W=1W=1: Operandy 16-bitowe (np. AX,BX,CX,DX,SP,BP,SI,DIAX, BX, CX, DX, SP, BP, SI, DI).
  • Bit D (Direction):
    • D=0D=0: Pole REGREG określa źródło (SOURCE), a pole R/MR/M określa cel (DESTINATION).
    • D=1D=1: Pole R/MR/M określa źródło (SOURCE), a pole REGREG określa cel (DESTINATION).
  • Bit S (Sign-extend):
    • S=0S=0: Pełny operand natychmiastowy (8 bitów dla W=0W=0, 16 bitów dla W=1W=1).
    • S=1S=1: 8-bitowy operand natychmiastowy z rozszerzeniem znaku do 16 bitów (stosowane przy W=1W=1).

Szczegółowa budowa formatów rozkazów

  • 1-bajtowy bez operandu:
    • Budowa: Kod operacji (88 bitów).
    • Przykład: nop=10010000nop = 10010000, ret=11000011ret = 11000011, clc=11111000clc = 11111000.
  • 1-bajtowy z rejestrem (INC/DEC/PUSH/POP):
    • Budowa: Kod operacji (55 bitów) + reg (33 bity).
    • Przykład: inc%BX=01000011inc \, \%BX = 01000 \, 011, dec%CX=01001001dec \, \%CX = 01001 \, 001, push%DX=01010010push \, \%DX = 01010 \, 010, pop%AX=01011000pop \, \%AX = 01011 \, 000.
  • 2-bajtowy rejestr-rejestr:
    • Bajt 1: op(6bitoˊw)DWop \, (6 \, bitów) \, D \, W.
    • Bajt 2: 11reg(3bity)r/m(3bity)11 \, reg \, (3 \, bity) \, r/m \, (3 \, bity).
    • Przykład: add%BX,%CX=0000000111011001add \, \%BX, \%CX = 00000001 \, 11011001, sub%DL,%BL=0010100011010011sub \, \%DL, \%BL = 00101000 \, 11010011.
  • 2-bajtowy rejestr + pamięć (bez przemieszczenia):
    • Bajt 1: op(6bitoˊw)DWop \, (6 \, bitów) \, D \, W.
    • Bajt 2: 00reg(3bity)r/m(3bity)00 \, reg \, (3 \, bity) \, r/m \, (3 \, bity).
    • Przykład: mov(%BX),%CL=1000101000001111mov \, (\%BX), \%CL = 10001010 \, 00001111.
  • 3-bajtowy rejestr + pamięć (8-bit przemieszczenie):
    • Bajt 1: op(6bitoˊw)DWop \, (6 \, bitów) \, D \, W.
    • Bajt 2: 01reg(3bity)r/m(3bity)01 \, reg \, (3 \, bity) \, r/m \, (3 \, bity).
    • Bajt 3: disp8disp8.
    • Przykład: and4(%BP),%CX=001000110100111000000100and \, 4(\%BP), \%CX = 00100011 \, 01001110 \, 00000100.
  • 4-bajtowy rejestr + pamięć (16-bit przemieszczenie):
    • Bajt 1: op(6bitoˊw)DWop \, (6 \, bitów) \, D \, W.
    • Bajt 2: 10reg(3bity)r/m(3bity)10 \, reg \, (3 \, bity) \, r/m \, (3 \, bity).
    • Bajty 3-4: disp16disp16 (kolejność LSB, MSB).
    • Przykład: or0x5000(%BX),%CX=00001011100011110000000001010000or \, 0x5000(\%BX), \%CX = 00001011 \, 10001111 \, 00000000 \, 01010000.
  • 3-bajtowy rejestr + natychmiastowy (8-bit data):
    • Bajt 1: 100000SW100000 \, S \, W.
    • Bajt 2: 11op(3bity)r/m(3bity)11 \, op \, (3 \, bity) \, r/m \, (3 \, bity).
    • Bajt 3: data8data8.
    • Przykład: add$5,%BX=100000111100001100000101add \, \$5, \%BX = 10000011 \, 11000011 \, 00000101.
  • 4-bajtowy rejestr + natychmiastowy (16-bit data):
    • Bajt 1: 10000001100000 \, 0 \, 1.
    • Bajt 2: 11op(3bity)r/m(3bity)11 \, op \, (3 \, bity) \, r/m \, (3 \, bity).
    • Bajty 3-4: data16data16 (kolejność LSB, MSB).
    • Przykład: add$0x400,%BX=10000001110000110000000000000100add \, \$0x400, \%BX = 10000001 \, 11000011 \, 00000000 \, 00000100.

Algorytm dekodowania rozkazów — krok po kroku

Procedura zamiany binarnego kodu na instrukcję w składni AT&T przebiega w następujący sposób:

  1. KROK 1: Pobierz bajt 1 i zamień jego postać na binarną.
  2. KROK 2: Zidentyfikuj format na podstawie pierwszych bitów bajtu 1.
    • 01000xxx01011xxx01000xxx \dots 01011xxx: Instrukcje 1-bajtowe (INC, DEC, PUSH, POP), rejestr zakodowany w ostatnich 3 bitach.
    • 1001000010010000: NOP.
    • 1100001111000011: RET.
    • 1111111x1111111x lub 1111011x1111011x: Przejdź do analizy bajtu 2 (rozszerzone operacje).
    • 100000xx100000xx: Operacja natychmiastowa (czytaj bajt 2 oraz dane).
    • Pozostałe: Standardowy 2-bajtowy rozkaz (bit72=opbit7-2 = op, bit1=Dbit1 = D, bit0=Wbit0 = W).
  3. KROK 3: Pobierz bajt 2 i podziel go na pola: mod(2bity)mod \, (2 \, bity), reg(3bity)reg \, (3 \, bity), r/m(3bity)r/m \, (3 \, bity).
  4. KROK 4: Zinterpretuj pole modmod:
    • mod=11mod=11: Pole r/mr/m wskazuje na rejestr.
    • mod=00mod=00: Pole r/mr/m wskazuje na adres bazowy w pamięci; jeśli r/m=110r/m=110, czytaj 2 bajty przemieszczenia (disp16disp16).
    • mod=01mod=01: Pole r/mr/m wskazuje na adres bazowy + czytaj 1 bajt przemieszczenia (disp8disp8).
    • mod=10mod=10: Pole r/mr/m wskazuje na adres bazowy + czytaj 2 bajty przemieszczenia (disp16disp16).
  5. KROK 5: Ustal kierunek operacji na podstawie bitu DD:
    • D=0D=0 \rightarrow rejestr (regreg) to źródło, a r/mr/m (rejestr lub pamięć) to cel.
    • D=1r/mD=1 \rightarrow r/m (rejestr lub pamięć) to źródło, a rejestr (regreg) to cel.
  6. KROK 6: Złóż końcową instrukcję w formacie AT&T: nazwa_instrukcji źródło, cel.

Opracowano na podstawie kursu Architektury Komputerów — Collegium Da Vinci, prowadzonego przez dr. D. Wawrzyniaka.