39
Úvod do x86 strojového kódu a assembleru Nudný ale nevyhnutný

Úvod do x86 strojového kódu a assembleru

  • Upload
    idiftl

  • View
    2.268

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Úvod do x86 strojového kódu a assembleru

Úvod do x86 strojového kódu a assembleru

Nudný ale nevyhnutný

Page 2: Úvod do x86 strojového kódu a assembleru

Na čo preBoha assembler?

● Znalosť vs. využívanie

● Kvalitná znalosť vyžaduje aspoň nejaké využívanie

● Využívanie neznamená len programovanie v ňom

● Využitie:

● Reverse engineering● Driver / system level programming● Copy protection● Machine code manipulation (compiler, packer, analyzer...)● ????● Profit

Page 3: Úvod do x86 strojového kódu a assembleru

X86 milestones

● 8086 (16-bit)● 80286 (chránený mód)● 80386 (32-bitový chránený mód + množstvo

nových fičúr)● X86-64● Rozšírené inštrukčné sady: FPU (x87), MMX,

SSE, SSE2, SSE3, SSSE3, SSE4, SSE5, VMX, SMX, SVM, AVX, XOP, ...

Page 4: Úvod do x86 strojového kódu a assembleru

“Chrbtica” x86

CPU Northbridge

RAM Video RAM ŔOM

Southbridge

Všetko ostatné

(nie naozaj)

Page 5: Úvod do x86 strojového kódu a assembleru

Čo z toho pre nás vyplýva

● Procesor pristupuje k všetkým zariadeniam tým istým mechanizmom (ako k RAM), nepotrebuje zvláštne inštrukcie ● nie celkom pravda, ale pre náš účel užitočná

abstrakcia

● Nebudeme sa zaoberať “systémovými” a málo používanými inštrukciami (segmentácia, stránkovanie, task switching, stránkovanie, 16-bit a real mód)

● Stačí nám zvládnuť základné operácie a prácu s pamäťou

Page 6: Úvod do x86 strojového kódu a assembleru

Inštrukcie

● Pokyny pre procesor (CPU) uložené v pamäti● CPU ich číta a vykonáva● Principiálne sa ničím nelíšia od bežných dát v

pamäti● DOS program na riešenie sudoku (62 bytov):

B4 3F 8B D5 CD 21 91 43 88 02 4E 78 F7 B8 31 40 80 3A 2E 75 F5 8B F9 4F 60 78 ED 38 03 75 11 97 D4 13 6B C0 0B 96 43 7B F7 33 C6 A9 C0 E0 7E 02 F6 E4 61 70 E2 C6 02 2E 3C 39 74 F6 EB D1

Page 7: Úvod do x86 strojového kódu a assembleru

Zápisy inštrukcii

● Binárny:

00000001 11011000

● Hexadecimálny:

01 D8

0000-0001 1101-1000

● Osmičkový:

001 330

00-000-001 11-011-000

● Desiatkový:

fuj

● Assembler:

add eax, ebx

add %ebx, %eax (fuj)

0000 - 0

0001 - 1

0010 - 2

0011 - 3

0100 - 4

0101 - 5

0110 - 6

0111 - 7

1000 - 8

1001 - 9

1010 - A

1011 - B

1100 - C

1101 - D

1110 - E

1111 - F

Page 8: Úvod do x86 strojového kódu a assembleru

“General purpose” registre

● Register = premenná procesoru

● CPU má množstvo registrov, 99.9% času sa ale pracuje s “general purpose” registrami (GPR)

● V bežnej (?) reči preto “Register” = “General Purpose Register”

● x86 má 8 GPR (až x86-64 rozšírilo počet na 16)

● 8086 mal 16-bitové GPR registre:

AX, BX, CX, DX, SP, BP, SI, DI

● Možnosť pristupovať k 8-bit častiam prvých 4 registrov:

AL (low), AH (high), BL, BH, CL, CH, DL, DH

● 386 rozšíril na 32-bitov:

EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI

Page 9: Úvod do x86 strojového kódu a assembleru

