You are on page 1of 35

MIKRORACUNARI

SKRIPTA ZA SPREMANJE PISMENOG ISPITA

-1-

Predgovor
Ovo je skriptica koju sam pravio prilikom spremanja pismenog dela ispita iz Mikroracunara. U njoj nisam obradio SSE2 instrukcije, posto su one nadogradjene SSE instrukcije, a sve su lepo napisane u knjizi Ace Samardzica :) Srecno :) Viktor

-2-

Procesor (CPU - Central Processing Unit ili ISP - Instruction Set Processor) Osnovnu strukturu cpu-a mozemo podeliti na ALU i CU jedinicu. ALU obavlja obradu podataka dok CU kontrolise prenos podaka i instrukcija u i iz procesora. Savremeni mikroprocesori imaju i druge funkcionalne jedinice. Program se sastoji od masinskih instrukcija. Da bi se program izvrsio, procesor dohvata jednu po jednu instrukciju i izvrsava odgovarajucu operaciju. Procesor vodi o adresi memorijske lokacije koja sadrzi narednu instrukciju koja treba da se izvrsi pomocu PC (program counter) registra. Sadrzaj ovog registara se u toku izvrsenja tekuce instrukcije updejtuje da pokazuje na narednu instrukciju u nizu. Bitan je IR registar (instruction register) koji sadrzi poslednju procitanu instrukciju. Ako svaka instrukcija ima 4 bajta izvrsenje instrukcije izgleda : 1. dohvata se sadrzaj memorijske lokacije na koju pokazuje PC i ona se ucitava u IR IR <- [[PC]] 2. sadrzaj PC se uvecava za 4 ( prelazi se na sledecu instrukciju) PC<- [PC]+4 3. izvrsava se instrukciaj u IR Koraci 1 i 2 se nazivaju fazom dohvatanja instrukcija a korak 3 je faza izvrsavanja instrukcije. Prenos podataka izmedju registara. Svaki registar ima 2 kontrolna signala koji koristi za prosledjivanje sadrzaja na magistralu ili za ucitavanje podataka sa magistrale u registar. Svi transferi se odvijaju u vremenskim intervalima koje odredjuje casovnik procesora. Brojevi i operacije sa njima Razlikujemo oznacene i neoznacene brojeve. Broj je neoznacen ako ne sadrzi znak. oni se predstavljaju u klasicnom obliku:

A = 2 i ai za broj an-1....a1a0 .
i =0

n 1

Broj je iznacen ako mu an-1 predstavlja znak broja. an-1 = 0 broj je pozitivan, an-1 = 1 broj je negativan. Za koriscenje oznacenih celih brojeva koriste se sledece notacije.
1.Znak i apsolutna vrednost. Krajnji levi bit je znak a ostali n-1 bitova je apsolutna vrednost. Negativan broj se dobija tako sto se u odgovarajucoj reprezentaciji pozitivne vrednosti tog broja zameni bit navece tezine sa 0 na 1. +5 je 0101 -5 je 1101 2.Nepotpuni komplement ( Prvi komplement) Pozitivni brojevi se zapisuju kao u zapisu znak i apsolutna vrednost. Negativan broj je predstavljen kao broj koji se dobija kada se svaka cifra u zapisu apsolutne vrednosti broja A zameni njenim komplmentom do najvece cifre brojcanog sistema. +3 0011 -3 1100 3. Potpuni komplment(Drugi komplement). Pozitivni se predstavljaju isto kao pod 1. Negativan broj se predstavlja kao broj koji se dobija kada se u zapisu nepotpunog komplementa broja A doda jedinica na mesto najmanje tezine.

Sabiranje pozitivnih brojeva (primer): 0 1 0 1 +0 + 0 +1 +1 ____ ____ ____ _____ 0 1 1 10 U poslednjem slucaju kazemo da je suma 0 i prenos(carry-out) je 1. Prekoracenje moze da nastupi samo pri sabiranju dva broja istog znaka. Najjednostavniji nacin da proverimo da li je doslo do prekoracenje je da uporedimo znakove sabiraka x i y sa znakom sume. Ako su oba sabirka istog znaka do prekoracenja dolazi ako znak sume nije isti kao znak x i y. Memorija Memorija se sastoji od vise miliona memorijskih celija koje cuvaju po jedan bit informacije i imaju vrednost 1 ili 0. Bitovi se uglavnom grupisu u grupe fiksne velicine koje se obradjuju odjednom. 8 bitova - > bajt Svaka grupa od n bitova se oznacava kao rec. a broj ne predstavlja duzinu reci. Duzine reci kod danasnjih racunara se krecu izmedju 16 i 64 bita. Masinske instrukcije mogu zahtevati jednu ili vise reci za svoju reprezentaciju. Bajt-adresibilna memorija je memorija u kojoj uzastopne adrese referisu na uzastopne brojeve u memroiji- takav je slucaj skoro kod svih modernih racuanra. Sve teorijski moguce adrese formiraju adresni prostor racunara. Postoje 2 nacina adresiranja bajtova u reci: 1. big-endian gde se na adresi sa manjim brojem nalazi bajt vece tezine u reci 1. little-endian gde se na adresi sa manjim brojem nalazi bajt manje tezine u reci

-3-

Pravljenje make fajla


Ime make fajla je Makefile ili makefile. Ako u tekucem direktorijumu imamo makefile pozivamo ga naredbom make. Pravila u makefile-u imaju striktan format. U prvoj liniji se navodi fajl koga treba azurirati kada se neki drugi fajlovi promene(cilj), zatim sledi dvotacka, a potom lista fajlova od kojih je ovaj prvi zavisan(lista zavisnosti). Zatim slede redovi koji sadrze komande za regenerisanje cilja na osnovu zavisnosi i svaki od njih mora da pocinje sa tab znakom. Primer :
hello: hello.c gcc -o hello hello.c

makefile uglavnom sadrzi veliki broj pravila. i make uvek izvrsava samo jedno pravilo o to ili ono koje je prvo u listi ako iza naredbe make nije nista navedeno ili ono ciji je cilj naveden iza make naredbe. Ukoliko se u tim zavisnostima javi neki drugi cilj iz makefajla onda se rekurzivno izvrsava i pravilo koje se odnosi na taj drugi cilj i tako redom. Tako da bi tu trebalo voditi racuna! Ako je make pokrenut bez argumenata prvo se analizira prvo pravilo. Promenljive se uvode tako sto se navede ime promenljive zatim znak jednakosti i onda vrednost koja se dodeljuje promenljivoj. Referenciranje se vrsi tako sto se ime promenljive navede izmedju obicnih zagrada sa znakom $ kao prefiksom. Primer:
CC=gcc hello: hello.c $(CC) -o hello hello.c

Specijalne promenljive:

$@ - predstavlja cilj pravila $^ - lista svih zavisnosti pravila $< - sadrzi prvu iz liste zavisnosti

Primer:
CC=gcc hello: hello.c $(CC) -o $@ $<

Propustanje koda kroz beautifier-a i ciscenje nepotrebnih fajlova: Primer:


CC=gcc PROGRAM=hello $(PROGRAM): hello.c $(CC) -ansi -c -o hello.o $< $(CC) -o $@ hello.o .PHONY: beauty clean beauty: -indent -kr *.c //opciono i *.h -rm *~ clean: -rm *.o

indent je alat namenjen formatiranju C koda. Upotreba : iza imena programa navede se ime fajla koji treba obraditi (indent hello.c). Reformatirani kod ce biti sacuvan u fajlu sa istim imenom, dok ce originalni sadrzaj fajla biti sacuvan u fajlu sa sufiksom ~. Ako se doda -o mozemo dati ime gde da se cuva reformatirani fajl (indent hello.c -o hello1.c). Kernigan-Rici stil se postize dodavanjem opcije -kr ( indent -kr hello.c)

-4-

IA- 32
Intel Arhitektura - IA IA-32 su procesori sa 32-bitnim memorijskim operandima i 32-bitnim operandima podacima. Prvi IA32 procesor he 80386 koji se pojavio 1985. Od tada su nastali 80486(1989) , Pentium(1993), Pentium Pro(1995), Pentium II (1997), Pentium III (1999) ,Pentium IV (2000)

Kod IA32 arhitetkure vaze sledece osobine: - memorija je bajt adresibilna - adrese su duzine 32 bita - instrukcije operisu nad podacima duzine 8 ili 32 (bajt ili dvostruka rec). Operand duzine 16 je rec. - little-endian adresiranje memorije Skup registara Prvu grupu registara cine registri opste namene : EAX - tu se ostavlja povratna vrednost funkcije, pri ALU operacijama EBX ECX - brojac u petljama EDX ESI - adrese elemenata stringova EDI - adrese elemenata stringova ESP - za rad sa stekom EBP - za rad sa stekom ali u potprogramima ( u njega kopiramo sadrzaj ESP) Nizih 16 bita mogu biti individualno adresirani kao na slici. Sledecu grupu cine segmentni registri: CS, SS, DS, ES, FS i GS. Koriste se za podrsku segment organizovanoj memoriji. Ostala su jos dva registra EIP i EFLAGS kojima se ne moze pristupiti direktno vec se njihov sadrzaj menja izvrsavanjem odgovarajucih instrukcija. EIP - Instruction pointer registar koji cuva adresu naredne instrukcije odnosno ponasa se kao PC registar. EFLAGS - sadrzi vrednosti raznih flegova. Znacajni flegovi su CF- carry fleg koji nastaja ako je doslo do prekoracenja pri sabiranju ili oduzimanju, ZF - zero fleg koji se postavlja ako je rezultat jednak 0 ...
Adresiranje operanada IA32 instrukcije mogu imati 0, 1 ili vise operanada. On moze biti zadata direktno u instrukciji ili se moze nalazitu u registru, memoriji ili UI portu. Osim memorijskih svi operandi se adresiju direktno. Adresa memeorijskh operanada se moze sastojati od vise komponenti : base, index, scale i displacement odnosno b, i ,s i d. Adresa operanda se izracunava kao b+i*s+d.

