vezba 8 - uslovne strukture

20
1 8. USLOVNE STRUKTURE Uslovna struktura se definiše kao jedan ili više uslovnih izraza koji zahtevaju izbor između različitih logičkih grananja. Svakim grananjem se izvršava različita sekvenca instrukcija. 8.1 Blokovski IF iskazi IF struktura podrazumeva da je logički izraz praćen sa dva skupa iskaza: jedan koji se izvršava kada je izraz tačan, a drugi kada je netačan: if (logički-izraz) skup-iskaza-1 else skup-iskaza-2 Else deo iskaza je opcioni. U asembleru, ova struktura se kodira po koracima. Najpre, evaluira se logički izraz tako da se jedan od procesorskih flegova menja. Potom, kreira se serija skokova koji prosleđuju kontrolu ka dva skupa iskaza, na osnovu vrednosti relevantnih flegova. Primer 1 U sledećem C++ kodu, dva iskaza dodele se izvršavaju ako je op1 jednako sa op2: if( op1 == op2 ) then { X = 1; Y = 2; } Ovaj IF iskaz se translira u asemblerski jezik pomoću CMP instrukcije posle koje slede uslovni skokovi. Pošto su op1 i op2 memorijski operandi (promenljive), jedna od njih mora biti premeštena u registar pre izvršavanja CMP instrukcije. Sledeći kod najefikasnije implementira IF iskaz tako što omogućava kodu da propagira ka dve MOV instrukcije koje želimo da izvršimo kada je logički iskaz tačan: mov eax,op1

Upload: acikamvulovic

Post on 27-Sep-2015

29 views

Category:

Documents


0 download

DESCRIPTION

Vezba 8 - Uslovne Strukture