Špecializované využitie “general purpose” registrov

0 = [E]AX = accumulator

1 = [E]CX = counter

2 = [E]DX = data

3 = [E]BX = base

4 = [E]SP = stack pointer

5 = [E]BP = base pointer

6 = [E]SI = source index

7 = [E]DI = destrination index

Page 10: Úvod do x86 strojového kódu a assembleru

Formát x86 inštrukcie

● Prefix – voliteľný byte pred inštrukciou, menia jej funkčnosť

● Mnemonics – udáva základnú operáciu ktorá sa vykoná

● Operand – udáva register alebo pamäťovú premennp, nad ktorou sa vykoná operácia. Operandy môžu byť 0 až 3.● Operandy musia byť rovnakej veľkosti● Cieľový (destination) operand prvý● Niektoré inštrukcie majú implicitný operand

Page 11: Úvod do x86 strojového kódu a assembleru

Presun / priradenie hodnoty GPR

MOV (move)mov eax, 31337

mov ecx, 123

mov esi, edx

mov bh, al

mov al, 500 (neplatná)

mov eax, sp (neplatná)

mov ah, ebx (neplatná)

Page 12: Úvod do x86 strojového kódu a assembleru

Súčet / Rozdiel

ADD (addition)add ebx, eax

add esp, 1

INC (increment, jeden operand)inc eax

SUB (subtract)sub ebp, 20

sub eax, ebx

DEC (decrement, jeden operand)dec ecx

Page 13: Úvod do x86 strojového kódu a assembleru

Bitové operácie

ANDand al, 11111100b

XORxor al, 101b

ORor al, 100b

NOT (jeden operand)not al

Page 14: Úvod do x86 strojového kódu a assembleru

Negatívne čísla

● Čísla ktoré môžu nadobúdať aj zápornú hodnotu sa nazývajú znamienkové

● Existuje niekoľko možností ako ich reprezentovať v binárnej forme

● Najšikovnejší “two's complement”

● Tie isté operácie pre znamienkové aj neznamienkové čísla

● Horný bit udáva znamienko● Podtečenie: najmenšia hodnota – 1 = najväčšia

hodnota● Pretečenie: najväčšia hodnota +1 = najväčšia

hodnota

Page 15: Úvod do x86 strojového kódu a assembleru

Two's complement

00000001 (1)

-00000001 (1)

00000000 (0)

00000010 (2)

-00000001 (1)

00000001 (1)

00000111 (7)

-00000010 (2)

00000101 (5)

00000000 (0)

-00000001 (1)

11111111 (255)

00000000 (0)

-00000010 (1)

11111110 (254)

00000011 (3)

+11111111 (255)

00000010 (2)

Page 16: Úvod do x86 strojového kódu a assembleru

Negatívne čísla

add eax, ebx

sub ecx, 5

add al, -1

add al, 255

sub al, 1

sub cl, -5

sub cl, 251

add cl, 5

Page 17: Úvod do x86 strojového kódu a assembleru

Negácia čísla

NEG (negation)neg eax

neg dx

neg cl

Bitwise spôsobnot eax

inc eax

Napr.:00000001 (1)

not

11111110 (-2)

+1

11111111 (-1)

Page 18: Úvod do x86 strojového kódu a assembleru

Pamäť (z pohľadu CPU)

● Pole bytov● Adresovaná 32-bitovým číslom, toto udáva

pozíciu (index) bytu v “poli”.● Nieje možné pristupovať k dvom miestam v

pamäti vrámci jednej inštrukcie● Zápis operandu pre prístup k pamäti v

assembleri:

[adresa] (adresa v hranatých zátvorkách)

Page 19: Úvod do x86 strojového kódu a assembleru

Priama adresácia pamäte

mov al, [1]

mov [2], al

add [0], eax

xor esp, [20]

mov [30], [29] - neexistuje

sub [0], [1] - neexistuje

Page 20: Úvod do x86 strojového kódu a assembleru

Endianness

● Možnosť pristupovať k pamäti v rôznych veľkostiach

8-bit - byte