Pristup nizu ako je ECX brojac, a u ESI je adresa prvog elementa niza -> [ESI + 4*ECX]
Tipovi podataka IA32 uzima za operande vrednosti duzine 1, 2 , 4 , 8 ili 16 bajtova 1 - bytes 2 - words 4 - doublewords 8 - quadwords 16 - double quadwords tipovi podataka sa kojima procesor radi su neoznaceni i oznaceni celi brojevi, realni brojevi, pointeri, polja bitova, stringovi SIMID tipovi podataka, BCD brojevi.

-5-

Rad sa asemblerom Da bi koristili intelovu sintaksu koristimo direktivu na samom pocetku .intel_syntax noprefix noprefix- imena registara ne treba da imaju % prefiks koji asembler iance ocekuje Asemblerske direktive se ne prevode! One uticu na prevodjenje! Naredbe se razdvajaju novim redom ili dvotackom Komentari pocinju sa # Direktive : .data definise sekciju gde se deklarisu podaci cije vrednosti treba da budu inicijalizovane u memoriji. Svaka deklaracija se sastoji od tri dela ime_podatka: .tip_podatka vrednost .bss se koristi za neinicijalizovane podatke. Memorijske promenljive se u ovoj sekciji deklarisu pomocu .lcomm direktive koju slede zarezom razvojeni ime promenljive i broj bajtova koje ista u memoriji zauzima. .bss .lcomm x, 4 Direktiva .ascii .asciz .byte .double .float .int .octa .quad .short Tip podataka string string terminiran nulom 8 bitni ceo broj 64 bitni realan broj 32 bitni realan broj 32 bitni ceo broj 128 bitni ceo broj 64 bitni ceo broj 16 bitni ceo broj

.text - sekcija za kod .global main - oznacava da je simbol main vidljiv i izvan objektnog fajla. Simbol main oznacava pocetak programa
.intel_syntax noprefix .data fmt: .asciz "Hello\n" .text .global main main: enter 0,0 pusha lea eax, fmt push eax call printf add esp, 4

Koristi se za raunanje efektivne adrese. scanf("%d",&x);

#stek raste prema nizim adresama pa zato ovako mozemo skinuti fmt sa #steka

popa xor eax, eax leave ret

Pri radu sa asemblerom treba voditi racuna da se argumenti prenose preko steka. Stek je deo memorije kome s e pristupa po LIFO principu, za rad sa njim koriste se PUSH i POP instrukcije. Prenosenje argumenata proceduri sastoji se od stavljanja istih na stek i to obrnutim redom! Kompajliranje : Fajlovi sa asemblerskim kodom imaju ekstenziju .s as - o hello.o hello.s gcc -o hello hello.o

-6-

Aritmeticko logicke instrukcije Instrukcije koje implementiraju binarne operacije najcesce upisuju rezultat u priv operand! Prvi operand zato ne moze biti konstanta! Samo jedan moze biti memorijski operand, drugi mora biti registar ili konstanta Menmonik ADD ADC SUB SBB INC DEC CMP NEG MUL Operacija sabiranje sabiranje sa prenosom oduzimanje oduzimanje sa pozajmicom inkrementiranje, kao i DEC radi sa jednim operandom dekrementiranje poredjenje, menja vrednosti flagova i nigde ne smesta rezultat, radi isto sto i SUB instrukcija promena znaka, tretira operan kao oznacen broj mnozenje neoznacenih brojeva ima samo jedan operand koji moze biti vrednost u registru ili u memroiji Ovaj operand se mnozi sa sadrzajem registra AL, AX ili EAX( u zavisnosti od sirine operanda), pri cemu rezultat biva smeste respektivno u registe AX, DX:AX odnosno EDX:EAX DX:AX - to znaci da se DX odnosi na vise bitove podataka a AX na nize
mov eax, x imul dword ptr y push eax

Instrukcije imul i idiv prihvataju 8 bitni, 16 bitni i 32 bitni operand, kada se navodi vrednosti iz memorije njena sirina nije implicitno odredjena, pa se dodaje prefix
BYTE PTR - 8-bitni operand WORD PTR - 16-bitni operand DWORD PTR - 32- bitni operand QWORD PTR - 64-bitni operand

IMUL DIV

mnozenje oznacenih brojeva deljenje neoznacenih brojeva ima samo jedan operand koji moze biti vrednost u registru ili u memroiji
mov eax, x cdq idiv dword ptr y push eax

Pri deljenju delilac se nalazi u EDX:EAX registrima. Zato treba registar EAX upisati u registar EDX. Za to koristimo CDQ instrukciju koja prosiruje 32bitnu vrednosu iz eax u 64bitnu u edx:eax registrima U registru EAX se nalazi celobrojni koicnika, a u EDX ostatak pri deljenju. Npr. ako delimo 23 sa 10, u eax se nalazi 2 a u edx 3 IDIV AND OR NOT XOR deljenje oznacenih brojeva bitska konjukcija bitska disjunkcija bitska negacija bitska operacija xor

-7-

Instrukcije za transfer podataka Menmonik MOV CMOV Operacija prenos podataka vazi sve kao i za binarne instrukcije- samo jedan moze biti memorijska lokacija uslovni prenos podataka uslov se tice flegova u EFLAGS registru sufiksi : Kao i kod instrukcija skokova, sto idu posle J podrzane od PentiumPro procesora razmena podataka razmenjuje sadrzaj svoja dva operanda promena redosleda bajtova razmena i sabiranje podataka prvo razmenjuje a onda izracunava zbir i smesta ga u odredisni operand testiranje i razmena podataka tri operanda porede dva operanda, pa ako su jednaki zamenjuju drugi sa trecim a ako nisu ucitavaju drugi u prvi radi sa 32 bitnim vrednostima prvi operand je implicitno EAX testiranje i razmena 64bitnih podataka tri operanda isto kao i cmpxchg radi sa 64bitnim operandima prvi i treci su implicitno refistri EDX:EAX odnosno ECX:EBX stavljanje na stek umanjuje esp za odgovarajuci broj i stavlja dati podatak na novu adresu na koju pokazuje ovaj registar skidanje sa steka uvecava vrednost esp registra stavljanje registara optse namene na stek skidanje registara opste namene sa steka koverzija 8bitne u 16bitnu vrednost AL->AX konverzija 16bitne u 32bitnu vrednost AX->DX:AX konverzija 16bitne u 32bitnu vrednost AX->EAX konverzija 32bitne u 64bitnu vrednost EAX->EDX:EAX prenos podataka uz prosirivanje ocuvanjem znaka prenos podataka uz prosirivanje popunjavanjem nulama

XCHG

BSWAP XADD

CMPXCHG

CMPXCHG8

PUSH

POP PUSHA POPA CBW

CWD

CWDE

CDQ

MOVSX MOVZX

-8-

Instrukcije kontrole toka Instrukcije bezuslovnog skoka: Mnemonik Operacija bezuslovni skok JMP ucitava u EIP registar adresu koja je zadata kao operan cime se izvrsavanje nastavlja instrukcijom koja se nalazi na toj adresi poziv potprograma CALL povratak iz potprograma RET Instrukcije uslovnog skoka : Proveravaju flegove u EFLAGS registru i vrse skok ako je dati uslov zadovoljen. Mnemonik Operacija JA/JNBE skok ako je vece JAE/JNB skok ako je vece ili jednako JB/JNAE skok ako je manje JBE/JNA skok ako je manje ili jednako skok ako ima prenosa JC skok ako je jednako JE/JZ Primer: poredimo da li je uneti karakter jednak znaku '+', znaci da prethodno sledi CMP radi provere
cmp al, op je addition

JNC JNE/JNZ JP/JPE JNP/JPO JCXZ JECXZ JG/JNLE JGE/JNL JL/JNGE JLE/JNG JNO JNS JO JS

skok ako nema prenosa(jednako 0) skok ako nije jednako(razlicito od nule) skok ako je parnost parna skok ako je parnost neparna skok ako je registar CX jednak 0 skok ako je registar ECX jedna 0 Oznaceni brojevi skok ako je vece skok ako je vece ili jednako skok ako je manje skok ako je manje ili jednako skok ako nema prekoracenja skok ako je pozitivno skok ako ima prekoracenja skok ako je negativno

Instrukcije za brojacke petlje: Mnemonik Operacija Obicna instrukcija brojacke petlje LOOP Instrukcija LOOP dekrementira sadrzaj ECX registra i ukoliko nova vrednost nije jednaka 0, skace na adresu datu operandom. Petlje ovog tipa se izvrse bar jednom zato je pogodno koristiti naredbu JECXZ pa ako je brojac jednak 0 moze se preskociti citava petlja
next: .... loop next:

LOOPE/LOOPZ LOOPNE/LOOPNZ

instrukcija brojacke petlje sa izlaskom ako ZF=0 instrukcija brojacke petlje sa izlasko ako ZF=1 Tekuci element je jednak trazenom

-9-