TRANSCRIPT

  • 1

    8.

    USLOVNE STRUKTURE

    Uslovna struktura se definie kao jedan ili vie uslovnih izraza koji zahtevaju izbor

    izmeu razliitih logikih grananja. Svakim grananjem se izvrava razliita sekvenca

    instrukcija.

    8.1 Blokovski IF iskazi

    IF struktura podrazumeva da je logiki izraz praen sa dva skupa iskaza: jedan koji se

    izvrava kada je izraz taan, a drugi kada je netaan:

    if (logiki-izraz)

    skup-iskaza-1

    else

    skup-iskaza-2

    Else deo iskaza je opcioni. U asembleru, ova struktura se kodira po koracima. Najpre,

    evaluira se logiki izraz tako da se jedan od procesorskih flegova menja. Potom, kreira se serija

    skokova koji prosleuju kontrolu ka dva skupa iskaza, na osnovu vrednosti relevantnih flegova.

    Primer 1

    U sledeem C++ kodu, dva iskaza dodele se izvravaju ako je op1 jednako sa op2:

    if( op1 == op2 ) then

    {

    X = 1;

    Y = 2;

    }

    Ovaj IF iskaz se translira u asemblerski jezik pomou CMP instrukcije posle koje slede

    uslovni skokovi. Poto su op1 i op2 memorijski operandi (promenljive), jedna od njih mora biti

    premetena u registar pre izvravanja CMP instrukcije. Sledei kod najefikasnije implementira

    IF iskaz tako to omoguava kodu da propagira ka dve MOV instrukcije koje elimo da

    izvrimo kada je logiki iskaz taan:

    mov eax,op1

  • 2

    cmp eax,op2 ; op1 == op2?

    jne L1 ; ne: preskoi sledee naredbe

    mov X,1 ; da: dodeli X i Y

    mov Y,2

    L1:

    Ako implementiramo operator == koristei JE instrukciju, rezultujui kod e biti manje

    kompaktan (est instrukcija umesto pet):

    cmp eax,op2 ; op1 == op2?

    je L1 ; da: skoi na L1

    jmp L2 ; ne: preskoi dodele

    L1: mov X,1 ; dodeli X i Y

    mov Y,2

    L2:

    Primer 2

    U FAT32 fajl sistemu, veliina klastera na disku zavisi od celokupnog kapaciteta diska.

    U sledeem pseudokodu, podeavamo veliinu klastera na 4.096 ako je veliina diska (u

    promenljivoj gigabytes) manja od 8 GB. U suprotnom, podeavamo veliinu klastera na 8.192:

    clusterSize = 8192;

    if gigabytes < 8

    clusterSize = 4096;

    Sledi nain kako se moe implementirati isti iskazi u asembleru:

    mov clusterSize,8192 ; pretpostavka veeg klastera

    cmp gigabytes,8 ; da li je vei od 8 GB?

    jae next

    mov clusterSize,4096 ; uzmi manji klaster

    next:

    Primer 3

    Sledei pseudokod ima dva grananja:

    if op1 > op2 then

    call Routine1

    else

    call Routine2

    end if

    U sledeem asemblerskom prevodu pseudokoda, pretpostavljamo da su op1 i op2

    oznaene promenljive veliine dvostruke rei. Kada se porede promenljive, jedna se mora

    premestiti u registar:

    mov eax,op1 ; prebaci op1 u registar

    cmp eax,op2 ; op1 > op2?

    jg A1 ; da: call Routine1

    call Routine2 ; ne: call Routine2

    jmp A2 ; izlaz iz IF iskaza

    A1: call Routine1

    A2:

  • 3

    8.1.1 White box testiranje

    Sloeni uslovni iskazi mogu imati nekoliko putanja izvravanja, to ih ini teke za

    debagovanje po principu inspekcije (pregleda koda). Programeri esto implementiraju tehniku

    poznatu kao white box testiranje, koja verifikuje ulaze i odgovarajue izlaze subrutina. White

    box testiranje zahteva da imate kopiju izvornog koda. Dodeljujete veliki skup vrednosti ulaznim

    promenljivama. Za svaku kombinaciju ulaza, runo prolazite kroz izvorni kod i verifikujete

    putanje izvravanja i izlaze koje daje subrutina. Da vidimo kako se to radi u asembleru tako to

    emo implementirati sledei ugnjedeni IF iskaz:

    if op1 == op2 then

    if X > Y then

    call Routine1

    else

    call Routine2

    end if

    else

    call Routine3

    end if

    Sledi mogui nain transliranja u asemblerski jezik, sa dodatim brojevima linija. Kod

    obre poetni uslov (op1 == op2) i odmah skae na ELSE deo. Sve to je ostalo jeste da se

    translira unutranji IF-ELSE iskaz:

    1: mov eax,op1

    2: cmp eax,op2 ; op1 == op2?

    3: jne L2 ; ne: call Routine3

    ; Obrada unutranjeg IF-ELSE iskaza.

    4: mov eax,X

    5: cmp eax,Y ; X > Y?

    6: jg L1 ; da: call Routine1

    7: call Routine2 ; ne: call Routine2

    8: jmp L3 ; izlaz

    9: L1: call Routine1 ; call Routine1

    10: jmp L3 ; izlaz

    11: L2: call Routine3

    12: L3:

    U tabeli 1 su prikazani rezultati white box testiranja ovog koda. U prve etiri kolone,

    testne vrednosti su dodeljene promenljivama op1, op2, X i Y. Rezultujue putanje izvravanja

    su verifikovane u kolonama 5 i 6.

    Tabela 1. Testiranje ugnjedenog IF iskaza

    op1 op2 X Y Sekvenca izvravanja linija koda Pozivi

    10 20 30 40 1, 2, 3, 11, 12 Routine3

    10 20 40 30 1, 2, 3, 11, 12 Routine3

    10 10 30 40 1, 2, 3, 4, 5, 6, 7, 8, 12 Routine2

    10 10 40 30 1, 2, 3, 4, 5, 6, 9, 10, 12 Routine1

  • 4

    8.2 Sloeni izrazi

    8.2.1 Logiki AND operator

    Asemblerski jezik lako implementira sloene logike izraze koji sadre AND operator.

    Posmatrajmo sledei pseudokod, u kojem se pretpostavlja da su vrednosti koje se porede

    neoznaeni celi brojevi:

    if (al > bl) AND (bl > cl) then

    X = 1

    end if

    8.2.2 Evaluacija po principu kratkog spoja

    Sledi implementacija po principu evaluacije kratkog spoja, u kojoj se drugi izraz ne

    evaluira ako je prvi iskaz netaan. To je standardno za jezike visokog nivoa:

    cmp al,bl ; prvi izraz...

    ja L1

    jmp next

    L1: cmp bl,cl ; drugi izraz...

    ja L2

    jmp next

    L2: mov X,1 ; oba tana: podesi X na 1

    next:

    Kod se moe smanjiti na pet instrukcija tako to se poetna JA instrukcija zameni sa JBE:

    cmp al,bl ; prvi izraz...

    jbe next ; izai ako je netaan

    cmp bl,cl ; drugi izraz

    jbe next ; izai ako je netaan

    mov X,1 ; oba su tana

    next:

    Redukcija veliine koda od 29% (sa 7 na 5 instrukcija) se deava jer se procesoru

    dozvoljava da propagira kroz kod do druge CMP instrukcije ako prvi JBE skok nije izvren.

    8.2.3 Logiki OR operator

    Kada sloeni izraz sadri podizraz sastavljen sa OR operatorom, celokupan izraz je taan

    ako je bilo koji od podizraza taan. Koristiemo sledei pseudokod kao primer:

    if (al > bl) OR (bl > cl) then

    X = 1

    U sledeoj implementaciji, kod skae na L1 ako je prvi izraz taan. U suprotnom,

    propagira do druge CMP instrukcije. Drugi izraz obre operator > i koristi JBE umesto toga:

    cmp al,bl ; 1: poreenje AL sa BL

    ja L1 ; ako je tano, preskoi sledei iskaz

    cmp bl,cl ; 2: poreenje BL sa CL

    jbe next ; netano: preskoi sledei iskaz

    L1: mov X,1 ; tano: setuj X = 1

  • 5

    next:

    Za sledei sloeni izraz, postoji nekoliko naina implementacije u asembleru.

    8.3 WHILE petlje

    WHILE petlja testira uslov pre izvravanja skupa iskaza. Sve dok je uslov petlje taan,

    iskazi se ponavljaju. Sledea petlja je napisana u C++-u:

    while( val1 < val2 )

    {

    val1++;

    val2--;

    }

    Kada se ova struktura implementira u asemblerskom jeziku, pogodno je obrnuti uslov u

    petlji i skoiti na endwhile ako uslov postane taan. Pod pretpostavkom da su val1 i val2

    promenljive, moramo kopirati jednu od njih u registar na poetku, a restaurirati vrednost

    promenljive na kraju:

    mov eax,val1 ; kopiraj promenljivu u EAX

    beginwhile:

    cmp eax,val2 ; if not (val1 < val2)

    jnl endwhile ; izai iz petlje

    inc eax ; val1++;

    dec val2 ; val2--;

    jmp beginwhile ; ponovi petlju

    endwhile:

    mov val1,eax ; sauvaj novu vrednost za val1

    EAX je posrednik (zamena) za val1 unutar petlje. Reference na val1 moraju biti kroz

    EAX. Koristi se JNL, to oznaava da su val1 i val2 oznaeni celi brojevi.

    Primer: IF iskaz ugnjeden u petlji

    Jezici visokog nivoa su posebno dobri za prikaz ugnjedenih kontrolnih struktura. U

    sledeem C++ kodu, IF iskaz je ugnjeden unutar WHILE petlje. Rauna se suma svih

    elemenata niza veih od vrednosti u sample:

    int array[] = {10,60,20,33,72,89,45,65,72,18};

    int sample = 50;

    int ArraySize = sizeof array / sizeof sample;

    int index = 0;

    int sum = 0;

    while( index < ArraySize )

    {

    if( array[index] > sample )

    {

    sum += array[index];

    }

    index++;

  • 6

    }

    Pre kodiranja ove petlje u asembleru, koristiemo algoritam prikazan na slici 1 da bismo

    opisali logiku. Da bismo pojednostavili translaciju i ubrzali izvravanje smanjenjem broja

    pristupa memoriji, registri zamenjuju promenljive. EDX = sample, EAX = sum, ESI = index i

    ECX = ArraySize (konstanta). Dodata su i imena labela.

    Slika 1. Petlja koja sadri IF iskaz

    Asemblerski kod

    Najlaki nain za generisanje asemblerskog koda iz algoritma je implementacija

    posebnog koda za svaki element u algoritmu. Primetite direktnu povezanost izmeu labela u

    algoritmu i labela koje se koriste u sledeem kodu:

    .data

    sum DWORD 0

    sample DWORD 50

    array DWORD 10,60,20,33,72,89,45,65,72,18

    ArraySize = ($ - Array) / TYPE array

    .code

    main PROC

    mov eax,0 ; sum

  • 7

    mov edx,sample

    mov esi,0 ; index

    mov ecx,ArraySize

    L1: cmp esi,ecx ; if esi < ecx

    jl L2

    jmp L5

    L2: cmp array[esi*4], edx ; if array[esi] > edx

    jg L3

    jmp L4

    L3: add eax,array[esi*4]

    L4: inc esi

    jmp L1

    L5: mov sum,eax

    8.3.1 Selekcija na osnovu tabele

    Selekcija na osnovu tabele je nain kako se moe koristiti tabela za pretragu koja

    zamenjuje strukturu viestrukih selekcija. Da bi se koristila, mora se kreirati tabela koja sadri

    vrednosti koje se trae i ofsete labela ili procedura, a potom se mora koristiti petlja za

    pretraivanje tabele. Ovo najbolje radi kada se vri veliki broj poreenja.

    Na primer, sledi deo tabele koja sadri vrednosti od jednog karaktera i adrese procedura:

    .data

    CaseTable BYTE 'A' ; vrednost koja se trai

    DWORD Process_A ; adresa procedure

    BYTE 'B'

    DWORD Process_B

    (itd.)

    Pretpostavimo da se Process_A, Process_B, Process_C i Process_D nalaze na adresama

    120h, 130h, 140h i 150h, respektivno. Tabela bi bila smetena u memoriji kao na slici 2.

    Slika 2. Tabela ofseta procedura

    Programski kod

    U sledeem programu, korisnik unosi karakter sa tastature. Koristei petlju, karakter se

    poredi sa svakim ulazom u tabeli. Prvo podudaranje prouzrokuje poziv ofseta procedure koja

    je smetena neposredno nakon vrednosti. Svaka procedura u EDX uitava ofset razliitog

    stringa, koji se prikazuje tokom petlje:

    TITLE Tabela ofseta procedura (ProcTble.asm) ; Ovaj program sadri tabelu sa ofsetima procedura. ; Koristi tabelu za izvravanje indirektnih poziva procedura.

  • 8

    INCLUDE Irvine32.inc .data CaseTable BYTE 'A' ; vrednost koja se trai DWORD Process_A ; adresa procedure EntrySize = ($ - CaseTable) BYTE 'B' DWORD Process_B BYTE 'C' DWORD Process_C BYTE 'D' DWORD Process_D NumberOfEntries = ($ - CaseTable) / EntrySize prompt BYTE "Press capital A,B,C,or D: ",0 ; Definisanje posebne poruke za svaku proceduru. msgA BYTE "Process_A",0 msgB BYTE "Process_B",0 msgC BYTE "Process_C",0 msgD BYTE "Process_D",0 .code main PROC mov edx,OFFSET prompt ; pitaj korisnika da unese karakter call WriteString call ReadChar ; uitaj karakter u AL mov ebx,OFFSET CaseTable ; ukai EBX na tabelu mov ecx,NumberOfEntries ; broja petlje L1: cmp al,[ebx] ; pronaeno podudaranje? jne L2 ; ne: nastavi call NEAR PTR [ebx + 1] ; da: pozovi proceduru ; Ova instrukcija CALL poziva proceduru ija je adresa smetena na memorijskoj lokaciji na koju ukazuje EBX + 1. Indirektan poziv poput ovog zahteva NEAR PTR operator. call WriteString ; prikaz poruke call Crlf jmp L3 ; izai iz pretrage L2: add ebx,EntrySize ; ukai na sledei ulaz loop L1 ; ponovi dok ne bude ECX = 0 L3: exit main ENDP ; Svaka od sledeih procedura premeta razliit ofset stringa u EDX. Process_A PROC mov edx,OFFSET msgA ret Process_A ENDP Process_B PROC mov edx,OFFSET msgB ret Process_B ENDP Process_C PROC mov edx,OFFSET msgC ret Process_C ENDP

  • 9

    Process_D PROC mov edx,OFFSET msgD ret Process_D ENDP END main

    Ovaj metod ima odreene reperkusije, ali moe da smanji veliinu koda. Tabela moe da

    radi sa velikim brojem poreenja, a moe se i lake modifikovati neko dugaka serija poreenja,

    skokova i CALL instrukcija. Tabela se ak moe rekonfigurisati i u vreme izvravanja.

    8.4 Konani automati

    Konani automat (finite-state machine, FSM) je maina ili program koji menja stanje na

    osnovu nekog ulaza. FSM se jednostavno predstavlja preko grafa koji sadri kvadrate (ili

    krugove) koji se nazivaju vorovi, i linija sa strelicama izmeu krugova, koje se nazivaju ivice

    (ili lukovi).

    Jednostavan primer je prikazan na slici 3. Svaki vor predstavlja stanje programa, a svaka

    ivica predstavlja prelaz iz jednog stanja u drugo. Jedan vor je oznaen kao poetno stanje, to

    je na dijagramu prikazano sa dolazeom strelicom. Ostala stanja se mogu oznaiti sa brojevima

    ili slovima. Jedno ili vie stanja se oznaava kao krajnje stanje, prikazano sa debelom ivicom

    oko kvadrata. Krajnje stanje predstavlja stanje u kojem se program moe zaustaviti, a da se ne

    prijavi greka. FSM je specifina instanca generalnijeg tipa struktura koje se nazivaju direktni

    grafovi.

    Slika 3. Jednostavan konani automat

    8.4.1 Validacija ulaznog stringa

    Programi koji itaju ulazne tokove podataka esto moraju da proveravaju ulaze tako to

    obavljaju odreene provere na greke. Na primer, kompajler programskog jezika moe da

    koristi FSM da bi proverio izvorne programe i konvertovao rei i simbole u tokene, koji su

    obino kljune rei, aritmetiki operatori i identifikatori.

    Kada se koristi FSM za proveru validnosti ulaznog stringa, obino se ita ulaz karakter

    po karakter. Svaki karakter je predstavljen sa ivicom (prelazom) u dijagramu. FSM detektuje

    pogrenu sekvencu ulaza na jedan od dva naina:

    Sledei karakteri ne odgovara nijednom prelazu iz trenutnog stanja.

  • 10

    Kraj ulaza je dostignut, a trenutno stanje je nije krajnje stanje.

    Primer sa karakterima u stringu

    Hajde da proverimo validnost ulaznog stringa na osnovu dva pravila:

    String mora poinjati sa slovom x, a zavravati se sa slovom z.

    Izmeu prvog i poslednjeg karaktera, moe postojati nula ili vie slova unutar

    opsega {a..y}.

    FSM dijagram sa slike 4 opisuje ovu sintaksu. Svaki prelaz je identifikovan sa

    pojedinanim tipom ulaza. Na primer, prelaz iz stanja A u stanje B se jedino moe desiti ako se

    slovo x oita sa ulaza. Prelaz iz stanja B u samo sebe se deava ako je na ulazu bilo koje slovo

    alfabeta osim z. Prelaz iz stanja B u stanje C se deava samo kada se sa ulaza oita slovo z.

    Slika 5. FSM za string

    Ako je kraj ulaznog toka podataka dostignut dok je program u stanju A ili B, dolazi do

    greke, jer je samo stanje C oznaeno kao krajnje stanje. FSM bi prepoznala sledee ulazne

    stringove:

    xaabcdefgz

    xz

    xyyqqrrstuvz

    Validacija oznaenog celog broja

    FSM za parsiranje oznaenog celog broja je prikazana na slici 5. Ulaz se sastoji od

    opcionog poetnog znaka posle koga ide sekvenca cifara. Ne postoji maksimalni broj cifara koji

    se moe uneti, na osnovu ovog dijagrama.

    Slika 5. FSM za oznaene decimalne cele brojeve

  • 11

    FSM se lako transliraju u asemblerski kod. Svako stanje na dijagramu (A, B, C,) je

    predstavljeno sa labelom u programu. Sledee radnje se izvravaju na svakoj labeli:

    Pozivom ulazne procedure se oitava sledei karakter sa ulaza.

    Ako je stanje krajnje, proveri da li je korisnik pritisnuo taster Enter za kraj.

    Jedna ili vie instrukcija za poreenje proverava svaki mogui prelaz koji vodi iz

    datog stanja. Svako poreenje je praeno sa instrukcijom uslovnog skoka.

    Na primer, u stanju A, sledei kod oitava sledei ulazni karakter i proverava mogui

    prelaz u stanje B:

    StateA:

    call Getnext ; uitaj sledei karakter u AL

    cmp al,'+' ; da li poinje sa +?

    je StateB ; idi u stanje B

    cmp al,'-' ; da li poinje sa -?

    je StateB ; idi u stanje B

    call IsDigit ; ZF = 1 ako AL sadri cifru

    jz StateC ; idi u stanje C

    call DisplayErrorMsg ; nekorektan ulaz

    jmp Quit

    Labela Quit oznaava izlaznu taku programa, na kraju glavne procedure:

    Quit:

    call Crlf

    exit

    main ENDP

    Sledi i kompletan programski kod.

    TITLE Finite State Machine (Finite.asm) INCLUDE Irvine32.inc ENTER_KEY = 13 .data InvalidInputMsg BYTE "Nekorektan ulaz",13,10,0 .code main PROC call Clrscr StateA: call Getnext ; uitaj sledei karakter u AL cmp al,'+' ; da li poinje sa +? je StateB ; idi u stanje B cmp al,'-' ; da li poinje sa -? je StateB ; idi u stanje B call IsDigit ; ZF = 1 ako AL sadri cifru jz StateC ; idi u stanje C call DisplayErrorMsg ; nekorektan ulaz jmp Quit StateB: call Getnext ; uitaj sledei karakter u AL call IsDigit ; ZF = 1 ako AL sadri cifru jz StateC

  • 12

    call DisplayErrorMsg ; nekorektan ulaz jmp Quit StateC: call Getnext ; uitaj sledei karakter u AL call IsDigit ; ZF = 1 ako AL sadri cifru jz StateC cmp al,ENTER_KEY ; Da li je pritisnut Enter? je Quit ; da: izai call DisplayErrorMsg ; ne: nekorektan ulaz jmp Quit Quit: call Crlf exit main ENDP ;----------------------------------------------- Getnext PROC ; ; Uitava karakter sa standardnog ulaza. ; Prima: nita ; Vraa: AL sadri karakter ;----------------------------------------------- call ReadChar ; ulaz sa tastature call WriteChar ; ispis na ekranu ret Getnext ENDP ;----------------------------------------------- DisplayErrorMsg PROC ; ; Prikazuje poruku o greci koja pokazuje ; da ulazni tok podataka sadri nekorektan unos. ; Prima: nita. ; Vraa: nita ;----------------------------------------------- push edx mov edx,OFFSET InvalidInputMsg call WriteString pop edx ret DisplayErrorMsg ENDP END main

    Ovaj program poziva proceduru IsDigit, koja se nalazi u Irvine32 biblioteci. Ona prima

    AL registar kao ulaz, a vrednost koja vraa predstavlja podeavanje Zero flega.

    ;-----------------------------------------------------------

    IsDigit PROC

    ;

    ; Odreuje da li je karakter u AL validna decimalna cifra.

    ; Prima: AL = karakter

    ; Vraa: ZF = 1 ako AL sadri validnu decimalnu cifru; u

    suprotnom, ZF = 0.

    ;-----------------------------------------------------------

    cmp al,'0'

    jb ID1 ; ZF = 0 kada se skok izvri

    cmp al,'9'

  • 13

    ja ID1 ; ZF = 0 kada se skok izvri

    test ax,0 ; setuje ZF = 1

    ID1: ret

    IsDigit ENDP

    U sledeoj tabeli su prikazani ASCII kodovi decimalnih cifara. Poto su vrednosti

    kontinualne, treba da proverimo samo opseg izmeu poetne i krajnje vrednosti.

    Karakter 0 1 2 3 4 5 6 7 8 9

    ASCII kod (hex) 30 31 32 33 34 35 36 37 38 39

    U proceduri IsDigit, prve dve instrukcije porede karakter u AL registru sa ASCII kodom

    za cifru 0. Ako je numeriki ASCII kod karaktera manji od ASCII koda za 0, program skae na

    labelu ID1:

    cmp al,'0'

    jb ID1 ; ZF = 0 kada doe do skoka

    Ali neko moe upitati, ako JB prosleuje kontrolu labeli ID1, kako znamo stanje Zero

    flega? Odgovor je u nainu na koji CMP radi: obavlja se implicitno oduzimanje ASCII koda za

    nulu (30h) od karaktera u AL registru. Ako je vrednost u AL manja, Carry fleg je setovan, a

    Zero fleg je obrisan. Instrukcija JB je dizajnirana da prosleuje kontrolu labeli kada je CF = 1

    i ZF = 0.

    Potom, kod u proceduri poredi AL sa ASCII kodom za cifru 9. Ako je vrednost vea, kod

    skae na istu labelu:

    cmp al,'9'

    ja ID1 ; ZF = 0 kada doe do skoka

    Ako je ASCII kod za karakter u AL vei od ASCII koda cifre 9 (39h), Carry i Zero flegovi

    su obrisani. To je upravo kombinacija flegova koja dovodi da JA instrukcija prosledi kontrolu

    labeli.

    Ako nijedan skok nije izvren (ni JA ni JB), pretpostavljamo da je karakter u AL zaista

    cifra. Samim tim, ubacujemo instrukciju koja zasigurno setuje Zero fleg. Testiranje bilo koje

    vrednosti sa nulom oznaava da se vri implicitna AND operacija sa svim nulama. Rezultat

    mora biti nula:

    test ax,0 ; setuje ZF = 1

    Instrukcije JA i JB skau na labelu koja je domah posle TEST instrukcije. Ako da, ako se

    ti skokovi izvre, Zero fleg e biti obrisan.

    8.5 Direktive za uslovnu kontrolu toka

    MASM poseduje vei broj direktiva visokog nivoa za uslovnu kontrolu toka koje

    pojednostavljuju kodiranje uslovnih iskaza. Pre asembliranja koda, asembler vri

  • 14

    pretprocesiranje. U ovom koraku, on prepoznaje direktive kao to su .CODE, .DATA, kao i

    direktive koje se mogu koristiti za uslovnu kontrolu toka. U tabeli 2 su prikazane ove direktive.

    Tabela 2. Direktive za uslovnu kontrolu toka

    Direktiva Opis

    .BREAK Generie kod za zavretak .WHILE ili .REPEAT bloka.

    .CONTINUE Generie kod za skok na poetak .WHILE ili .REPEAT bloka.

    .ELSE Poetak bloka iskaza koji se izvravaju kada je .IF uslov netaan.

    .ELSEIF uslov Generie kod koji testira uslov i izvrava iskaze koji slede potom, sve dok se ne doe do .ENDIF ili druge .ELSEIF direktive.

    .ENDIF Zavrava blok iskaza koji poinje sa .IF, .ELSE ili .ELSEIF direktivom.

    .ENDW Zavrava blok iskaza koji poinje sa .WHILE.

    .IF uslov Generie kod koji izvrava blok iskaza ako je uslov taan.

    .REPEAT Generie kod koji ponavlja izvravanje bloka iskaza sve dok uslov ne postane taan.

    .UNTIL uslov Generie kod koji ponavlja izvravanje bloka iskaza izmeu .REPEAT i .UNTIL sve dok uslov ne postane taan.

    .UNTILCXZ Generie kod koji ponavlja izvravanje bloka iskaza izmeu .REPEAT i .UNTIL sve dok CX ne postane jednak nuli.

    .WHILE uslov Generie kod koji izvrava blok iskaza izmeu .WHILE i .ENDW sve dok je uslov taan.

    8.5.1 Kreiranje IF iskaza

    Direktive .IF, .ELSE, .ELSEIF i .ENDIF olakavaju kodiranje logike viestrukog

    grananja. One ine da asembler generie CMP i instrukcije uslovnog skoka u pozadini, koje se

    pojavljuju u izlaznom listingu. Sintaksa je:

    .IF uslov1

    iskazi

    [.ELSEIF uslov2

    iskazi ]

    [.ELSE

    iskazi ]

    .ENDIF

    Uglaste zagrade oznaavaju da su .ELSEIF i .ELSE opcioni, dok su .IF i .ENDIF

    obavezni. Uslov je logiki izraz koji ima iste operatore koji se koriste u C++ i Javi (kao to su

    , ==, !=). Izraz se evaluira u vreme izvravanja. Slede primeri validnih uslova, koji koriste

    32-bitne registre i promenljive:

    eax > 10000h

    val1 0) && (eax > 10000h)

    (val1

  • 15

    (val2 != ebx) && !CARRY?

    Kompletna lista relacionih i logikih operatora je prikazana u tabeli 3.

    Tabela 3. Relacioni i logiki operatori

    Operator Opis

    expr1 == expr2 Vraa true kada je expr1 jednako sa expr2.

    expr1 != expr2 Vraa true kada expr1 nije jednako sa expr2.

    expr1 > expr2 Vraa true kada je expr1 vee od expr2.

    expr1 >= expr2 Vraa true kada je expr1 vee ili jednako sa expr2.

    expr1 < expr2 Vraa true kada je expr1 manje od expr2.

    expr1 val1

    mov result,1

    .ENDIF

    Pretpostavlja se da su val1 i result 32-bitni neoznaeni celi brojevi. Kada asembler proita

    gornje linije koda, on ih proiruje u sledee asemblerske instrukcije, koje se mogu videti

    prilikom debagovanja u Disassembly prozoru:

    mov eax,6

    cmp eax,val1

    jbe @C0001 ; skok na osnovu neoznaenog poreenja

    mov result,1

    @C0001:

    Labela @C001 je kreirana od strane asemblera. To se radi tako da se garantuje da su sve

    labele unutar iste procedure jedinstvene.

    Poreenje oznaenih i neoznaenih vrednosti

    Kada se koristi .IF direktiva za poreenje vrednosti, mora se voditi rauna da MASM

    generie uslovne skokove. Ako se poredi neoznaena promenljiva, u generisani kod se ubacuje

  • 16

    instrukcija neoznaenog uslovnog skoka. Sledei primer je isti kao i gornji, samo sa definisanim

    promenljivama:

    .data

    val1 DWORD 5

    result DWORD ?

    .code

    mov eax,6

    .IF eax > val1

    mov result,1

    .ENDIF

    Asembler ovaj kod proiruje koristei JBE (instrukciju neoznaenog skoka):

    mov eax,6

    cmp eax,val1

    jbe @C0001 ; skok na osnovu neoznaenog poreenja

    mov result,1

    @C0001:

    Poreenje oznaenih celih brojeva

    Ako .IF direktiva poredi oznaene promenljive, u kod se ubacuju instrukcije oznaenog

    uslovnog skoka. Na primer, val2 je oznaena dvostruka re:

    .data

    val2 SDWORD -1

    result DWORD ?

    .code

    mov eax,6

    .IF eax > val2

    mov result,1

    .ENDIF

    Samim tim, asembler generie kod ubacujui instrukciju JLE:

    mov eax,6

    cmp eax,val2

    jle @C0001 ; skok na osnovu oznaenog poreenja

    mov result,1

    @C0001:

    Poreenje registara

    Prilikom poreenja vrednosti u dva registra, asembler ne moe znati da li su vrednosti u

    njima oznaene ili neoznaene:

    mov eax,6

    mov ebx,val2

    .IF eax > ebx

    mov result,1

    .ENDIF

  • 17

    Generie se sledei kod, koji pokazuje da je podrazumevana vrednost neoznaeno

    poreenje:

    mov eax,6

    mov ebx,val2

    cmp eax, ebx

    jbe @C0001

    mov result,1

    @C0001:

    8.5.2 Sloeni izrazi

    Dosta sloenih logikih izraza koristi logike OR i AND operatore. Kada se koristi .IF

    direktiva, simbol || oznaava logiki OR operator:

    .IF izraz1 || izraz2

    iskazi

    .ENDIF

    Slino, simbol && je oznaka za logiki AND operator:

    .IF izraz1 && izraz2

    iskazi

    .ENDIF

    Primer 1

    U sledeem primeru je prikazana SetCursorPosition procedura, koja proverava opseg

    vrednosti dva ulazna parametra, DH i DL. Y-koordinata (DH) mora biti izmeu 0 i 24. X-

    koordinata (DL) mora biti izmeu 0 i 79. U sluaju pogrenog opsega, prikazuje se poruka o

    greci.

    SetCursorPosition PROC

    ; Podeava poziciju kursora.

    ; Prima: DL = X-koordinata, DH = Y-koordinata.

    ; Proverava opsege DH i DL.

    ; Vraa: nita

    ;------------------------------------------------

    .data

    BadXCoordMsg BYTE "X-koordinata van opsega!",0Dh,0Ah,0

    BadYCoordMsg BYTE "Y-koordinata van opsega!",0Dh,0Ah,0

    .code

    .IF (dl < 0) || (dl > 79)

    mov edx,OFFSET BadXCoordMsg

    call WriteString

    jmp quit

    .ENDIF

    .IF (dh < 0) || (dh > 24)

    mov edx,OFFSET BadYCoordMsg

    call WriteString

    jmp quit

    .ENDIF

    call Gotoxy

  • 18

    quit:

    ret

    SetCursorPosition ENDP

    Sledi kod kojeg generie MASM:

    .code

    ; .IF (dl < 0) || (dl > 79)

    cmp dl, 000h

    jb @C0002

    cmp dl, 04Fh

    jbe @C0001

    @C0002:

    mov edx,OFFSET BadXCoordMsg

    call WriteString

    jmp quit

    ; .ENDIF

    @C0001:

    ; .IF (dh < 0) || (dh > 24)

    cmp dh, 000h

    jb @C0005

    cmp dh, 018h

    jbe @C0004

    @C0005:

    mov edx,OFFSET BadYCoordMsg

    call WriteString

    jmp quit

    ; .ENDIF

    @C0004:

    call Gotoxy

    quit:

    ret

    Primer 2

    Pretpostavimo da student eli da se registruje za kurs. Koristiemo dva kriterijuma da li

    student moe da se registruje: prvi je procena ocena, na skali od 0 do 400, gde je 400 najvea

    ocena. Drugi je broj ESPB bodova koje student eli da upie. Moe se koristiti .IF, .ELSEIF i

    .ENDIF.

    .data

    TRUE = 1

    FALSE = 0

    gradeAverage WORD 275 ; testna vrednost

    credits WORD 12 ; testna vrednost

    OkToRegister BYTE ?

    .code

    mov OkToRegister,FALSE

    .IF gradeAverage > 350

    mov OkToRegister,TRUE

    .ELSEIF (gradeAverage > 250) && (credits

  • 19

    .ENDIF

    Sledi i kod koji generie MASM.

    mov byte ptr OkToRegister,FALSE

    cmp word ptr gradeAverage,350

    jbe @C0006

    mov byte ptr OkToRegister,TRUE

    jmp @C0008

    @C0006:

    cmp word ptr gradeAverage,250

    jbe @C0009

    cmp word ptr credits,16

    ja @C0009

    mov byte ptr OkToRegister,TRUE

    jmp @C0008

    @C0009:

    cmp word ptr credits,12

    ja @C0008

    mov byte ptr OkToRegister,TRUE

    @C0008:

    8.5.3 Kreiranje petlji sa .REPEAT i .WHILE

    Direktive .REPEAT i .WHILE pruaju alternativan nain pisanja petlji, umesto CMP i

    instrukcija uslovnog skoka. Dozvoljavaju korienje uslovnih iskaza prikazanih u tabeli 3.

    Direktiva .REPEAT izvrava telo petlje pre testiranja uslova u .UNTIL direktivi:

    .REPEAT

    iskazi

    .UNTIL condition

    Direktiva .WHILE testira uslov pre izvravanja petlje:

    .WHILE uslov

    iskazi

    .ENDW

    Primeri

    Sledei iskazi prikazuju vrednosti od 1 do 10 koristei .WHILE direktivu. EAX je

    incijalizovan na nulu pre petlje. Potom, u prvom iskazu unutar petlje, EAX se inkrementira.

    Direktiva .WHILE izlazi iz petlje kada EAX bude jednako 10.

    mov eax,0

    .WHILE eax < 10

    inc eax

    call WriteDec

    call Crlf

    .ENDW

    Sledei iskazi prikazuju ispis vrednosti od 1 do 10 koristei .REPEAT direktivu:

    mov eax,0

    .REPEAT

  • 20

    inc eax

    call WriteDec

    call Crlf

    .UNTIL eax == 10

    Primer: petlja koja sadri IF iskaz

    Pseudokod za WHILE petlju koja sadri IF iskaz je:

    while( op1 < op2 )

    {

    op1++;

    if( op1 == op3 )

    X = 2;

    else

    X = 3;

    }

    Sledi implementacija ovog pseudokoda koristei .WHILE i .IF direktive. Poto su op1,

    op2 i op3 promenljive, premetaju se u registre kako bi se izbeglo posedovanje dva memorijska

    operanda u bilo kojoj instrukciji:

    .data

    X DWORD 0

    op1 DWORD 2 ; testni podatak

    op2 DWORD 4 ; testni podatak

    op3 DWORD 5 ; testni podatak

    .code

    mov eax,op1

    mov ebx,op2

    mov ecx,op3

    .WHILE eax < ebx

    inc eax

    .IF eax == ecx

    mov X,2

    .ELSE

    mov X,3

    .ENDIF

    .ENDW