16-bit - word

32-bit - dword (double word)

64-bit - qword (quad word, X86-64 only)

● Poradie bytov vo väčších číslach od najmenej významného po najviac významný (tzv. “little endian”)

● byty 00h, 01h = word 100h = word 100000000b = 256● byty 11h, 22h, 33h, 44h = dword 44332211h

Page 21: Úvod do x86 strojového kódu a assembleru

Priama adresácia pamäte

mov eax, [1234]

mov eax, dword [1234]

mov [31337], ecx

add [20], ebx

inc byte [0]

inc word [0]

neg dword [1]

Page 22: Úvod do x86 strojového kódu a assembleru

Nepriama adresácia pamäte

● Ako adresa môže byť použitá aj hodnota v registri:

mov eax, dword [ebx]

mov al, byte [esi]

● K registru v adrese môže byť pripočítaná konštanta

mov edx, dword [ebx+4]

mov al, byte [esi-1]

Page 23: Úvod do x86 strojového kódu a assembleru

Nepriama adresácia pamäte

● Úplná forma 32-bitovej adresácie:

[base + scale*index + displacement]

base - ľubovolný register

scale - konštanta 1, 2, 4, alebo 8

index - ľubovolný register

displacement - číselná 32-bit konštanta● Napríklad:

[ebx + 4*edi + 401224]

[eax + eax] = [2*eax]

[8*eax]

[3*ebx + 3] = [ebx + 2*ebx + 3]

Page 24: Úvod do x86 strojového kódu a assembleru

Nepodmienený skok

● JMP (jump, nepodmienený skok)jmp 200

jmp dword [200]

jmp eax

jmp dword [eax]

● V assembleri číselné adresy nahrádzame symbolickými návestiami:

jmp koniec

koniec:

Page 25: Úvod do x86 strojového kódu a assembleru

Príznaky

● CPU má register flags (korektne príznaky, hovorovo flagy)

● Každý z jeho bitov má samostatný význam● Nečítame ani nezapisujeme ho priamo● Nastavuje sa podľa výsledku (nielen)

aritmetických inštrukcii

Page 26: Úvod do x86 strojového kódu a assembleru

Príznaky

● CF (carry flag)

● Nastaví sa ak operácia pretečie ako celočíselná● Inak využívaný inštrukciami ktoré “potrebujú nejaký

flag”● OF (overflow flag)

● Nastaví sa ak operácia pretečie ako znamienková● SF (sign flag)

● Nastaví sa ak je výsledkom operácie záporné číslo (horný bit výsledku je 1)

● ZF (zero flag)

● Nastaví sa ak výsledok operácie je nula.

Page 27: Úvod do x86 strojového kódu a assembleru

Pretečenie

mov al, 0

sub al, 1 CF=1, OF=0, SF=1

mov al, 0

add al, 11111111b CF=0, OF=1, SF=1

mov al, 0

sub al, 11111111b CF=1, OF=1, SF=0

Page 28: Úvod do x86 strojového kódu a assembleru

Podmienené skoky

● Skáču iba ak je splnená podmienka

JC (jump if carry) - CF=1

JNC (jump if not carry) - CF=0

JO (jump if overflow) - OF=1

JNO (jump if not overflow)- OF=0

JS (jump if signed) - SF=1

JNS (jump if not signed) - SF=0

JZ (jump if zero) - ZF=1

JNZ (jump if not zero) - ZF=0

Page 29: Úvod do x86 strojového kódu a assembleru

Príklad:Nulovanie 16 bytov

mov ecx, 16 ;nuluj 16 bytov

mov edi, 5 ;od adresy 5

nuluj:

mov byte [edi], 0 ;vynuluj byte na adrese EDI

inc edi ;posun EDI na dalsi byte

dec ecx ;dalsi byte hotovy

jnz nuluj ;ak je ecx>0, opakuj cyklus

Page 30: Úvod do x86 strojového kódu a assembleru

CMP

● CMP (compare)● Porovnáva dva operandy● Nastaví flagy pre špeciálne skoky● V skutočnosti SUB ktorý neprepíše cieľový register,