Instrukcije za rad sa stringovima String predstavlja kontinualan niz bitova, bajtova, wordova ili double word-ova. Instrukcije za rad sa stringovima imaju uglavnom implicitne operande. Adrese elemenata stringova koji ucestvuju u operaciji moraju biti u registrima ESI odnosno EDI. Velicina operanda je odredjena sufiksom instrukcije : B za 8bit, W za 16bit, D za 32bit. Po izvrsenju odgovarajuce operacije sadrzaj registra ESI i/ili EDI se azurira tako da pokazuju na naredni ili prethodni element stringa, sto je odredjeno vrednoscu direction flega u EFLAGS registru. Ako je on 0(CLD) onda se sadrzaj uvecava za odgovarajuci broj bajtova, ako je 1(STD) onda se umanjuje. Mnemonik Operacija kopiranje elemenata stringa MOVS poredjenje elemenata stringova CMPS poredjenja elemenata stringa sa datom vrednoscu SCAS Vrednost sa kojom se poredi tekuci element stringa nalazi se u AL, AX odn EAX refistru zavisno od sufiksa instrukcije ucitavanje elemenata stringa u registar, ucitava iz registra esi LODS smestanje sadrzaja registra u element stringa, ucitava u adresu koja se nalazi u registru edi STOS
#poredi dva stringa .intel_syntax noprefix .data wrfmt: .asciz "%c\n" .bss .lcomm s0, 80 .lcomm s1, 80 .text .global main main: enter 0,0 pusha lea eax, s0 push eax call gets add esp, 4 lea eax, s1 push eax call gets add esp, 4 cld # duzina prvog stringa, string je terminiran # nulom, pa u al stavljamo 0 a u edi adresu # prvog karaktere u onda sa scas ispitujemo # redom dok ne nadjemo na nulu, Akumuliramo # duzinu u ecx xor al, al lea edi, s0 xor ecx, ecx next_char0: scasb je compare inc ecx jmp next_char0 compare: inc ecx #da bi ukljucili i termalni kar. lea esi, s0 lea edi, s1 #poredjenje stringova next_char1: cmpsb loope next_char1 # ako je petlja zavrsena jer su pronadjena dva # razlicita karaktera u al se smesta n a u # suprotnom se smesta y jme xor mov jmp not_equal: not_equal eax, eax al, 'y' print

xor eax, eax mov al, 'n' print: push eax lea eax, wrfmt push eax call printf add esp, 8 popa xor eax, eax leave ret

Instrukcije sa stringovima se cesto koriste u petljama zato IA32 podrzava prefikse koji se mogu njima dodati i omogucavaju da se petlje kompaktno zapisu. Ovde se isto kao i kod LOOP instrukcije dekrementira ECX registar. Prefiks Znacenje ponavljanje instrukcije sve dok je ECX razlicito od 0 REP ponavljanje sve dok je ECX razlicito od nule i ZF=0 REPE/REPZ
next_char1: cmpsb = loopz next_char1 repz cmpsb

REPNE/REPNZ

ponavljanje sve dok su ECX i ZF razliciti od nule - 10 -

Instrukcije za rad sa flegovima Mnemonik STC CLC CMC STD CLD STI CLI LAHF SAHF PUSHF POPF PUSHFD POPFD Operacija postavlja carry fleg na 1 postavlja carry fleg na 0 komplemntiranje vrednosti carry flega postavlja direction fleg na 1 postavlja direction fleg na 0 postavlja interrupt fleg na 1 postavlja interrupt fleg na 0 ucitavanje bajta najmanje tezine EFLAGS registra u AH registar ucitavanje sadrzaja AH registra u bajt najmanje tezine EFLAGS registra stavljanje nizih 16 bitova EFLAGS registra na stek skidanje 16bitne vrednosti sa steka u nizih 16 bita EFLAGS registra stavljanje EFLAGS registra na stek skidanej 32bit vrednosti sa steka u EFLAGS registar

Preostale instrukcije opste namene Mnemonik LEA XLATB Operacija izracunavanje efektivne adrese date memorijske promenljive i smesta je u zadati registar opste namene instrukcija za lookup u tabeli Pristupa elementu polja bajtova u memoriji cija je adresa prvog elementa data u registru EBX a index elementa u AL, ucitava sadrzaj ovog elementa u AL insturkcija za detekciju procesora Pupunjava registre EAX,EBX,ECX, EDX sa informacijama o procesoru instrukcija koja ne radi nista samo uvecava sadrzaj EIP registra nedefinisana instrukcija

CPUID NOP UD2

Bitske instrukcije Mnemonik SHL/SAL SHR SAR SHLD SHRD ROL ROR RCL RCR BT BTS BTR BTC BSF BSR SET TEST Operacija logicko i aritmericko siftovanje ulevo logicko siftovanje udesno aritmeticko siftovanje udesno siftovanje ulevo iz drugog podatka siftovanje udesno iz drugog podatka rotacija ulevo rotacija udesno rotacija ulevo kroz CF rotacija udesno kroz CF testiranje bita testiranje i postavljanje bita na vrednost 1 testiranje i postavljanje bita na vrednost 0 testiranje i komplementiranje vrednosti bita pretrazivanje prema bitu najvece tezine pretrazivanje prema bitu najmanje tezine postavljanje bajta prema vrednosti flega bitska konjunkcija bez upisa rezultata

- 11 -

Potprogrami Potprogram po svom zavrsetku mora da zna da se vrati na instrukciju koja se nalazi iza instrukcije kojom je potprogram pozvan - > na IA32 cuva se povratna adresa na steku. CALL-> pre nego sto se skoci povratna adresa se stavlja na stek RET -> zavrsava se rad potprograma i skida se sa steka povratna adresa pa se bezuslovno skace na nju. RET ima forum u kojoj ima operand, a to je broj koji treba dodati na sadrzaj ESP registra(argumente koje prenosimo potprogramu) Argumenti se potprogramu prenose pomocu steka. Pre poziva potprograma argumenti se stavljaju na stek (samo 32bit vrednosti). Program im pristupa direktno. Problem : sto se ESP registar moze promeniti i tako da se argumenti ne mogu lako adresirati zato se standardno pristupa preko EBP u koji se odmah po ulasku stavlja na stek i u njega se kopira vrednost ESP registra, pa se stanje EBP registra vise ne menja, na kraju vracamo sadrzaj EBP regisra(tj skidamo ga sa steka - pogledati enter 0,0) Vracabhe rezultata se vrsi preko EAX registra.
.intel_syntax noprefix .data rdfmt: .asciz "%d" wrtfmt: .asciz "%d\n" .bss n: .int 1 .text .global main main: enter 0,0 pusha lea eax, n push eax lea eax, rdfmt push eax call scanf add esp, 8 mov eax, n push eax call fact push eax lea eax, wrtfmt push eax call printf add esp, 8 popa xor eax, eax leave ret fact: push ebp mov ebp, esp mov eax, [ebp+8] cmp eax ,1 jg recursion mov eax, 1 jmp done recursion : dec eax push eax call fact imul dword ptr [ebp+8] done : pop ebp ret 4

n povratna adresa EBP EBP stack frame


pravac rasta steka

Lokalne promenljive : na pocetku potprograma alociramo prostor za njih na steku tako sto od esp registra oduzmeom broj bajtova koji je potreban za njih, na kraju ne treba zaboraviti da treba dotai esp registur odgovarajuci broj bajtova. One postaju deo stack frame-a ENTER L, 0 zamenjuje sledecu sekvencu LEAVE zamenjuje sekvecu push ebp mov esp, ebp mov ebp, esp pop ebp sub esp, L - 12 -

Pozivanje asemblerskog i C koda C program stavlja argumente potprograma na stek i to pocev od poslednjeg argumenta prema prvome. Rezultat potprograma se vraca u registar EAX ili ST(0) Potprogrami moraju da ocuvaju sadrzaj registra EBX, ESI, EDI i EBP. Podebljani registri NE SMEJU da se menjaju, moraju biti ocuvani! Pozivanje funkcije za racunanje faktorijela iz prethodnog primera:
main.c #include <stdio.h> extern int fact(int); int main() { int n; scanf("%d", &n); printf("%d\n", fact(n)); return 0; } fact.s .intel_syntax noprefix .text .global fact fact: enter 8,0 mov ecx, [ebp+8] mov [ebp-4], dword ptr 1 mov [ebp-8], dword ptr 2 next: cmp [ebp-8],ecx jg done mov eax, [ebp-4] imul dword ptr [ebp-8] mov [ebp-4], eax inc dword ptr [ebp-8] jmp next done: mov eax, [ebp-4] leave ret

Makefile koji pokrece ovaj program treba da izgleda: fact: fact.o main.o gcc -o fact fact.o main.o fact.o: fact.s as -o fact.o fact.s main.o:main.c gcc -c -o main.o main.c Prenos pokazivaca kao argumenata funkcije: Neka se pokazivac nalazi na ebp+8 adresi na steku mov ebx, [ebp+8] # kopiramo podatak(pokazivac) sa adrese ebp+8 u registar ebx mov [ebx], <podatak> # kopiramo zeljeni podatak na adresu na koju pokazuje ebx Prvo se mora iskopirati neki podatak iz memorije u registar, a zatim dereferencirati, jer se jedino mogu dereferencirati registri(sintaksa [ebx])

- 13 -

Rad sa realnim brojevima


