X86 asembler

Post on 29-Jan-2016

113 Views

Category:

Documents

6 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

Transcript

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.

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

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

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

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.

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.

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

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.

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.

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.

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)

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.

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

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 ...

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]

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

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.

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).

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

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

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

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

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?

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).

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

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

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

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

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.

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

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

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

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

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

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

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

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.

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)

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)

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) >

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.

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

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

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

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

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

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

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.

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>

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

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

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

P5b.c (potprogram)

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

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

}

p5a.s (program)

• Isti kao p4a.s

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

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

p6b.s (potprogram)

• Isti kao p4b.s

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;}

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

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

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

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.

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.

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

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

Rekurzivne funkcije

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

• Koristiti stdcall konvenciju pozivanja.

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.

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

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

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

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

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

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]

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

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

Primjeri rada sa WIN32 API

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 _ExitProcess@4.end

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>

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

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

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).

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)

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

Microsoft asembler

Informativno

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.

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

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.

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

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

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)

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

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

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.

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

Uslovno prevođenje

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

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.

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

top related