Top Banner
X86 asembler
98

X86 asembler

Jan 29, 2016

Download

Documents

deanna

X86 asembler. 80 386 procesor. 32 -bitna CISC arhitrktura . Pretežno dvoadresna mašina. Veličina memorijskog adresnog prostora: 4GB. Adresibilna jedinica: bajt. Veličina podataka u instrukcijama: bajt, reč ( word )– dva uzastopna bajta, - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: X86 asembler

X86 asembler

Page 2: X86 asembler

80386 procesor

• 32-bitna CISC arhitrktura.

• Pretežno dvoadresna mašina.

• Veličina memorijskog adresnog prostora: 4GB.

• Adresibilna jedinica: bajt.

• Veličina podataka u instrukcijama:– bajt,– reč (word)– dva uzastopna bajta,– dvostruka reč (double word) – četiri uzastopna bajta.

Page 3: X86 asembler

Redosled bajtova podatka u memoriji

• Little-endian – viši bajt na višoj adresi.• Riječi:

– (a): 34 12

– (a+1): 56 34

– (a+2): 78 56

• Duple riječi:– (a) : 78 56 34 12

Page 4: X86 asembler

Zdravo svete! (Linux, int) 3

• .intel_syntax noprefix.arch i386

.data 1

poruka:.ascii “Zdravo svete!\n“kraj_poruke:

.equ duzina_poruke, kraj_poruke – poruka

.text 1

• .globl _start_start:

mov ebx, 1# mov ecx, offset porukalea ecx, porukamov edx, duzina_porukemov eax, 4int 0x80 2

mov ebx,0mov eax,1int 0x80 2

Page 5: X86 asembler

Prevođenje, povezivanje i pokretanje

• Asembliranje:– as zdravo_svete.s –o zdravo_svete.o– korišćena opcija: -o <output_file_name>

• Linkovanje (povezivanje):– ld zdravo_svete.o –o zdravo_svete– korišćena opcija: -o <output_file_name>

• Pokretanje– ./zdravo_svete

Page 6: X86 asembler

Prevođenje i povezivanje pomoću gcc

• Asembliranje:gcc -c -o zdravo_svete.o zdravo_svete.s– korišćene opcije:

• -o <output_file_name>• -c Prevedođenje i asembliranje, bez linkovanja

• Linkovanje (povezivanje):gcc -o zdravo_svete -nostartfiles zdravo_svete.o– korišćene opcije:

-o <output_file_name>-nostartfiles Poveži bez standardnih startup fajlova.

• Ili, i prevođenje i povezivanje jednim pozivom gcc:gcc -o zdravo_svete -nostartfiles zdravo_svete.s

• Druge opcije:-nodefoultlibs Povezivanje bez standardnih biblioteka.-nostdlib Kao –nostartfiles –nodefaultlibs-v Ispisuje komande koje pokreće.-### Kao prethodno, ali bez izvršavanja komandi.

Page 7: X86 asembler

Asemblerske naredbe (Intel sintaksa)