Realni brojevi se predstavljaju nizom od 32 (single-precision) ili 64(double precision) bita. Bit najvece tezine je bit znaka i ima brednost 0 za pozitivne i 1 za negativne brojeva. Ostatak broja je podeljen na eksponent i mantisu. Ukoliko su bitovi eksponenta i mantise jednaki 0 onda je broj 0. Ukoliko su svi bitovi eksponenta jednaki 1, a mantisa jednaka 0, radi se o nizu bitova kojim se predtavljaju vrednosti plus i minus beskonacno. Na kraju ukoliko su svi bitovi eksponenta jednaki 1 a mantisa razlicita od nule, radi se o NaN vrednosti. Rad sa realnim brojevima u prvim verzijama 80386 kao i kod 80486 bio je izdvojen u numericki procesor. Sada je integrisan, ali se koristi naziv FPU(floating point unit). Registri numerickog koprocesora: Skup registara se sastoji od 8 registara za podatke duzine 80 bita (R0,...,R7), kontrolnog, statusnog i tag registra. Registri za podatke cuvaju brojeve u formatu sa prosirenom preciznoscu (15bitova za eksponent i 64 za mantisu). Oni se koriste kao stek! U statusnom registru jedno polje odredjuje koji je registar vrh steka. ST(0) ili ST- Vrh steka, a zatim redom ide ST(1), ST(2) Statusni registar sadrzi flegove koji ukazuju na to da li je doslo do greske. Kontrolni registar sadrzi bitove kojima se dozvoljava ili sprecava generisanje odgovarajuceg prekida ako dodje do greske prilikom izracunavanja, te preciznost... Tag registar opisuje sadrzaj registra za podatke (za svaki 2bita), tj da li je u registru nalazi validna vrednost, nula, specijalna vrednost ili je prazan. Instrukcije za transfer podataka Mnemonik FLD Operacija ucitavanje realnog broja iz memorije i smestanje na vrh steka za podatka. Operand moze biti u single DWORD PTR (float) double QWORD PTR (double) ili extended preciznosti Posle nje ST -> na ST(1) Moze imati kao operand i neki registar sa steka i tada se sadrzaj tog registra kopira na vrh steka. Isto tako i FST i FSTP ucitavanje celog broja iz memorije, u extended precisznosti upis realnog broja u memoriju, broj sa vrha steka upisuju na zadatu lokaciju upis celog broja u memoriju, broj sa vrha steka upisuju na zadatu lokaciju upis realnog broja u memoriju i njegovo skidanje sa steka upis celog broja u memoriju i njegovo skidanje sa steka razmenjuje sadrzaj registra sa vrha steka i registra koji se specificira kao operand prebacuje vrednost iz specificiranog registra u registar ST(0) ako je uslov ispunjen

FILD FST FIST FSTP FISTP FXCH FCMOV

Instrukcije za ucitavanje konstanti Mnemonik FLDZ FLD1 FLDPI FLDL2T FLDL2E FLDLG2 FLDLN2 Operacija Ucitavanje broja 0 Ucitavanje broja 1 Ucitavanje broja Ucitavanje broja log 2 10 Ucitavanje broja log 2 e Ucitavanje broja log10 2 Ucitavanje broja log e 2

Stavljaju novu vrednost na vrh steka! - 14 -

Rad sa realnim brojevima (2) Aritmeticke instrukcije

Mnemonik FADD/FADDP FIADD FSUB/FSUBP FISUB FSUBR/FSUBRP FMUL/FMULP FIMUL FDIV/FDIVP FIDIV FDIVR/FDIVPR FIDIVR FABS FCHS FSQRT FPREM FRNDINT FPREM1 FXTRACT FISUBR

Operacija Sabiranje realnih brojeva Sabiranje realnog i celog broja Oduzimanje realnih brojeva oduzimanje realnog i celog broja oduzimanje realnih brojeva sa obrnutim operandima mnozenje realnih brojeva mnozenje ralnog i celog broja deljenje realnih brojeva deljenje ralnog i celog broja deljenje realnih brojeva sa obrnutim operandima deljneje realnog i celog broja sa obrnutim operandima izracunavanje apsolutne vrednosti promena znaka operanda izracunavanje kvadratnog korena izracunavanje delimicnog ostatka zaokruzivanje na ceo broj zizracunavanje delimicnog ostatka po IEEE standardu razdvajanje eksponenta i mantise oduzimanje ralnog i celog broj sa obrnutim operandima

-Uzimaju za operande ili dva registra sa steka ili jedan registar i realan ili ceo broj iz memorije. -Instrukicije sa sufiksom P po izvrsenoj operaciji sikidaju vrednost sa vrha steka. -Kod instrukcija sa sufiksom R redosled operanada je obrnut

Primer na FADD instrukciji Prve dve varijante se odnose na 32bitni i 64bitni memorijski operand u kom slucaju se taj operand sabira sa vrednoscu reigstra ST(0) i rezultat se smesta na ST(0) Druge dve varijante imaju za operande registar ST(0) i neki drugi registar ST(i), pri cemu je u prvom slucaju prvi odredisni registar a u drugom je drugi odredisni registar. Postoje i dve varijante sa P prefiksom, prva ima dva operanda i to neki registar ST(i) kao odredisni operand a registar ST(0) kao drugi operand dok druga nema operande. U prvom slucaju se sabiraju vrednosti registra ST(i) i ST(0), rezultat se smesta u ST(i) i vrednost iz ST(0) se skida sa steka. U drugom operandi su implicitni i to ST(0) i ST(1) i rezultat se smesta u ST(1) a ST(0) se skida sa steka. FIADD postoji u dve varijante koje su ekvivalntne kao kod FADD.
add: enter 0,0 # [ebp+8] a, [ebp+12] b fld dword ptr [ebp+8] fld dword ptr [ebp+12] faddp leave ret add: enter 0,0 # [ebp+8] a, [ebp+12] b fld dword ptr [ebp+8] fadd dword ptr [ebp+12] leave ret

- 15 -

Rad sa realnim brojevima (3)

Instrukcije poredjenja Mnemonik FCOM/FCOMP/FCOMPP Operacija predjenje realnih brojeva i podstavljanje flegova koprocesora Porede vrednost u registru ST(0) sa datim operandom, ako su operandi neuredjeni generise se greska. P skida jedan, a PP skida dva sa steka -One se mogu i koristiti za skidanje nepotrebnih vrednosti sa steka ( u istu svrhu se mogu koristiti i FFREE i FINCSTP instrukcije) isto kao prethodno uz neuredjeno poredjnje poredjenje realnih i celih brojeva i azuriranje flegova koprocesora isto kao i prethodno uz neurdjeno poredjnje poredjenje realnih brojeva uz azuriranje flagova u eflags registru poredjenje sa nulom klasifikacija broja klasifikacija vrednosti iz registra ST(0) u zavisnusti da li je obican realan broj, denormalizovan, nula, beskonacan ili NaN postavljaju se flegovi statusnog registra koprocesora

FUCOM/FUCOMP/FUCOMPP FICOM/FICOMP FUCOMI/FUCOMIP FCOMI/FCOMIP FTST FXAM

Neuredjeno poredjenje se odnosi ako jedan od brojeva ima NaN vrednost. Trigonometrijske instrukcije Mnemonik FSIN FCOS FSINCOS Operacija izracunavanje sinusa izracunavanje kosinusa istovremeno i sinus i kosinus zamenjuje sadrzaj registra na vrhu steka sa njegovim sinusom a potom stavlja na stek i vrednost njegovog kosinusa izracunavanje tangensa izracunavanje inverznog tangensa racuna inverzni tangens kolicnika registra st(1) i st(0) u radijanima i smesta u st(1) a potom skida vrednost sa vrha steka

FPTAN FPATAN

Sve uzimaju operande sa vrha registarskog steka i rezultat smestaju na isti. Operandi za prve cetiri instrukcije moraju biti zadati u radijanima. Logaritamske i eksponencijalne funckcije Mnemonik FYL2X Operacija izracunavanje vrednosti y log 2 x x, y se nalaze na registrima st(0) i st(1) rezultat se smesta u registar st(1) i skida se jedna vrednost sa steka izracunavanje vrednosti y log 2 ( x + 1) izracunavanje vrednosti 2 x 1 zamnejuje izracunatu vrednost iz registra st(0). Operand mora biti u opsegu [-1,1] mnozenje stepenom dvojke

FYL2XP1 F2XM1 FSCALE

- 16 -

Rad sa realnim brojevima (4) Kontrolne instrukcije Mnemonik FINIT/FNINIT Operacija inicijalizacija koprocesora inicijalizuju koprocesor i postavljaju sve njegove registre na podrazumevanje vrednosti ucitavanje kontrolnog registra korocesora FLDCW FSTCW/FNSTCW kopiranje sadrzaja kontrolnog registra koprocesora u memoriju FSTSW/FNSTSW kopiranje sadrzaja statusnog registra u memoriju resetovanje flagova u statusnom registru FCLEX/FNCLEX ucitavanje sadrzaja svih pomocnih registara koprocesora, osim steka iz memorije FLDENV FSTENV/FSTNENV kopiranje sadrzaja svih pomocnih registara koprocesora u memoriju ucitavanje sadrzaja svih registara koprocesora FRSTOR kopiranje sadrzaja svih registara procesora FSAVE/FNSAVE inkrementiranje stek-pointera za registarski stek FINCSTP dekrementiranje stek-pointera za registarski stek FDECSTP oslobadjanje registra FFREE prazna instrukcija FNOP instrukcija za sinhronizaciju WAIT/FWAIT

Ukoliko racunamo e na x, postupak je sledeci (najveci problem je kod F2XM1 , ona radi samo sa intervalom [-1,1]!!!). Koristimo :

e x = 2 log 2 e = 2 x log 2 e
x

fld qword ptr [adresa od x] fldl2e fmulp #stek x*log2e=y fld st frndint # stek: y,int(y) fsub st(1),st fxch # int(y), y-int(y)=f f2xm1 #int(y), 2^f-1 fld1 faddp #int(y),2^f fscale #int (y),2^(f+int(y)) fxch fcomp

Koristan izraz koji jos koristimo :

r =2

log 2 ( n r )

=2

1 log 2 r n

- 17 -

Rad sa realnim brojevima (5)


.intel_syntax noprefix .data .text .global lnxplus1
########################################################################### ## Funkcija: ## double lnxplus1(double x, double eps); ## racuna vrednost ln(x+1) kao parcijalnu sumu stepenog reda, sa ## preciznoscu eps. ## double x -- [ebp+8] -- broj ciji ln(x+1) racunamo ## double eps -- [ebp+16] -- preciznost ###########################################################################

lnxplus1:
## Prolog funkcije