iba nastaví flagy podľa výsledku odpočítania.

● Príklady:cmp eax, ebx

cmp eax, dword [4]

cmp byte [eax], dl

cmp ecx, 30

Page 31: Úvod do x86 strojového kódu a assembleru

CMP pre neznamienkové čísla

● Podmienené skoky:

JB – jump if 1st operand below 2nd

JBE – jump if 1st operand below or equal to 2nd

JE – jump if 1st operand equal to 2nd

JAE – jump if 1st operand above or equal to 2nd

JA – jump if 1st operand above 2nd

● Pre každý z nich možno obrátiť podmienku: JN (jump if not) namiesto J (jump if)

Page 32: Úvod do x86 strojového kódu a assembleru

CMP pre znamienkové čísla

● Podmienené skoky:

JL – jump if 1st operand lower than 2nd

JLE – jump if 1st operand lower than or equal to 2nd

JE – jump if 1st operand equal to 2nd

JGE – jump if 1st operand greater than or equal to 2nd

JG – jump if 1st operand greater than 2nd

● Pre každý z nich možno obrátiť podmienku: JN (jump if not) namiesto J (jump if)

Page 33: Úvod do x86 strojového kódu a assembleru

Príklad #2Nulovanie 16 bytov inak

mov ecx, 0

nuluj:

mov byte [ecx+5], 0 ;vynuluj ECX-ty byte od

;adresy 5

inc ecx ;dalsi byte hotovy

cmp ecx, 16 ;hotovych 16 bytov?

jne nuluj ;ak je ecx>0, opakuj cyklus

Page 34: Úvod do x86 strojového kódu a assembleru

Príklad #3Porovnanie reťazcov

mov esi, retazec1 mov edi, retazec2

porovnaj:

mov al, byte [esi] ;nacitaj znak prveho

cmp byte [edi], al ;porovnaj so znakom

;druheho

ja druhy_vacsi ;znak druheho vacsi?

jb prvy_vacsi ;znak druheho mensi?

inc esi ;ak su rovnake, posun

inc edi ;na dalsi znak

jmp porovnaj ;a repete

Page 35: Úvod do x86 strojového kódu a assembleru

Čo je “assembler”?

● Program, ktorý prekladá symbolický zápis inštrukcii na binárny strojový kód

● Syntax zápisu inštrukcii sa medzi rôznymi assemblermi viac či menej odlišuje

● Z toho prenesene “assembler” ako označenie niektorej konkrétnej syntaxe

● V širokom zmysle sa “assembler” používa aj ako označenie ľubovolnej syntaxe ktorá reprezentuje priamo strojový kód

Page 36: Úvod do x86 strojového kódu a assembleru

Rozšírené assemblery

● MASM (Microsoft Macro Assembler)● MASM32 projekt

● gas (GNU Assembler)● NASM (Netwide Assembler)

● YASM (Yet-another Assembler, ...)

● FASM (Flat Assembler)● GoAsm, HLA (High Level Assembly), RosAsm

Page 37: Úvod do x86 strojového kódu a assembleru

Zdroje pre štúdium

● Intel x86 CPU manuals

● http://developer.intel.com/products/processor/manuals/index.htm● AMD CPU manuals

● http://developer.amd.com/documentation/guides/pages/default.aspx#manuals● Art of assembly programming (Randall Hyde)

● http://webster.cs.ucr.edu/● Asm komunity:

● http://www.asmcommunity.net/board/ (General)● http://board.flatassembler.net (FASM)● http://www.masm32.com/board/ (MASM)● Newsgroups: alt.lang.asm, comp.lang.x86.asm

Page 38: Úvod do x86 strojového kódu a assembleru

Nabudúce (?)

● Zásobník● Procedúry● Volacie štandardy (stdcall, ccall, fastcall,

vararg)● Ďalšie “prídavné” inštrukcie● Čo ma ešte napadne● Socializácia

Page 39: Úvod do x86 strojového kódu a assembleru

vid (nie 'Vid')

[email protected]