• [labela:] mnemonik [operandi] [#komentar]

• Labela predstavlja adresu na kojoj se nalazi naredba.

• mnemonik je simbolički zapisana komanda.

• Mogu biti do dva operanda.– Prvi je uvijek odredište, a nekad i izvorište.

– Drugi je izvorište.

Page 8: X86 asembler

Transfer podataka

• mov dst, src # dst = src

• lea dst, src # dst = offset(src)1

• lds dst, src # ds:dst = src• les dst, src # es:dst = src

• xchg op1, op2 # mijenja vrijednosti# u operandima op1 i op2

Page 9: X86 asembler

Programski dostupni registri(flat mode, aplikativni režim)

• Opštenamjenski (32-bitni):– eax, ebx, ecx, edx, esi i edi.

• Registri za manipulaciju podacima na steku:– esp i ebp.

• Segmentni registri (16-bitni): – cs, ss, ds, es, fs i gs.– U flat modu, svi ukazuju na početak memorije.

• Registri dostupni samo korišćenjem posebnih instrukcija– programski brojač eip,– statusna riječ procesora eflags.

Page 10: X86 asembler

Preslikavanje logičke u linearnu (flat) adresu

• Logička adresa:(Selektor) + ofset

• Selektor (16b) = segmentni registar• Ofset: adresa iz instrukcije(32bita)

• Selektor pokazuje na deskriptor u okviru deskriptorske tabele (deo operativnog sistema)

• Svi moderni OS podešavaju sadržaj deskriptora svih segmenata tako da pokazuju na logičku adresu 0, tako da je programeru dostupan ceo prostor od 4GB koristeći samo ofset i ne vodeći računa o segmentima tzv. Linearni adr. prostor

• Po potrebi se može uključiti i straničenje, kada se logička adresa preslikava u fizičku adresu.

Page 11: X86 asembler

Opštenamjenski registri

• Nižih 16 bita registara eax, ebx, ecx i edx se može koristiti i kao:– 16-bitni registar: ax, bx, cx i dx;– dva 8-bitna registra:

• Npr. ax ->– ah – viši bajt,– al – niži bajt.

• Imaju i posebne namene:– eax – akumulator,– ebx – bazni registar za adresiranje,– ecx – brojački registar,– edx – pomoćni registar za podatke u nekim instrukcijama,– esi i edi – indeksiranje pri adresiranju.

Page 12: X86 asembler

Registri za rad sa stekom

• esp – pokazivač na vrh steka– pokazuje na zauzetu lokaciju na vrhu steka,

– umanjuje se pre smeštanja podatka,

– uvećava se posle skidanja podatka.

• ebp – bazni registar za pristup argumentima potprograma i lokalnim promenljivim

• Radi sa:• Rečima (16 bita – esp se menja za 2)• Duplim rečima (32 bita – esp se menja za 4)

Page 13: X86 asembler

Rad sa stekom

• push src ; stavlja na stek src

• pop dst ; sa steka upisuje u dst

• pushfd ; čuva eflags na steku

• popfd ; restaurira eflags sa steka (; u neprivilegovanom režimu ; bitovi posle OF neće se promeniti)

• pushf/popf ; koristi samo donjih 16 bita eflags

• pushad/popad ; čuvanje svih registara na steku:; eax, ecx, edx, ebx, esp, ebp,; esi, edi.

Page 14: X86 asembler

Statusna riječ procesora

• CF – prenos.• PF – parnost.• AF – pomoćni prenos za BCD aritmetiku.• ZF – rezultat nula.• SF – negativan rezultat.• TF – prekid posle svake instrukcije.• IF – maskiranje svih maskirajućih prekida.• DF – smjer za operacije nad stringovima.• OF – prekoračenje.• IOPL – I/O priviledge level• NT – nested task flag• RF – resume flag• VM – virtual 8086 mode

VM RF NT IOPL OF DF IF TF SF ZF AF PF CF

Page 15: X86 asembler

Načini adresiranja 1/2

• Neposredno: – mov eax, 10– add ebx, 20h

• Registarsko direktno (svi registri): – mov eax, 2– mov edi, ebx– mov [ebp+6], ecx

• Memorijsko direktno: – mov eax, suma– mov niz+6, edx ...

Page 16: X86 asembler

Načini adresiranja 2/2

• Registarsko indirektno (svi opšte namene):– mov [ebx], eax

• Registarsko indirektno sa pomerajem: – mov [eax+88h], 2– mov niz[edx], 2

• Bazno indeksno (adresa se sastoji od dva registra): – mov [ebx][edx], eax

• Bazno indeksno sa pomjerajem (kao prethodno plus pomjeraj):– mov eax, niz[ebx][edi]

Page 17: X86 asembler

Skaliranje indeksa

• Opšti oblik:– <konstanta>[<bazna_adresa>+<faktor>*<indeks>]

– <faktor> može biti:• 1,• 2,• 4.

• mov eax, suma[ebx+4*esi]• mov vrsta[edx+2*eax], bx

Page 18: X86 asembler

Napomene

• Samo jedan operand u memoriji– postoji nekoliko izuzetaka.

• Podrazumjevana upotreba segmentnih registara:– cs – kod,– ds – podaci, osim ako se u adresnom izrazu koristi ebp– ss – ako se u adresnom izrazu koristi ebp

• Zamjena podrazumjevanog segmentnog registra:– mov ax,ds:[ebp+4]

• Flat režim = samo jedan segment veličine 4GB.

Page 19: X86 asembler

Sistemski pozivi (Linux)

• Tri načina:– direktno,

• kroz prekid 0x80,• kod novijih procesora, instrukcijama SYSENTER i SYSEXIT,

– indirektno, preko funkcija omotača iz standardne biblioteke.

• int 0x80– eax = 1: exit(int)

• ebx: povratna vrijednost programa.– eax = 3: read(int, char*, int)

• ebx: ručka fajla (0 za standardni ulaz),• ecx: adresa bafera,• edx: veličina bafera u B.

– eax = 4: write(int, char*, int)• analogno prethodnom (1 je ručka za standardni izlaz).

Page 20: X86 asembler

Zdravo svete! (Linux, int) 3

• .intel_syntax noprefix.arch i386

.data 1

poruka:.ascii “Zdravo svete!\n“kraj_poruke:

.equ duzina_poruke, kraj_poruke – poruka

.text 1

• .globl _start_start:

mov ebx, 1# mov ecx, offset porukalea ecx, porukamov edx, duzina_porukemov eax, 4int 0x80 2

mov ebx,0mov eax,1int 0x80 2

Page 21: X86 asembler

Zdravo svete! (Linux, libc) 1

• .intel_syntax noprefix.arch i386.dataporuka:.asciz "Zdravo svete!\n”kraj_poruke: .equ duzina_poruke, kraj_poruke – poruka.text.extern write.extern exit

• .globl _start

_start: push duzina_poruke push offset poruka push 1 call write add esp, 12#write(1,&poruka,# duzina_poruke);

push 0 call exit # exit(0);.end

Page 22: X86 asembler

Prevođenje, povezivanje i pokretanje

• Asembliranje:– as -o p1.o p1.s

• Povezivanje:– ld -o p1 -dynamic-linker /lib/ld-linux.so.2 p1.o -l c

– l c: • uključuje biblioteku libc.a1,• važno: navesti biblioteku posle objektnih fajlova koji je koriste2.

– dynamic-linker /lib/ld-linux.so.2• uključuje biblioteku za dinamičko povezivanje.

• Pokretanje– ./zdravo_svete

Page 23: X86 asembler

Potprogrami

• Počinje labelom i opciono:– u redu ispred labele: .type <labela>, @Function

– za potrebe umetanja informacija za debug:• na početku .func <naziv> [, <labela>]1

• na kraju .endfunc

• Završava se instrukcijom za povratak iz potprograma:– ret [exp] # u flat modelu, bliski povratak (samo offset)

– exp: broj koji po povratku treba dodati na esp

• Poziv potprograma:– call dst

– near poziv -> na steku se čuva EIP (u flat režimu se koristi ovaj pristup)

– far poziv -> na steku se čuvaju CS i EIP

– skače na dst

Page 24: X86 asembler

Proslijeđivanje parametara u registrima i globalnim promjenljivim

• Prije poziva se upisuje u registar ili globalno dostupnu memorijsku lokaciju.

• IZBEGAVATI, osim ako je primarna brzina.

• U jednom trenutku smije postojati najviše jedan poziv takve funkcije -> 1

– Da li je dozvoljena rekurzija?– Pozivanje u prekidnim rutinama?– Pozivanje u konkurentnim nitima?

Page 25: X86 asembler

Proslijeđivanje parametara preko steka

• Parametri se prije poziva ostavljaju na steku.

• U funkciji im se pristupa pomoću registra EBP.

• Zato svaka funkcija:

– počinje sa:push ebpmov ebp, esp ili enter 0, 0 1

– završava se sa:mov esp, ebp ili leave 2

pop ebp

• Ovako je obezbjeđeno da svaki poziv funkcije ima svoj zapis na steku (prikaz na sledećem slajdu).

Page 26: X86 asembler

Zapis poziva funkcije

Param[n]

Loc[m]

...

Loc[1]

EBPstaro

retEIP

Param[1]

...

ESP

EBP

+4

+8

-4*m

+4+4*n

-4

Bliski poziv

enter 4*m,0

call naziv_funkcija

Pred poziv funkcije:push param[n]…push param[1]

Zapis tekućeg poziva neke

funkcije

Page 27: X86 asembler

Instrukcija enter

• enter op1, op2:– op1:

• broj bajtova koje je potrebno rezervisati za lokalne prom.• 16-bitna neposredna konstanta.

– op2:• dubina ugniježđenosti funkcije (0-31),• govori koliko pokazivača na prethodne okvire treba iskopirati u

tekući.

– algoritam: 1

• push ebp• mov ebp, esp• Na stek doda pokazivače na okvirove prethodnih nivoa

(stare vrednososti epb registra)• sub esp, op1

Page 28: X86 asembler

Konvencije pozivanja potprograma

• Konvencija pozivanja potprograma definiše:– kako se poravnava stek,– kako se prosleđuju parametri,– ko radi oslobađanje prostora sa steka,– kako se vraća vrednost,– koji registri mogu da se koriste u funkciji bez da se čuvaju.

• Konvencije koje se koriste u gcc-u:– cdecl (podrazumjevana)– stdcall– fastcall

Page 29: X86 asembler

cdecl konvencija pozivanja

• Pred poziv funkcije, stek mora biti poravnat na granicu deljivu sa 16.1

• Argumenti se smeštaju na stek, s desna na levo.

• Prostor na steku oslobađa pozivaoc:– izuzetak je skriveni pokazivač, kojeg oslobađa pozvana funkcija.

• Vrednost se najčešće vraća u registru:– 1 bajt -> AL– 2 bajta -> AX– 4 bajta -> EAX (naredni primjer)– 8 bajtova -> EDX:EAX– struktura ili klasa -> preko skrivenog pokazivača 2

• Funkcija ne mora da čuva registre: eax, ecx i edx

Page 30: X86 asembler

Razlike stdcall i fastcall u odnosu na stdcall

• stdcall– pozvani potprogram skida sve argumente sa steka

• fastcall– prva dva argumenta, ako su celobrojnog tipa, prosleđuju

se: • prvi u ecx• drugi u edx• ostali, kao i oni koji nisu celobrojnog tipa1 prosleđuju se

preko steka

– pozvani potprogram skida sve argumente sa steka• u slučaju da je promenljiv broj argumenata, na stek se

stavljaju svi.

Page 31: X86 asembler

Napisati potprogram za sabiranje dva broja koristeći stdcall i cdecl konvencije 1

• Potprogram:stdcallsaberi: enter 0, 0 mov eax, [ebp+8] add eax, [ebp]+12 leave ret 8

cdeclsaberi: enter 0, 0 mov eax, [ebp+8] add eax, [ebp]+12 leave ret

• Primjer poziva:

push broj1push broj2call saberimov rezultat, eax

push broj1push broj2call saberimov rezultat, eaxadd esp, 8

Page 32: X86 asembler

Napisati potprogram za sabiranje dva broja

push 25

push 33

call saberi

retAdr:

mov rezultat, eax

saberi:

enter 0, 0

mov eax, [ebp+8]

add eax, [ebp]+12

leave

ret 8

EBP_old

retAdr

33

25

?EAX

ESP

EBP

33

25

58

Page 33: X86 asembler

Vraćanje vrijednosti preko steka

typedef struct {int a, b;} struc;

struc f(int x, int y){struc a;a.a = x;a.b = y;return a; 1

}

void main(){struc r = f(0x1122, 0x3344);

}

<f>:push ebpmov ebp, espsub esp, 0x10 # za lokalne promjenljive

mov eax, 0xc[ebp] # eax = xmov [ebp-0x8], eax # a.a = eax

mov eax, [ebp+0x10] # eax + ymov [ebp-0x4], eax # b.b = eax

mov ecx, [ebp+0x8] # ecx = &ret_bafer

mov eax, [ebp-0x8] # eax = a.amov edx, [ebp-0x4] # edx = a.b

mov [ecx], eax # ret_bafer.a = eaxmov [ecx+0x4], edx # ret_bafer.b = edxmov eax, [ebp+0x8] # eax = &ret_bafer

leave ret 0x4 # “oslobađa” skriveni parametar

Page 34: X86 asembler

Sabiranje i oduzimanje

• add dst, src # dst=dst+src• adc dst, src # dst=dst+src+cf

• sub dst, src # dst=dst-src• sbb dst, src # dst=dst-src-cf

• neg dst # dst=-dst

• inc dst # dst=dst+1• dec dst # dst=dst-1

• cmp src1, src2 # setuje flegove na osnovu # src1-src2

Page 35: X86 asembler

Množenje i dijeljenje

• mul src # neoznaceno množenje• imul src # označeno množenje

– src (8-bitni) množi sa al i rezultat ostavlja u ax– src (16-bitni) množi sa ax i rezultat ostavlja u dx:ax– src (32-bitni) množi sa eax i rezultat ostavlja u edx:eax

• div src # neoznačeno dijeljenje• idiv src # označeno dijeljenje

– Dijeli ax sa src (8-bitni) i rezultat ostavlja u al, a ostatak u ah. – Dijeli dx:ax sa src (16-bitni) i rezultat ostavlja u ax, a ostatak u dx– Dijeli edx:eax sa src (32-bitni) i rezultat ostavlja u eax, a ostatak

u edx

• Za množenje postoje i druge forme, sa dva i tri operanda

Page 36: X86 asembler

Proširivanje podataka znakom

• cbw # proširuje ah sa znakom iz al

• cwde # proširuje eax sa znakom iz ax

• cwd # proširuje dx sa znakom iz ax

• cdq # proširuje edx sa znakom iz eax

Page 37: X86 asembler

Logičke operacije

• not dst # dst = ~dst

• and dst, src # dst = dst & src

• or dst, src # dst = dst | src

• xor dst, src # dst = dst ^ src

• test op1, op2 # setuje flegove na osnovu # op1 & op2

Page 38: X86 asembler

Pomjeranje i rotiranje

• shl dst, cnt # pomjeranje logički lijevo• sal dst, cnt # pomjeranje aritmetički lijevo• shr dst, cnt # pomjeranje logički desno• sar dst, cnt # pomjeranje aritmetički desno• ror dst, cnt # rotiranje desno• rol dst, cnt # rotiranje lijevo• rcr dst, cnt # rotiranje kroz cf desno• rcl dst, cnt # rotiranje kroz cf lijevo

• cnt može biti:– 1,– neposredna vrijednost ili– registar cl.

Page 39: X86 asembler

Primjer

• stanje prije: ax=0xf00f, CF=0, cl=2

• shl ax, cl # 0xC03C, CF=1 (bit koji je ispao)• sal ax, cl # 0xC03C, CF=1 (bit koji je ispao)

• shr ax, cl # 0x3C03, CF=1 (bit koji je ispao)• sal ax, cl # 0xFC03, CF=1 (bit koji je ispao)

• ror ax, cl # 0xFC03, CF=1 (poslednji• rol ax, cl # 0xC03F, CF=1 rotirani bit)

• rcr ax, cl # 0xBC03, CF=1 (poslednj• rcl ax, cl # 0xC03D, CF=1 izbačeni bit)

Page 40: X86 asembler

Uslovni skokovi 1/2

• Relativni skok.• Pomjeraj se posmatra kao označeni cijeli broj veličine:

– 8 bita (short jump), ili– 16-bita (near jump), ili– 32-bita (near jump).

• Test pojedinačnih flegova:– jz (je), (Jump if Zero; Jump if Equal)– jnz (jne), (Jump if Not Zero; Jump if Not Equal– js, (Jump if Sign set)– jns,– jp (jpe), (Jump if Parity flag set; Jump if Parity

even)– jnp (jpo), (Jumo if No Parity flag set; Jump if Parity odd)

Page 41: X86 asembler

Uslovni skokovi 2/2

• Poređenje neoznačenih brojeva:– jb (jnae, jc) <(Jump Below; Jump Not Above or Equal)– jnb (jae, jnc) >=– jbe (jna) <=– jnbe (ja) >

• Poređenje označenih brojeva:– jl (jnge) <(Jump Lower; Jump Not Greater or Equal)– jnl (jge) >=– jle (jng) <=– jnle (jg) >

Page 42: X86 asembler

if-then-else

• Viši programski jezici:– if (ecx<=0) {

blok1 } else { blok2}

– Blok1 i blok2 su nizovi instrukcija

• Asembler:– cmp ecx,0

jbe blok1

jmp blok2blok1: …

jmp daljeblok2: …dalje: …

Izračunavanje uslova.

Ako je tačan, skače na blok1.U suprotnom na

blok2.

Page 43: X86 asembler

Lokalne labele

• Smanjuju mogućnost slučajnog ponavljanja iste labele.

• Moguće koristiti 10 različitih:– <cifra>:

• Sa svakog mjesta je moguće referisati prvu labelu:– unazad:

• <cifra>b• odnosi se na prvo pojavljivanje labele “<cifra>:”

prije tekuće instrukcije

– unaprijed• <cifra>f• odnosi se na prvo pojavljivanje labele “<cifra>:”

posle tekuće instrukcije

Page 44: X86 asembler

Primjer upotrebe lokalnih labela

• #Primjer 1:

cmp ecx,0je 1fjmp 2f

1: …jmp 1f

2: …1: …

• #Primjer 2:

1: add eax, ebxsub ebx, 1test ebx, 1je 2fdec ebx

2: jnz 1b

Page 45: X86 asembler

Podrška za petlje 1/2

• Neke moguće implementacije:– Pomoću instrukcija uslovnog skoka

– Pomogu namjenskih instrukcija za formiranje petlji

– Pomoću potprograma i manipulacije povratnom adresom (strogo izbjegavati).

• Instrukcije:– loop lab

– loopz (loope) lab

– loopnz (loopne) lab

Page 46: X86 asembler

Podrška za petlje 2/2

• Algoritam rada:– na početku instrukcije se prvo umanji ecx: ecx=ecx-1– potom se provere uslovi izlaska iz petlje:

• ecx==0, za loop• ecx==0 ili zf==0, za loope• ecx==0 ili zf==1, za loopne

• Lab je labela početak petlje ili instrukcije skoka na početak petlje.

• Lab mora biti u opsegu -128..+127B od adrese sledeće instrukcije.

• jcxz lab ;skače na lab ako je ecx=0

Page 47: X86 asembler

Primjer, suma prvih N brojeva

mov ecx, n # inicijalizacija # brojača

jcxz 2f # ako je ecx = 0, preskače se

# petlja

mov eax, 0 # početna vrijednost # sume

1: add eax, ecx # računanje sume

loop 1b # skok na početak # petlje ako je# ecx>0

2: ... # prva sledeća instrukcija

Page 48: X86 asembler

Bezuslovni skok

• jmp lab # skace na lab

• Za lab se mogu koristiti modovi adresiranja kao i za podatke

• Može se koristiti i indirektno memorijsko adresiranje.

• Primeri:– jmp eax # skače se na adresu zapisanu u eax– jmp [eax] # skače se na adresu zapisanu na adresi iz eax– jmp lab # skače se na labelu lab– jmp [lab] # sa adrese lab se čita adresa skoka– jmp DWORD PTR lab # isto kao prethodno

Page 49: X86 asembler

Minimum dva broja 1

• Napisati program koji sa standardnog ulaza učitava dva broja i na standardni izlaz ispisuje manji od dva unijeta broja.

• Traženje minimuma izdvojiti u funkciju u zasebnom fajlu (koristiti stdcall konvenciju pozivanja).

• Zadatak uraditi:– tako da se oba fajla napišu na asembleru,

– tako da se potprogram napiše na C-u, a program na asembleru,

– tako da se potprogram napiše na asembleru, a da se program napiše na C-u.

Page 50: X86 asembler

Uvoženje i izvoženje simbola

• Izvoženje:– Dvije sintakse:

• .globl <naziv_simbola>• .global <naziv_simbola>

– Ako je simbol definisan, ostaće vidljiv i za fazu povezivanja.

– Ako simbol nije definisan, smatra se da se uvozi spolja.

• Uvoženje:– .extern <naziv_simbola>

Page 51: X86 asembler

p4b.s (potprogram)

.data

.globl izlazni_formatizlazni_format:

.asciz "min(%i, %i) = %i\n"

.text

.globl minmin: 1

enter 0, 0mov ebx, [ebp+8]cmp ebx, [ebp]+12 #isto što i [ebp+12]jle 1fmov eax, [ebp]+12jmp 2f

1: mov eax, ebx2: leave

ret 8 1 .end

Page 52: X86 asembler

p4a.s (program)

.dataulazni_format:

.asciz "%i%i"

.extern izlazni_format

.text.extern printf.extern scanf.extern exit.globl _start

_start:call mainpush 0call exit.extern min

main:enter 8, 0and esp, 0xfffffff0

lea eax, [ebp-4]push eaxsub eax, 4push eaxpush offset ulazni_formatcall scanfadd esp, 12

push [ebp-8]push [ebp-4]call min

push eaxpush [ebp-4]push [ebp-8]push offset izlazni_formatcall printfadd esp, 16leaveret

.end

Page 53: X86 asembler

Prevođenje, povezivanje i pokretanje

• Prevođenje asemblerskog koda:– as -o p4a.o p4a.s– as -o p4b.o p4b.s

• Povezivanje:– ld -o p4 -dynamic-linker /lib/ld-linux.so.2 -l c p4a.o p4b.o

• Pokretanje:– ./p4

Page 54: X86 asembler

P5b.c (potprogram)

char izlazni_format[] = "min(%i, %i) = %i\n";

int __attribute__((stdcall)) min(int a, int b) {return a < b ? a : b;

}

Page 55: X86 asembler

p5a.s (program)

• Isti kao p4a.s

Page 56: X86 asembler

Prevođenje, povezivanje i pokretanje

• Prevođenje:– as -o p5a.o p5a.s

• Prevođenje C koda:– gcc -c -o p5b.o p5b.c– c: prevesti samo do objektnog programa, bez povezivanja

• Povezivanje:– ld -o p5 -dynamic-linker /lib/ld-linux.so.2 -l c p5a.o p5b.o

• Pokretanje– ./p5

• Disasembliranje objektnog fajla koji sadrži funkciju min– objdump –d1 –Mintel2 p5b.o

Page 57: X86 asembler

Disasembliran prevod C funkcije

00000000 <min>: 1

0: 55 push ebp

1: 89 e5 mov ebp, esp

3: 8b 45 08 mov eax, [ebp+0x8]

6: 39 45 0c cmp [ebp+0xc], eax

9: 0f 4e 45 0c cmovle eax, [ebp+0xc]

d: 5d pop ebp

e: c2 08 00 ret 0x8

Page 58: X86 asembler

p6b.s (potprogram)

• Isti kao p4b.s

Page 59: X86 asembler

p6a.c (program)

#include<stdio.h>

extern char izlazni_format;

int __attribute__((stdcall)) min(int x, int y);

int main(){int x1, x2, z;scanf("%i%i", &x1, &x2);z = min(x1,x2);printf(&izlazni_format, x1, x2, z);

return 0;}

Page 60: X86 asembler

Prevođenje, povezivanje i pokretanje

• Prevođenje– gcc -c -o p6a.o p6a.c

• -c: želi se samo prevesti zadati fajl, bez pozivanja.– as -o p6b.o p6b.s

• Povezivanje:– ld -o p6 -dynamic-linker /lib/ld-linux.so.2 -L /usr/lib/gcc/i686-

linux-gnu/4.6/ /usr/lib/i386-linux-gnu/crt1.o /usr/lib/i386-linux-gnu/crti.o /usr/lib/gcc/i686-linux-gnu/4.6/crtbegin.o p6a.o p6b.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i686-linux-gnu/4.6/crtend.o /usr/lib/i386-linux-gnu/crtn.o

• Prevođenje i povezivanje u jednoj komandi:– gcc –o p6 p6a.c p6b.s– za prikaz pojedinačnih komandi dodati opciju –v

• Pokretanje– ./p6

Page 61: X86 asembler

Definisanje podataka i poravnavanje

• . balign bajt_multipl, [bajt_za_dopunjavanje], [max]– bajt_multipl1

– bajt_za_dopunu2

– max3

• Rezervisanje prostora u memoriji:– Bajt: .byte init [,init...] – Riječ (2B): .word init [,init...]

.short init [,init...]– Dupla riječ (4B) : .long init [,init...]

.int init [,init...]– Lista stringova: .ascii lista_stringova_odvojenih_zapetama– Lista stringova sa \0:4 .asciz lista_stringova_odvojenih_zapetama

• Ponavljanje sadržaja: – .rept broj_ponavljanja

sadržaj za ponavljanje.endr

Page 62: X86 asembler

Primjer

• a: .byte 2 – jedan bajt kojem se pristupa sa a

• b: .word 3, 8, 6– 3 riječi, sa b se pristupa prvoj, a sa b+2 i b+4 drugim dvijema.

• c: .asciz "Tekst"– niz od 6 bajtova, zadnji je null.

• d: .long c– jedna dupla riječ sa ofsetom od c

• F: .rep 4.byte 0,1.endr

– 8 bajtova inicijalizovanih sa 0,1,0,1,0,1,0,1

Page 63: X86 asembler

Direktive

• .equ noviSimbol, izraz– svako pojavljivanje noviSimbol zamjenjuje vrijednošću izraza.

• .include file– uključuje sadržaj fajla file na poziciju ove direktive.

• OFFSET expr– vraća ofset izraza.

• BYTE PTR expr– pristup bajtu.

• WORD PTR expr– pristup riječi.

• DWORD PTR expr– pristup dvostrukoj riječi.

Page 64: X86 asembler

Sabiranje niza brojeva

• Napisati program koji sa standardnog ulaza učitava i sabira niz brojeva. Program prvo učita broj elemenata niza, a potom i elemente niza. Broj elemenata nije unapred poznat, pa se prostor alocira na steku. Smatrati da će stek biti dovoljno veliki za smeštanje niza, kao i da se zbir računa unutar potprograma.

Page 65: X86 asembler

Sabiranje niza brojeva

.dataporuka: .asciz "Unesite broj elemenata\ niza, pa zatim elemente niza.\n"ulazni_format: .asciz "%i"izlazni_format: .asciz "Suma elemenata unijetog\ niza je = %i\n"

.text

.extern scanf

.extern printf

.extern exit

.globl _start_start:

call mainpush 0call exit # exit(0);

# prvi argument: broje elemenata# naredni argumenti: elementi nizasaberi:

enter 0, 0xor eax, eax # sum = 0mov ecx, [ebp+8] # i = N

jcxz 2f # if (i==0) ret 0;

# adresa prvog elementa: ebp+12# i=N .. 1# adrese elemenata niza:# ebp+12 + (i-1)*4

# sum+=niz[i-1]1: add eax, [ebp+4*ecx]+8

loop 1b

2: leaveret

Page 66: X86 asembler

Sabiranje niza brojeva

main: enter 4, 0

push offset poruka call printf add esp, 4

lea eax, [ebp-4] # eax = &[ebp-4]

push eax # 2. arg za scanf

push offset ulazni_format # 1. arg

call scanf add esp, 8

mov ecx, [ebp-4] jcxz 2f # if (N==0) goto

exit mov ebx, ecx shl ebx, 2 sub esp, ebx mov ebx, esp

1: push ecx

push ebx push offset ulazni_format call scanf # scanf(“%i”, adr_elementa) add esp, 8

pop ecx

add ebx, 4 # adr_elementa++

loop 1b

push DWORD PTR [ebp-4]# push N call saberi # eax = sum add esp, 4

push eax push offset izlazni_format call printf # printf(“…”, sum) add esp, 8

2: leave ret.end

Page 67: X86 asembler

Rekurzivne funkcije

• Napisati rekurzivnu funkciju koja sabira brojeve u opsegu 0..N.

• Koristiti stdcall konvenciju pozivanja.

Page 68: X86 asembler

Primjer – rekurzija, sabiranje N..0

suma: push ebp mov ebp, espmov eax, [ebp+8] # čitanje parametra sa stekacmp eax, 0 # da li se doslo do 0?je dalje # ako jeste, skoci na kraj i

# vrati 0dec eax # ako nije, pozovi suma(i-1)push eaxcall sumaadd eax, [ebp+8] # na tekucu sumu (0..i-1) dodaj i

dalje: pop ebpret 4 # po povratku oslobodi prostor rezervisan

# za parametar na steku

Promjer poziva sa parametrom 3:

3 ;vrijednost programa proslijeđena pred poziv retEIP ;adresa van funkcijeEBPold12 retEIP ;adresa add EAX, [EBP+8]EBPold21retEIP ;adresa add EAX, [EBP+8]EBPold30retEIP ;adresa add EAX, [EBP+8]EBPold3

EBP pokazuje ovdjeEBP+8 pokazuje na poziciju koja sadrži

vrijednost 3Pošto je sa steka očitano 3, što je različito od 0, na stek

se stavlja 3-1, što je parametar za naredni poziv

EBP pokazuje ovdjeEBP+8 pokazuje na poziciju koja sadrži

vrijednost 2

Pošto je sa steka očitano 2, što je različito od 0, na stek

se stavlja 2-1, što je parametar za naredni poziv

EBP pokazuje ovdjeEBP+8 pokazuje na poziciju koja sadrži

vrijednost 1

Pošto je sa steka očitano 1, što je različito od 0, na stek

se stavlja 1-1, što je parametar za naredni poziv

EBP pokazuje ovdjeEBP+8 pokazuje na poziciju

koja sadrži vrijednost 0.Pošto je 0, skače se na kraj.

Primjetiti da je u ovom trenutku EAX=0 što je

početna suma

Sada se kreće sa izlascima iz ranije učinjenih poziva ove

funkcije. Svaki put se po povratku na tekuću sumu doda vrijednost

parametra iz tekućeg poziva. Tekuća suma se uvijek zapiše u

EAX i u njemu se i ostavlja.

EBP pokazuje ovdje. Sa [EBP+8] se čita 1 i

dodaje na tekuću sumu:EAX = EAX+1 (0+1)

EBP pokazuje ovdje. Sa [EBP+8] se čita 2 i

dodaje na tekuću sumu:EAX = EAX+2 (1+2)

EBP pokazuje ovdje. Sa [EBP+8] se čita 3 i

dodaje na tekuću sumu:EAX = EAX+3 (3+3).

Ovo je i povratna vrijednost funkcije.

Page 69: X86 asembler

Uslovno prevođenje

• Početak bloka sa uslovnim prevođenjem:– .if apsolutni_izraz

• da li je vrijednost apsolutnog izraza različita od nule?

– .ifdef name:• da li je simbol name definisan?

– .ifndef

• Opciono može da se pojavi i else grana:– .else– .elseif

• Na kraju mora da se pojavi:– .endif

Page 70: X86 asembler

Makroi 1/2

• Početak makroa:– .macro name [arg[=def_val] {[ |,] [arg[=def_val]} – name – naziv makroa– arg – parametri– def_val – podrazumijevana vrijednost parametra

• Kraj makroa:– .endm

• Izlazak iz makroa sa sredine:– .exitm

• Upotreba parametara:– \naziv_parametra

Page 71: X86 asembler

Primjer upotrebe makroa

• Definicija:

.macro INVOKE, func, p1, p2, p3push \p3push offset \p2push \p1call \funcadd esp, 12

.endm

• Poziv:

INVOKE write,1,poruka,duzina_poruke

Page 72: X86 asembler

Primjer upotrebe makroa

• Definicija:

.macro sum from=0, to=5

.long \from

.if \to-\fromsum "(\from+1)",\to.endif.endm

• Poziv:sum 0,5

• Rezultat1:.long 0.long 1.long 2.long 3.long 4.long 5

Page 73: X86 asembler

Makroi 2/2

• .irp param, <arg,[,arg...]># ovaj segment koda se ponavlja onoliko puta koliko ima# argumenata i to tako da se svaki put umjesto svakog

pojavljivanja# param zamjeni jedna vrijednost arg.

.endm

• .irpc param, <string># isto kao prethodno, osim čto su argumenti slova# navedenog stringa

.endm

• \ - operator prepoznavanja parametra u tekstu

Page 74: X86 asembler

Primjeri upotrebe makroa

• Ulaz:.irp param,0,4,8move d\param,[BX+\param].endr

• Rezultat:move d0, [BX+0]move d4, [BX+4]move d8, [BX+8]

• Ulaz:.irpc param,048 move d\param,[BX+\param] .endr

• Rezultat:move d0, [BX+0]move d4, [BX+4]move d8, [BX+8]

Page 75: X86 asembler

Razlike između Intel i AT&T sintakse

Intel AT&T

Redosled operanada dst, src src, dst 1

Indirektno adresiranje [registar] (registar)

Prefix za registre nema %

Prefix za konstante nema $

Prefix za apsolutne adrese jump i call

nema *

Veličina operanada u memoriji

na osnovu direktiva uz operand

na osnovu sufiksa mnemonika 2

Daleke adrese section:offset $section, $offset

Page 76: X86 asembler

Primjer Intel i AT&T sitaksi

push ebp

mov ebp, esp

mov eax, [ebp+0x8]

cmp [ebp+0xc], eax

cmovle eax, [ebp+0xc]

pop ebp

ret 0x8

push %ebp

mov %esp, %ebp

mov 0x8(%ebp), %eax

cmp %eax, 0xc(%ebp)

cmovle 0xc(%ebp), %eax

pop %ebp

ret $0x8

Page 77: X86 asembler

Primjeri rada sa WIN32 API

Page 78: X86 asembler

Zdravo svete (Windows)

.intel_syntax noprefix

.arch i386

.extern _MessageBoxA@16: PROC

.extern _ExitProcess@4: PROC

.global _start

.equ MB_OK, 0

.datanl:.ascii "Zdravo svete\0“#.asciz "Zdravo svete"

.text _start: push MB_OK push offset nl push offset nl push 0 call _MessageBoxA@16 push 0 call [email protected]

Page 79: X86 asembler

Prevođenje

• Asembliranje:as zdravo_svete.s -o zdravo_svete.obj– korišćena opcija: -o <output_file_name>

• Linkovanje (povezivanje):ld -o zdravo_svete.exe zdravo_svete.obj -l user32 -l kernel32

– korišćene opcije:-o <output_file_name>

-l <library_name>

Page 80: X86 asembler

Primjer – čitanje jednog znaka i vraćanje u registru

.intel_syntax noprefix

.datastdin .long 0.text.extern _readconsolea@20

.type readc, @Functionreadc:

enter 8, 0push ebxlea eax, [ebp-4] # adresa bafera za podatke

lea ebx, [ebp-8] # bafer za broj procitanih # znakova

push 0push ebxpush 1 # broj znakova za citanjepush eax # adresa bafera za podatkepush stdin # stdin handle (naredni slajd)call _readconsolea@20 # stdcall

mov eax, [ebp - 4]and eax, 0ffh

pop ebxleaveret

Page 81: X86 asembler

stdin i stdout ručke

• Da bi se mogao vršiti ispis na konzolu, na početku programa (prije prvog ispisa) je neophodno dohvatiti stdout handle:

.equ STD_OUTPUT_HANDLE, -11push STD_OUTPUT_HANDLEcall GetStdHandlemov stdout, eax

• Da bi se moglo vršiti čitanje standardnog ulaza pripadajuće konzole, na početku programa (prije prvog čitanja) je neophodno dohvatiti stdin handle:

.equ STD_INPUT_HANDLE, -10push STD_INPUT_HANDLEcall GetStdHandlemov stdin, eax

Page 82: X86 asembler

Inline asembler

• Na mesto naredbe se ubacuje :_ _asm_ _(ʺ

# niz redova sa asemblerskim naredbama završenih sa ;

ʺ);

– ili

_ _asm_ _({"instrukcija \n"} : output : input : modify);• output: "=tmp"(naziv promenljive)• input: “tmp"(naziv ulazne promjenljive)• modify: "registar" – spisak registara na čije vrijednosti

kompajler ne treba da računa nakon izvršavanja bloka.• tmp – privremena lokacija (objašnjena na sledećem

slajdu).

Page 83: X86 asembler

Inline asembler – polje tmp

• tmp – oznaka privremene lokacije (registra ili memorije) – ova lokacija će biti korišćena u asembleru umesto

promenljive.

– u asembleru se referiše sa %<redni_broj>

– input -> prije instrukcija iz asm bloka, u tmp će se učitati vrednost promenljive navedene u zagradama.

– output -> nakon instrukcija iz asm bloka, vrednost tmp će se upisati u promenljivu navedenu u zagradama.

– za tmp je moguće koristiti:• registre (eax, ebx, ecx, edx, esi, edi, r-bilo koji registar)1

• memoriju (memory)

Page 84: X86 asembler

Inline asembler - primer

int t;

int main(){int x1, x2, z;

__asm__(// ".intel_syntax noprefix\n“1

"mov ebx, %2\n"\ "add ebx, %3\n" "mov %0, ebx\n"\ "mov %1, ebx\n"

// ".att_syntax\n“1

: "=c"(x1), "=m"(z)\ : "a"(x2), "m"(t)\

: "ebx"\ );

return 0;}

Izlaz koji se dobije kada se c kod prevede na asm:

mov eax, DWORD PTR [ebp-16]2

mov ebx, eax3

add ebx, DWORD PTR t4

mov ecx5, ebxmov DWORD PTR [ebp-20]6, ebx

mov esi, ecx7

mov DWORD PTR [ebp-12], esi

Page 85: X86 asembler

Microsoft asembler

Informativno

Page 86: X86 asembler

Definisanje potprograma (Microsoft asembler)

• name PROC [FAR|NEAR] – start potprograma. – Može biti:

• bliski (pri pozivu se koristi samo EIP) ili• daleki (koriste se i CS i EIP).

– Podrazumjevana vrijednost zavisi od modela (flat – near)– Moguće definisati i konvenciju pozivanja, kao i parametre

• <naziv>PROC[<lang>][<ostali_atributi>] {,<param>:<tip>}<lang> - neka od konvencija pozivanja :

– U slučaju definisanja konvencije pozivanja, umeću se i odgovarajuće instrukcije za navedenu konvenciju pozivanja:npr. za C, na početku: PUSH EBP MOV EBP, ESPi pred svaki ret: POP EBP

• name ENDP – kraj potprograma name. – Ne proizvodi nijednu instrukciju, pa je potrebno ispred staviti ret ili neku drugu

instrukciju za kontrolu toka, kako bi se osigurali da nikada neće doći do neregularne situacije.

Page 87: X86 asembler

Uvoženje i izvoženje simbola

• public name[,name...] – izvoz iz fajla

• extern name:type [,name:type...] – uvoz– Neki asembleri dozvoljavaju izostavljanje tipa– U MASM, tip je obavezan

• Novi pristup je direktiva externdef koja mijenja obje prethodne direktive:– Ukoliko je simbol definisan u fajlu u kojem se nalazi

direktiva, tada je to simbol koji se izvozi– Ukoliko simbol naveden u direktivi nije definisan, tada je to

simbol koji se uvozi– Sintaksa kao kod EXTERN direktive

Page 88: X86 asembler

Definisanje prototipa potprograma

• Direktiva PROTO• Prednosti:

– definiše prototip potprograma => poziv sa INVOKE

– dodjeljuje nazive parametrima (umjesto pomjeraja)– ova direktiva automatski generiše i odgovarajući EXTERNDEF

• Sintaksa:• <naziv>PROTO[<lang>][<ostali_atributi>] {,<param>:<tip>}

<lang> - neka od konvencija pozivanja.• Neophodno je na isti način definisati i sam potprogram (PROTO

zamjeniti sa PROC).• Moguće definisati i lokalne promjenljive:LOCAL <lvar>:<tip> {, <lvar>:<tip>} => pogodno za pristupanje lokalnim promjenljivim bez računanja

pomjeraja.

Page 89: X86 asembler

INVOKE

• Potprogrami definisani u skladu sa prethodnim slajdom, pomoću INVOKE mogu biti pozvani slično pozivima u višim programskim jezicima.

• Primjer:f1 PROC C par1:DWORD, par2:DWORD

mov EAX, par1add EAX, par2

f1 ENDP

f1 PROTO C param1:DWORD, param2:DWORD

INVOKE f1, EAX, EBX ;ekvivalentno sa:;push EBX;push EAX;call f1;add ESP, 8

Page 90: X86 asembler

Definisanje segmenata

• Pojednostavljene direktive (MASM):• klasa segmenta. Standardno:

.stack – stek (ne mora da se navodi)

.code – programski kod

.data – inicijalizovani podaci

.data? – neinicijalizovani podaci• Na početku programa navesti:

– .386P ; za koji procesor su naredbe– .model flat ; za linearne adrese– iza flat je moguće navesti standardnu konvenciju

pozivanja potprograma

Page 91: X86 asembler

Start programa

• end [label] – kraj programa

• ako postoji label, to je oznaka početka programa

• Pri linkovanju više fajlova, samo jedan smije imati ulaznu tačku (početak)

Page 92: X86 asembler

Definisanje podataka i poravnavanje

• even – poravnava sledeću promjenljivu na parnu adresu. Dobra praksa zbog bržeg pristupa memoriji.

• Rezervisanje prostora u memoriji:– Bajt:

[name] DB init [,init...] – Riječ (2B):

[name] DW init [,init...]– Dupla riječ (4B) :

[name] DD init [,init...]– Dvostruka dupla riječ (8B)

[name] DQ init [,init...]• Za svaku početnu vrijednost se rezerviše jedna lokacija.• count DUP (init [,init...])

– ponavlja ono što je u () onoliko puta koliko je vrijednost count.• ? – neinicijalizovana lokacija

Page 93: X86 asembler

Primjer

• a DB 2 – ;jedan bajt kojem se pristupa sa a

• b DW 3 DUP(?)– ;3 neinicijalizovane riječi, sa b se pristupa prvoj, a sa

b+2 i b+4 naredne dvije• c DB "Tekst$"

– ;niz od 6 bajtova• d DD c

– ;jedna dupla riječ sa segmentom i ofsetom od c• f DB 4 DUP(0,1)

– ;8 bajtova inicijalizovanih sa 0,1,0,1,0,1,0,1

Page 94: X86 asembler

Direktive

• name EQU expr – svako pojavljivanje name zamjenjuje sa expr.

• include file – uključuje sadržaj fajla file na poziciju ove direktive.

• OFFSET expr – vraća ofset izraza.

• BYTE PTR expr – pristup bajtu.

• WORD PTR expr – pristup riječi.

• LENGTH var – broj elemenata u nizovnim prom.

Page 95: X86 asembler

Bezimene labele (Microsoft asembler)

• Kao labela se može koristiti @@:

• Na labelu se referiše sa:@B - ako se želi prva bezimena labela unazad

@F - ako se želi prva bezimena labela unaprijed

Page 96: X86 asembler

Uslovno prevođenje

• IFDEF name – uslovno preveđenje.• ELSE• ENDIF

Page 97: X86 asembler

Makroi 1/2

• Početak makroa:name MACRO arg [,arg...]– name – naziv makroa– Arg - parametri

• ENDM – kraj makroa.• LOCAL name [,name...] – lokalni simboli za makro.

– Neophodno za labele u makrou, kako bi se jedan makro mogao ekspandovati više puta u okviru jednog koda bez problema dupliranih labela.

Page 98: X86 asembler

Makroi 2/2

• IRP param, <arg,[,arg...]>– ;ovaj segment koda se ponavlja onoliko puta koliko ima– ;argumenata i to tako da se svaki put umjesto svakog

pojavljivanja– ;param zamjeni jedna vrijednost arg.

• ENDM • IRPC param, <string>

– ;isto kao prethodno, osim čto su argumenti slova navedenog stringa

• ENDM• & - operator prepoznavanja parametra u tekstu