enter 0,0
## ## ## ## Pripremamo fpu-stek, na koji smestamo 0 (kao inicijalnu vrednost sume), argumente funkcije (x i eps), a zatim i broj 1 (kao x^0, ovaj registar cemo u svakoj iteraciji mnoziti sa x, kako bismo dobili x^n).

fldz fld qword ptr [ebp+8] fld qword ptr [ebp+16] fld1 xor ecx,ecx
## ## ## ## ##

## stek: ## ## ## stek:

0 stek: 0,x stek: 0,x,eps 0,x,eps,1

## Registar ecx ce cuvati celobrojnu vrednost n. Na pocetku svake ## iteracije cemo ga uvecavati za 1 (prvi sabirak je za n=1). Glavna petlja. U ovoj petlji racunamo sledeci sabirak, proveravamo da li je veci po apsolutnoj vrednosti od eps, i ako jeste, dodajemo ga na sumu. U komentarima nakon svake iteracije S je oznaka za sumu prvih n sabiraka, a S' je oznaka za sumu prvih n-1 sabiraka. Kada se n uveca za jedan, tada S postaje S'.

## stek: S,x,eps,x^n main_loop:


## Uvecavamo n za jedan.

inc ecx
## Racunamo x^n

## stek: S',x,eps,x^(n-1) ## stek: S',x,eps,x^n ## stek: S',x,eps,x^n,x^n

fmul st(0), st(2) fld st(0)


## Racunamo x^n/n.

push ecx fidiv dword ptr [esp] add esp,4 fld st(0) fabs fcomip st, st(3) jb done

## stek: S',x,eps,x^n,x^n/n

## Ispitujemo da li je |x^n/n| < eps

## stek: S',x,eps,x^n,x^n/n,x^n/n ## stek: S',x,eps,x^n,x^n/n,|x^n/n| ## stek: S',x,eps,x^n,x^n/n

## Ako jeste, zavrsavamo petlju. ## Proveravamo da li je n parno ili neparno.

test ecx,1 jnz add


## Za parno n, moramo da dodamo minus.

fchs add:

## stek: S',x,eps,x^n,-x^n/n

## Dodajemo sabirak na sumu, i prelazimo na sledecu iteraciju.

faddp st(4), st(0) jmp main_loop done:

## stek: S,x,eps,x^n ## stek: S,x,eps,x^n,x^n/n

## Skidamo sa fpu-steka sve vrednosti osim sume S.

fcompp fcompp
## Epilog funkcije

## stek: S,x,eps ## stek: S

leave ret

- 18 -

Rad sa realnim brojevima (6)


.intel_syntax noprefix .text .global ctg_sum
############################################################################ ## double ctg_sum(double x[], int n); ## racuna vrednost izraza: ## E = sum_{0<=i<n-1} (ctg(x_{i+1}) - ctg(x_{i})) / (x_{i+1} - x_{i}) ## -- double x[] -- ebp + 8 ## -- int n -- ebp + 12 ###########################################################################

ctg_sum: enter 0,0 push esi mov esi, [ebp+8]


## Postavljamo na stek nulu kao inicijalnu vrednost sume.

fldz mov ecx, [ebp+12] jecxz done

## stek: 0=E

## Ucitavamo broj elemenata niza. Ako je nula, preskacemo petlju.

## Umanjujemo ecx za jedan, zato sto je broj elemenata u sumi, ## pa samim tim i broj iteracija u petlji, jednak n-1.

dec ecx
## Ako je nakon ovog umanjenja ecx 0, to znaci da je u nizu bio samo ## jedan element, sto znaci da je suma opet nula, pa preskacemo petlju.

jecxz done
## Inicijalno ucitavamo na stek prvi element i njegov kotangens. ## Registar esi uvecavamo za 8, cime ga postavljamo na adresu ## sledeceg elementa u nizu.

fld qword ptr [esi] add esi,8 fld st fptan fdivrp main_loop:
## ## ## ##

## stek: E,x ## stek: E,x,x ## stek: E,x,tan(x),1 ## stek: E,x,ctg(x)


## stek: E,x,ctg(x)

Ucitavamo sledeci element, a zatim pomeramo pokazivac esi na naredni element (za sledecu iteraciju). U komentaru cemo ranije ucitani element niza preoznaciti u xp, kako bi se razlikovao od tekuceg.

fld qword ptr [esi] add esi,8 fld st fptan fdivrp fld st fsub st(0), st(3) fld st(2) fsub st(0),st(5) fdivp faddp st(5), st(0)

## stek: E,xp,ctg(xp),x

## Racunamo kotangens tekuceg elementa x

## stek: E,xp,ctg(xp),x,x ## stek: E,xp,ctg(xp),x,tan(x),1 ## stek: E,xp,ctg(xp),x,ctg(x) ## stek: E,xp,ctg(xp),x,ctg(x),ctg(x) ## stek: E,xp,ctg(xp),x,ctg(x),ctg(x)
## ## ## -ctg(xp) -ctg(xp),x -ctg(xp),x-xp

## Racunamo kolicnik iz formule.

## stek: E,xp,ctg(xp),x,ctg(x),ctg(x) ## stek: E,xp,ctg(xp),x,ctg(x),ctg(x) ## stek: E,xp,ctg(xp),x,ctg(x), ## stek: E,xp,ctg(xp),x,ctg(x)

## (ctg(x)-ctg(xp))/(x-xp) ## Dodajemo kolicnik na prethodnu sumu E i skidamo ga sa steka. ## Tekuci element postaje prethodni, pa zato njegovu vrednost i ## vrednost njegovog kotangensa kopiramo na odgovarajuce pozicije, ## kako bi stek imao istu formu kao i na pocetku iteracije.

fstp st(2) fstp st(2) loop main_loop fcompp done: pop esi: leave: ret

## stek: E,xp,ctg(x),x ## stek: E,x,ctg(x)

## Skidamo sa steka dve nepotrebne vrednosti. Na steku ostaje samo ## povratna vrednost.

## stek: E

- 19 -

Rad sa realnim brojevima (7)


.intel_syntax noprefix .text .global root
## ## ## ## ## ## ## ## Funkcija root() racuna n-ti korijen datog kompleksnog broja. Argumenti funkcije su: [ebp+8], [ebp+16] - realni i imaginarni dio datog broja [ebp+24] - broj korijena koga treba izracunati [ebp+28], [ebp+32] - adrese na koje treba smjestiti realni i imaginarni dio n-tog korijena Pretpostavlja se da je broj korijena pozitivan. Funkcija se u potpunosti podrvrgava C konvencijama pozivanja.

root:
## Prolog funkcije.

enter push ebx


## ## ## ##

0, 0

Kompleksni broj re+im*i ce biti prvo preveden u polarne koordinate r*e^(i*fi), a potom ce njegov n-ti korijen biti izracunat kao r^(1/n)*(cos(fi/n)+i*sin(fi/n)). Racuna se reciprocna vrijednost broja korijena.

fld1 # Stek: 1 fidiv dword ptr [ebp+24] # Stek: 1/n


## Racuna se polarna koordinata r=sqrt(re*re+im*im).

fld fmul fld fmul faddp fsqrt

qword ptr [ebp+16] st # qword ptr [ebp+8] # st # # #

# Stek: Stek: 1/n, Stek: 1/n, Stek: 1/n, Stek: 1/n, Stek: 1/n,

1/n, im im*im im*im, re im*im, re*re re*re+im*im sqrt(re*re+im*im)=r

## Racuna se n-ti korijen koordinate r. U komentarima je sa ## int() oznacen cjelobrojni, a sa frac() razlomljeni dio ## realnog broja.

fyl2x fld st frndint fsub st(1), st fxch f2xm1 fld1 faddp fscale fxch fcomp

# Stek: 1/n*log2(r)=log2(r^(1/n))=L # Stek: L, L # Stek: L, int(L) # Stek: L-int(L)=frac(L), int(L) # Stek: int(L), frac(L) # Stek: int(L), 2^frac(L)-1 # Stek: int(L), 2^frac(L)-1, 1 # Stek: int(L), 2^frac(L) # Stek: int(L), 2^int(L)*2^frac(L)=2^(int(L)+frac(L))=2^L # Stek: 2^L, int(L) # Stek: 2^L=2^log2(r^(1/n))=r^(1/n)

## Racuna se polarna koordinata fi.

fld qword ptr [ebp+16] # Stek: r^(1/n), im fld qword ptr [ebp+8] # Stek: r^(1/n), im, re fpatan # Stek: r^(1/n), atan(im/re)=fi ## Racuna se vrijednost fi/n, kao i sinus i kosinus toga ugla. fidiv dword ptr [ebp+24] # Stek: r^(1/n), fi/n fsincos # Stek: r^(1/n), sin(fi/n), cos(fi/n)
## Racuna se realna koordinata korijena datog kompleksnog broja ## r^(1/n)*cos(fi/n) i smjesta na odgovarajucu lokaciju u memoriji.

fmul mov fstp

st, st(2) ebx, [ebp+28] qword ptr [ebx]

# Stek:

r^(1/n), sin(fi/n), r^(1/n)*cos(fi/n) r^(1/n), sin(fi/n) r^(1/n)*sin(fi/n)

# Stek: # Stek:

## Racuna se imaginarna koordinata korijena datog kompleksnog broja ## r^(1/n)*sin(fi/n) i smjesta na odgovarajucu lokaciju u memoriji.

fmulp mov ebx, [ebp+32] fstp qword ptr [ebx]


## Epilog funkcije.

pop ebx leave ret

- 20 -

Rad sa realnim brojevima (8) Racunamo vrednost polinoma P ( x) = p 0 + p1 x + p 2 x 2 + ... + p m x m u tacki x. Radi efikasnijeg racunanje
polinom cemo da zapisemo kao P( x) = (....(((0 x + p m ) x + p m1 ) x + p m 2 ) x + ....) x + p 0
mov ecx, [ebp+8] # dimenzija polinoma -> m mov esi, [ebp+12] # adresa pocetnog koeficijenta mov eax,ecx inc eax shl eax, 3 add esi, eax fldz #stek :x, 0=S next_p: fmul st,st(1) #x,S*x fadd qword ptr [esi] #x,S*t+p_i sub esi,8 loop next_p

- 21 -

MMX instrukcije
Prva krupna ekstenzija na IA-32 arhitekturu je bilo dodavanje MMX(multimedia extensions) instrukcija, pocevsi od Pentium Pro generacije procesora. MMX uvode uslovno 8 novih 64-bitnih registara i instrukcije za paralelnu obradu nekoliko malih celobrojnih tipova. MMX koriste registre MM0,MM1,...,MM7. Ovi registri su sustinski registri matematickog koprocesora (zato moramo cuvati njegovo stanje fsafe, frestore). Prefix vecine MMX instrukcija je P. MMX ne generisu prekoracanja. One ili rade tako da ignorisu prekoracenja ili rade u rezimu saturacije kada se u slucaju prekoracenja za rezultat uzima najbliza vrednost koja se moze predstaviti datim tipom podataka. MMX registri se mogu koristiti na vise nacina, u njima se moze drzati osam 8-bitnih, cetiri 16-bitna ili dva 32-bitna broja nad kojima se mogu vrsiti paralelno odredjene operacije (ti brojevi se onda zovu pakovani operandi) ili se registi mogu koristiti kao jedan 64-bitni podatak.

SSE instrukcije
U Pentium III generaciji procesora su uvede instrukcije koje paralelno rade sa podacima koji su realni brojevi, to su SSE (streaming SIMID extensions). Slicne su MMX instrukcijama, mogu da izvrse 4 operacije nad realnim operandima u jednostrukoj tacnosti (duzine 32bita). Skup registara Skup registara je proseiren sa 8 novih 128-bitnih registara. To su XMM0,XMM1,...,XMM7. Takodje postoji i statusno-kontrolni registar MXCSR. SSE instrukcije uvek tretiraju sadrzaj SSE registara kao 4 realna 32-bitna (single precision) broja. Postoje dve varijante instrukcija : 1. operacija se izvrsava paralelno nad sva 4 broja sadrzana u datom registru, sufiks PS 2. operacija se izvrsava samo nad realnim brojem sadrzanim u 32 bita najmanje tezine datog registra sufiks SS

MXCSR sadrzi 6 flegova koji se postavljaju prilikm pojave odgovarajucih gresaka tokom izracunavanja i to: pogresna operacija, prisustvo denormalizovanog operanda, deljenje nulom, prekoracenje, potkoracenje i neprecizno izracunavanje. Kao i za MMX pre koriscenja SSE operacija treba proveriti da li ih procesor podrzava, koristi se CPUID instrukcija. To izgleda ovako:
mov eax, 1 cpuid test edx,0x2000000 jz done

Cuvanje sadrzaja SSE registara (i registara koprocesora) i njegovo vracanje:


mov edx, esp and esp, 0xfffffff0 sub esp,512 fxsave [esp] - - - - fxrstor [esp] mov esp, edx

- 22 -

SSE instrukcije(2)
Instrukcije za transfer podataka Mnemonik Operacija prebacivanje 4 uravnata podatka (32bitna realna broja) .Prebacuju izmedju dva sse registra MOVAPS ili registra i memorije(isto i MOVUPS) Ukoliko je jedan operand memorijska adresa, ta adresa mora biti deljiva sa 16 ili ce biti generisana greska. prebacivanje 4 neuravnata podatka MOVUPS prebacivanje jednog podatka MOVSS prebacivanje 2 podatka izmedju memorije i nizeg dela registra MOVLPS prebacivanje 2 podatka izmedju memorije i viseg dela registra MOVHPS MOVLHPS prebacivanje 2 podatka iz nizeg u visi deo registra MOVHLPS prebacivanje 2 podatka iz viseg u nizi deo registra MOVMSKPS upisivanje bitova znaka sva 4 podatka u registrar opste namene snimanje statusno-kontrolnog registra u memoriju STMXCSR LDMXCSR ucitavanje statusno-kontrolnog registra u memoriju snimanje svih registara numerickog procesora i sse registara u memoriju FXSAVE ucitavanje svih registara numerickog procesora i sse registara FXRSTOR

Aritmeticko-logicke instrukcije Za sve ove instrukcije operandi su dva SSE registra ili jedan registar i memorijska lokacija. Sve postoje i u varijanti sa PS sufiksom. Logicke instrukcije rade samo nad sva 4 podatka istovremeno i to tako sto se odgovarajuca logicka operacija pojedinacno primenjuje nad svakim od ukupno 128 bitskih parova. Memorijska adresa ako se koristi mora biti deljiva sa 16, ili da se prvo prebaci u registar pomocu MOVUPS pa se potom izvrsava odgovarajuca operacija! Operacija Mnemonik sabiranje ADDPS/ADDSS oduzimanje SUBPS/SUBSS mnozenje MULPS/MULSS deljenje DIVPS/DIVSS izracunavnje reciprocne vrednosti operanada RCPPS/RCPSS izracunavanje kvadratnog korena operanada SQRTPS/SQRTSS RSQRTPS/RSQRTSS izracunavanje reciprocne vrednosti i kvardatnog korena operanada izracunavanje veceg od operanada MAXPS/MAXSS izracunavanje manjeg od operanada MINPS/MINSS bitska konjunkcija operanada ANDPS negacija bitske konjunkcije operanada ANDNPS bitska disjunkcija operanada ORPS XOR operacija nad operandima XORPS - 23 -

SSE instrukcije(3)
Instrukcije poredjenja Mnemonik Operacija CMPPS istovremeno poredjenje 4 para podataka CMPSS poredjenje jednog para podataka COMISS poredjenje jednog para podataka i postavljanje flegova EFLAGS registra UCOMISS isto kao i prethodno uz neuredjeno poredjenje Instrukcije CMPPS/CMPSS imaju tri operanda: 1. SSE registar 2. SSE registar ili memorijska lokacija 3. 8-bitna vrednost koja odredjuje prema kojoj relaciji se vrsi pordjenje prva dva operanda Rezultat svakog poredjenja niz od 32 jedinice(ako je uslov zadovoljen), nule (ako nije) koji se upisuje na mesto odredisnog operanda. Treci operand: 0 jednako 1 manje 2 manje ili jednako 3 poredjenje na neuredjenost 4 nije jednako 5 nije manje 6 nije manje ili jednako 7 poredjenje na uredjenost Instrukcije COMISS i UCOMISS imaju dva operanda (dva SSE registra ili SSE registar i memorijska lokacija) i vrse poredjenje iz 32 bita najmanje tezine. Odgovara poredjenju neoznacenih celih brojeva Instrukcije konverzije podataka Mnemonik Operacija kopiranje pod 2 podatka iz svakog operanda u niza odnosno visa 64 bita odredisnog SHUFPS operanda UNPCKHPS naizmenicno kopiranje po 2 podatka iz visa 64 bita u odredisni operand UNPCKLPS naizmenicno kopiranje po 2 podatka iz niza 64 bita u odredisni operand CVTPI2PS konverzija 2 celobrojna podatka iz MMX registra ili memorije u 2 realna podatka u SSE registru CVTSI2SS konverzija jednog celobrojnog podatka iz registra opste namene ili memorije u realan podatak u SSE registru CVTPS2PI konverzija 2 realna podatka iz SSE registra ili memorije u 2 celobrojna podatka u MMX registru CVTSS2SI konverzija jednog realnog podatka iz SSE registra ili memrije u celobrojni podatak u registru opste namene SHUFPS ima tri operanda pri cemu je odredisni operand SSE registar, drugi operan opet SSE registar ili memorijska lokacija a treci operand 8-bitna vrednost. Ona selektuje 2 elementa iz svakog operanda koristeci pravilo dato u maski. 2 elementa iz prvog operanda se kopiraju na niza 2 elementa na odredisnom, a 2 iz drugog se kopiraju na visa 2 elementa u odredisnom Najcesce se koristi : Razmena vrednosti Koristi se maska 1Bh

- 24 -

SSE instrukcije(4)
Rotacija

Sirenje elementa AAh treci element

- 25 -

SSE instrukcije(5)
.global dot_product ############################################################################ ## void dot_product(float *x, float *y, int n, float *r); ## izracunava skalarni proizvod vektora x i y dimenzije n, i rezultat smesta ## na adresu r. Argumenti funkcije: ## -- float * x -- [ebp+8] -- adresa prvog vektora ## -- float * y -- [ebp+12] -- adresa drugog vektora ## -- int n -- [ebp+16] -- dimenzija vektora ## -- float * r -- [ebp+20] -- adresa na koju se smesta rezultat. ############################################################################ dot_product: enter 0, 0 push ebx push esi push edi ## Proverava se da li procesor podrzava SSE instrukcije. mov eax, 1 cpuid: test edx, 0x2000000 : jz not_supported ## Cuva se sadrzaj SSE registara i registara koprocesora. mov edx, esp: and esp, 0xfffffff0: sub esp, 512 fxsave [esp] mov ecx, [ebp+16] mov esi, [ebp+8] mov edi, [ebp+12] ## Registar xmm0 cemo koristiti za parcijalne sume. xorps xmm0, xmm0 next_four: ## Dokle god ima bar jos cetiri elemenata... cmp ecx, 4 jb next_one ## ...ucitavamo sledeca cetiri elemenata iz oba vektora, mnozimo ih ## i dodajemo na parcijalne sume. movups xmm1, [esi] movups xmm2, [edi] mulps xmm1, xmm2 addps xmm0, xmm1 ## Prelazi se na narednu iteraciju. add esi, 16 add edi, 16 sub ecx, 4 jmp next_four next_one: ## Dokle god ima jos elemenata... jecxz finish ## ...ucitavamo sledece elemente iz oba vektora, mnozimo ih i dodajemo ## na najnizu parcijalnu sumu. movss xmm1, [esi] movss xmm2, [edi] mulss xmm1, xmm2 addss xmm0, xmm1 ## Prelazi se na narednu iteraciju. add esi, 4 add edi, 4 dec ecx jmp next_one finish: ## Sabiramo 4 parcijalne sume i dobijamo konacnu sumu u najnizem ## podatku registra xmm0. movhlps xmm1, xmm0 addps xmm0, xmm1 movaps xmm1, xmm0 shufps xmm1, xmm1, 0b01010101 addss xmm0, xmm1 ## Upisujemo podatak na za to predvidjenu lokaciju u memoriji. mov edi, [ebp+20] movss [edi], xmm0 ## Vraca se prethodni sadrzaj u registre koprocesora i SSE registre. fxrstor [esp] mov esp, edx done: pop edi pop esi pop ebx leave ret not_supported: ## Ako SSE instrukcije nisu podrzane, prekidamo program exit(1) pozivom. mov eax, 1 mov ebx, 1 int 0x80

- 26 -

ARM arhitektura
ARM procesor je RISC procesor. Razvli su ga Apple i Acorn sredinom osamdesetih. Verzije arhitekture su v1-v6. Mi cemo koristiti v4 koja je 32bitna. Karakteristike:
1. 2. 3. 4. 5. 6. 7. 32-bitna arhitektura Uniforman dizna i format instrukcija Veliki broj registara opste namene (16) Uslovno izvrsavanje instrukcija Opciono azuriranje flegova instrukcije ne azuriraju nuzno flagove vec je potrebno dodati opcioni argument koji to eksplicitno zahteva. Najcesce se dodjae sufiks S Siftovanje kao opcioni deo vecine instrukcija Memorijski pristum mora biti poravnat

Kao simulator arm masine koristimo : QEMU, ciji asembler kao komentar ne koristi # vec @. Registri Postoji 16 32-bitnih registara opste namene koji se oznacavaju sa r0-r12. r13 Stack Pointer (sp skracenica). Koristi se uglavnom za memorisanje privremenih podataka r14- Link Registar(lr skracenica). Kada se pozove neki podprogram pomocu BL instrukcije lr regostar se namesta na adresu sledece instrukcije, pa da bi se vratili iz potprograma potrebno je da kopiramo link registar u pc. r15- PC registar. On se oznacava i kao pc registar i ima posebnu ulogu. Prilikom pisanja u ovaj registar vrsi se skok na upisanu adresu Load/Store instrukcije Mnemonik LDR LDRB LDRH LDRSB LDRSH STR STRB STRH Operacija ucitava jedan 32-bitni podatak ucitava jedan bajt, a ostatk popunjava nulama ucitava 16-bitni podatak, a ostatak popunjava nulama ucitava jedan bajt, ostatak se popunjava bitom znaka ucitava 16 bitni podatak, a ostatak se popunjava bitom znaka kopira 32-bitni podatak u memoriju kopira jedan bajt najmanje tezine u memoriju kopira 16bitni podatak u memoriju

Svi memorijski transferi se obavljaju pomocu instrukcija iz ove grupe! Ostale instrukcije priamju kao operande samo registre! Siftovanje Sifter Znacenje LSL sifotovanje u levo, ekvivalent mnozenju sa 2 LSR logicko siftovanje u desno, ekvivalent deljenju sa 2 ASR aritmeticko siftovanje u desno ROR rotacija u desno RRX rotacija kroz C flag za jednu poziciju Razliciti tipovi adresiranja : 1. Offset adresiranje : bazni registar + offset koji moze biti +/- 12 bitna konstanta ili drugi registar, koji opciono moze biti siftovan
ldr r0, [r1,#4] @ ucitava rec sa adrese r1+4 i smesta u r0 ldr r0, [r1,r2] @ ucitava vrednost sa asrese r1+r2 str r0, [r1,-r2,lsl #2] @ cuva vrednost r0 na adresu r1-4*r2

ldr r0, [r1, #0] pisemo i kao ldr r0,[r1]

- 27 -

2. Pre-indexed: isto kao i offset samo sto se bazni registar azurira na izracunatu adresu
ldr r0, [r1, #8]!

ucitava rec sa adrese r1+8, a zatim registar r1 postavlja na r1+8

3. Post-indexed: isto kao i offset samo sto se bazni registar azurira nakon sto se njegova originalna vrednost upotrebi kao adresa
str r0, [r1], #4

cuva r0 na adresu r1 a zatim r1 uvecava za 4

Instrukcija kao LEA ne postoji. Medjutim postoji pseudo asemblerska instrukcija ADR koja vrsi slicnu stvar. ADR adr <registar>, <labela> smesta podatak koji se nalazi na labeli u registar dat prvim operandom

Primer: hello.s
.text fmt: .asciz "Hello world\n" .align 2 .global main main: @ Prolog funkcije stmfd sp!, {fp,lr} mov fp, sp adr r0, fmt @ ucitava se vrednost sa fmt u r0 bl printf @ poziva se funkcija printf mov r0, #0 @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc}

C konvencije o pozivanju funkcija Argumenti se prenose preko registara r0,r1,r2,r3 s leva u desno. Ako funkcija ima vise od 4 argumenata, tada se preostali argumenti prenose preko steka, pri cemu se na njega stavljaju u obrnutom redosledu. Potrebno je sacuvati sadrzaje r4-410 registara! Vrednost funkcija se po kenvenciji smesta u r0 registar! Instrukcije transfera medju registrima i instrukcije poredjenja Mnemonik MOV Operacija premestanje iz registra u registar. Prvi operan je registar a drugi shifter operand. Mogu imati sufiks S Shifter operand moze biti :
32bit konstanta registar registar siftovan za odredjeni broj pozicija rigeistar siftovan za broj pozicija koje su date u drugom registru

mov r0, r0,lsl #2

MVN CMP CMN TST TEQ

premestanje uz prethodno komplementiranje bitova uporedjivanje oduzimanjem i azuriranje flagova uporedjivanje sabiranjem i azuriranjem flagova testiranje bitovskom konjunkcijom testiranje ekskluzivnom disjunkcijom - 28 -

Aritmeticke instrukcije Mnemonik ADD ADC SUB SBC RSB RSC AND EOR ORR MUL MLA UMULL SMULL UMLAL Operacija sabiranje dva operanda sabiranje sa prethodnim prenosom oduzimanje dva operanda oduzimanje sa pozajmicom obrnuto oduzimanje obrnuto oduzimanje sa pozajmicom bitovska konjunkcija bitovska ekskluzivna disjunkcija bitovska disjunkcija ima tri operanda, i svi su registri, mnozi druga dva i smesta nizih 32 bita proizvoda u prvi Ima cetiri operanda( svi su registri) i mnozi drugi i treci i sabira ih sa cetvrtim i niza 32 bita smesta u prvi cetri operanda. Prvi predstavlja odrediste nizih 32bita drugi predstavlja odrediste visih 32 bita, a treci i cetvrti su cinioci. Vrsi neoznaceno mnozenje Isto ka i UMULL samo oznaceno Ima 4 operanda. Prvi su niza 32 bita operanda koji se dodaje na proizvod, koo i odrediste nizih 32 bita rezultata. Drugi su visih 32 bita operanda koji se dodaje, kao i odrediste za visih 32 bita rezultata. Treci i cetvrti su cinioci. Neoznaceno mnozenje Isto kao i UMLAL samo oznaceno

SMLAL

Aritmeticke instrukcije imaju tri operanda: prvi je odredisni registar, druga dva su operandi koji ucestvuu u operaciji. Ukoliko instrukcije imaju sufiks S tada azuriraju flegove. Ne postoje instrukcije za celobrojno deljenje. Mozemo ih simulirati uzastopnim oduzimanjem, pod linuxom postoje fje __divsi3 i __udivsi3 kao i __modsi3 i __umodsi3.

.align 2 .global add @ int add(int x, int y); @ r0 -- int x @ r1 -- int y add: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Sabiranje: r0 = r0 + r1 add r0, r0, r1 @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc}

Upotreba funkcija za deljenje(razlika izmedju njih je sto one sa prefiksom u se odnose na neoznacene brojeve):
@ Odredjujemo x % k mov r0, r4 mov r1, r5 bl __modsi3

- 29 -

Instrukcije grananja i uslovno izvrsavanje Mnemonik B BL Operacija ima jedan operand koji je labela. Ona se prevodi u relativnu adresu u odnosu na pc registar. Bezuslovno se skace na ovu adresu Isto kao i B samo sto instrukciju koja sledi nakon BL instrukcije smesta u registar lr

Vecina instrukcija ARM arhitekture se mogu izvrsavati uslovno. Ovo se postize dodavanjem odgovarajuceg koda kao sufiksa na mnemonik instrukcije. Ako se dodje S onda ovi sufiksi idu pre S. Ti kodovi su :
Sufiks
CS EQ VS GT GE PL HI HS

Znacenje ako je postavljen carry flag jednaki su ako je doslo do prekoracenja veci veci ili jednak pozitivan veci, neoznaceno veci ili jednak, neoznaceno

Sufiks
CC NE VC LT LE MI LO LS

Znacenje ako nije postavljen carry flag nisu jednaki ako nije doslo do prekoracenja manji manji ili jednak negativan manji, neoznaceno manji ili jednak, neoznaceno

Primeri: addgt r0,r0,r1 r0 = r0+r1 ako je prehodno bilo vece mullts r1,r2,r3 mnozi ako je prehodno bilo manje i azurira flagove Uslovni skokovi se na ARM arhitekturi prava tako sto se instrukcije B i BL izvrse uslovno dodavanje uslovnih kodova. Npr: BGT skok ako je vece.
.text .align 2 .global max @ int max(int x, int y); @ r0 -- int x @ r1 -- int y max: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Uporedjujemo x i y cmp r0, r1 bgt done @ Prebacujemo y u r0 ako je vece od x. mov r0, r1 done: @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc} done: @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc} max: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Instrukcija transfera se izvrsava samo ako je uslov ispunjen. cmp r0, r1 movlt r0, r1 .text .align 2 .global max @ int max(int x, int y); @ r0 -- int x @ r1 -- int y

- 30 -

ARM arhitektura (1)


(1 nacin) @ Funkcija @ int sum(int a[], int n); @ izracunava sumu elemenata celobrojnog niza. Argumenti funkcije su: @ -- r0 -- int * a -- adresa pocetka niza @ -- r1 -- int n -- duzina niza sum: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Komentari u produzetku instrukcija priblizno opisuju njihove @ C-ovske ekvivalente. mov r3, #0 @ S = 0; loop: cmp r1, #0 @ while(n > 0) { ldrne r2, [r0], #4 @ S = S + *a++; addne r3, r3, r2 subne r1, r1, #1 @ n--; bne loop @ } mov r0, r3 @ return S; done: @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc}

(2 nacin) sum: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Postavljamo na stek vrednost registra r4 koji cemo koristiti @ u funkciji (registri r4-r10 moraju da se sacuvaju ako se @ koriste, po konvencijama). str r4, [sp, #-4]! @ Komentari u nastavku instrukcija priblizno opisuju njihove @ C-ovske ekvivalente. mov r2, #0 @ i = 0; mov r3, #0 @ S = 0; loop: cmp r2, r1 @ while(i < n) { bge end_loop ldr r4, [r0, r2, asl #2] @ S = S + a[i]; add r3, r3, r4 add r2, r2, #1 @ i = i + 1; b loop @ } end_loop: mov r0, r3 @ return S; done: @ Vracamo vrednost registra r4 sa steka. ldr r4, [sp], #4 @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc}

- 31 -

ARM arhitektura (2)


@ int fact(int n) -- r0 -- int n

fact: stmfd sp!, {fp,lr} mov fp, sp


@ Smestamo na stek registar r4, jer cemo ga koristiti.

stmfd sp!, {r4}


@ Cuvamo n u r4.

mov r4, r0 @ Izlaz iz rekurzije: fact(0)=1 cmp r0, #0 bne rec_call mov r0, #1 b done rec_call:
@ Pozivamo fact(n-1)

sub r0, r0, #1 bl fact


@ Mnozimo n * fact(n-1)

mov r2, r0 mul r0, r2, r4 done:


@ Skidamo sa steka vrednost registra r4.

ldmfd sp!, {r4} mov sp, fp ldmfd sp!, {fp,pc}


@ @ @ @ @ void minimax(int a[], int n, int * min, int * max); odredjuje najveci i najmanji element niza celih brojeva. Argumenti -- r0 -- int * a -- adresa pocetka niza -- r1 -- int n -- duzina niza -- r2 -- int * min -- adresa na koju se smesta minimum -- r3 -- int * max -- adresa na koju se smesta maksimum.

minimax: stmfd sp!, {fp, lr} mov fp, sp


@ Smestamo na stek registre koje cemo koristiti.

stmfd sp!, {r4-r6}


@ Registar r5 ce cuvati maksimum, a r4 minimum. Inicijalno su oba jednaka prvom elementu niza.

ldr r5, [r0], #4 mov r4, r5 sub r1, r1, #1 loop:


@ Dokle god je n > 0

cmp r1, #0 beq end_loop


@ Ucitavamo u r6 tekuci element niza, i pomeramo pokazivac a u desno.

ldr r6, [r0], #4


@ Uporedjujemo ucitani element sa maksimumom.

cmp r6, r5
@ Ako je vece, onda je to novi maksimum.

movgt r5, r6
@ Uporedjujemo ucitani element sa minimumom.

cmp r6, r4
@ Ako je manje, onda je to novi minimum.

movlt r4, r6
@ Umanjujemo n i prelazimo na sledecu iteraciju.

sub r1, r1, #1 b loop end_loop:


@ Cuvamo podatke na za to predvidjene lokacije.

str r4, [r2] str r5, [r3]


@ Vracamo vrednosti registara koje smo koristili.

ldmfd sp!, {r4-r6} done: mov sp, fp ldmfd sp!, {fp, pc}

- 32 -

ARM arhitektura (3)


@ int arm_strlen(char * s); @ izracunava duzinu stringa s. Argument funkcije je: @ r0 -- char * s -- adresa pocetka stringa arm_strlen: stmfd sp!, {fp, lr} mov fp, sp @ Registar r1 ce nam biti pokazivac na tekuci karakter u @ stringu. Registar r0 ce biti brojac karaktera u stringu. mov r1, r0 mov r0, #0 next_char: @ Ucitavamo neoznaceni bajt sa adrese r1 i pomeramo pokazivac u desno. ldrb r2, [r1], #1 @ Ako je dati karakter jednak nuli, izlazimo iz petlje, a u @ suprotnom uvecavamo brojac. cmp r2, #0 beq done add r0, r0, #1 b next_char @ Na kraju je u registru r0 duzina stringa, sto je upravo @ povratna vrednost funkcije. done: mov sp, fp ldmfd sp!, {fp, pc}

- 33 -

ARM arhitektura (4)


@ void longest(char * str, int * start, int * length); @ pronalazi najduzu sekvencu istih karaktera u stringu. Argumenti funkcije su: @ -- r0 -- char * str -- adresa pocetka stringa @ -- r1 -- int * start -- lokacija na koju treba upisati indeks pocetka sekvence. @ -- r2 -- int * length -- lokacija na koju treba upisati duzinu sekvence. longest: stmfd sp!, {fp, lr} mov fp, sp stmfd sp!, {r4-r8} mov r4, #0 @ Registar r4 cuva pocetni indeks do sada najduze sekvence mov r5, #0 @ Registar r5 cuva duzinu do sada najduze sekvence. @ Ucitavamo prvi karakter i proveravamo da li je nula. ldrb r3, [r0], #1 cmp r3, #0 beq store mov r6, #0 @ Registar r6 cuva indeks pocetka tekuce sekvence. mov r7, #1 @ Registar r7 cuva tekucu duzinu sekvence. mov r8, r3 @ Registar r8 cuva prethodni karakter. next_char: @ Ucitavamo sledeci karakter i proveravamo da li je nula. ldrb r3, [r0], #1 cmp r3, #0 beq last_char @ Uporedjujemo tekuci karakter sa prethodnim. cmp r8, r3 beq equal @ Ako su razliciti, to je kraj tekuce sekvence. U tom slucaju @ poredimo duzinu tekuce sekvence sa do sada najduzom. cmp r7, r5 ble skip @ Ako je tekuca sekvenca duza, tada se azuriraju informacije @ o najduzoj sekvenci. mov r4, r6 mov r5, r7 skip: @ Inicijalizujemo sledecu sekvencu. add r6, r6, r7 mov r7, #1 b continue equal: @ Ako su tekuci i prethodni karakter jednaki, uvecavamo duzinu @ tekuce sekvence. add r7, r7, #1 continue: @ Tekuci postaje prethodni i prelazimo na sledeci karakter. mov r8, r3 b next_char last_char: @ Proveravamo da li je mozda poslednja sekvenca najduza. cmp r7, r5 ble store mov r4, r6 mov r5, r7 store: @ Cuvamo vrednosti u za to predvidjene lokacije. str r4, [r1] str r5, [r2] ldmfd sp!, {r4-r8} done: mov sp, fp ldmfd sp!, {fp, pc}

- 34 -

ARM arhitektura (5)


@ Funkcija: @ @ int twobits(unsigned x); @ @ izracunava broj pojavljivanja dve uzastopne jedinice u binarnom zapisu @ broja x. Argument funkcije je: @ @ -- r0 -- unsigned x -- dati broj @ twobits: @ Prolog funkcije stmfd sp!, {fp, lr} mov fp, sp @ Ideja algoritma: ako je binarni zapis datog broja dat kao @ x[31],x[30]...x[1],x[0], gde je x[i] bit na poziciji i u broju, @ tada se pomeranjem u desno za jednu poziciju dobija vrednost @ 0,x[31],x[30]...x[1]. Ako sada izvrsimo bitovsku konjukciju @ dobijene i originalne vrednosti, dobijamo vrednost: @ 0,(x[30]&x[31]),(x[29]&x[30]),...,(x[0]&x[1]). Broj jedinica @ u ovom binarnom zapisu je upravo jednak broju uzastopnih @ parova jedinica u originalnom broju. @ Kopiramo r0 u r3 mov r3, r0 @ Pomeramo r3 za jednu poziciju u desno (logicki) mov r3, r3, lsr #1 @ Vrsimo logicku konjukciju r0 i r3. and r0, r0, r3 @ Registar r1 ce biti brojac jedinica. Inicijalizujemo ga nulom. mov r1, #0 @ U registar r2 smestamo masku cija je vrednost inicijalno @ 1000...0000 mov r2, #1 mov r2, r2, lsl #31 next_bit: @ Dok maska ne postane nula cmp r2, #0 beq last_bit @ Testiramo bit tst r0, r2 @ Ako je jedan, uvecavamo brojac jedinica. addne r1, r1, #1 @ Pomeramo masku za jednu poziciju u desno. mov r2, r2, lsr #1 b next_bit last_bit: @ Smestamo rezultat u r0 mov r0, r1 @ Epilog funkcije mov sp, fp ldmfd sp!, {fp, pc}

- 35 -

You might also like