RAČUNARSTVO I INFORMATIKA III

Skripta - asembler

UVOD

Sadržaj kursa

Osnovni cilj je: ovladati programiranjem na asemblerskom jeziku procesora 80x86. U okviru kursa, upoznaćemo se sa sledećim temama:

- Istorijatom, arhitekturom i osobinama ovog procesora (o tome će biti mnogo više reči na predavanjima)

- Instrukcijama i pseudoinstrukcijama asemblerskog jezika

- Makroima

- Sistemom prekida i mehanizmom obrade prekida

- Načinom asembliranja i povezivanja (linkovanja)

- Strukturom izvršnih datoteka (izvršnog koda)

- Načinima za formiranje izvršne datoteke od više izvornih datoteka

- Koprocesorom (matematičkim pocesorom), njegovom arhitektu­rom, osobinama i instrukcijama, te mehanizmom zajedničkog rada koprocesora i procesora

- Povezivanjem asemblerskog koda sa programima napisanim na nekom drugom programskom jeziku

- Načinom komunikacije procesora sa drugim uređajima u okviru računarskog sistema: disk jedinicom, grafičkom karticom (video adapterom), karakter uređajima itd.

ASEMBLERSKI JEZICI, PROCESOR, ASEMBLER

Istorijat asemblerskih jezika

- Asemblerski (simbolički) jezici su najstariji programski jezici.

- Pre nastanka asemberskih jezika, komunikacija sa računarima (tj. programiranje) se odvijala tako što su sekvence nula i jedinica bivale ručno unošene u memoriju računara na zahtevanu poziciju (adresu), a potom je program startovan.

- Veliko unapređenje mukotrpnog postupka programiranja nastupa kada se dopusti da se koriste mnemotehničke oznake koje zamenjuju odgovarajuće instrukcije računara, tj. uvođenjem operacionog koda (opkod).

- Pored uvođenja operacionog koda, uvode se i simbolička imena adresa, tj. uvodi se mogućnost da se sekvence nula i jedinica zamene simboličkim imenom. Zbog te karakteristike, za asemblerske jezike se u literaturi često koristi naziv simbolički jezici.

- Program na asemblerskom jeziku, ne može direktno da se izvršava na mašini. On sada predstavlja ulaz za neke druge programe koji ga transformišu u kod razumljiv mašini i smeštaju u memoriju.

- Vremenom je programiranje na asemblerskom jeziku obogaćeno drugim mogućnostima: raznovrsnim načinima adresiranja; mogućnošću pravljenja procedura, tj. logičkog organizovanja programa i izdvajanja celina u podprograme; radom sa makroima itd.

- Asemblerski jezik koji podržava rad sa makroima naziva se makroasembler.

 

 

Osobine asemblerskih jezika

Sledeća klasifikacija ukazuje na mesto asemblerskih i makroasemblerskih jezika među programskim jezicima:

U poređenju sa mašinski nezavisnim jezicima, asemblerski i makroasemblerski jezici imaju sledeće osobine:

- zavise od konkretnog tipa računara, čime je bitno umanjena prenosivost programa (mada jedan proizvođač obično pravi svoje programe tako da budu vertikalno kompatibilni);

- manja udobnost u programerovom radu, nego što je to slučaj sa mašinskim jezicima (mada izražajna sredstva postaju sve raznovrsnija, a i samo okruženje postaje sve udobnije);

- programi (preciznije, dobro napisani programi) na asemblerskom jeziku osetno bolje iskorištavaju resurse računara, nego programi napisani na nekom od mašinski nezavisnih jezika; tako se smatra da se dobar asemblerski program u proseku izvršava 20-30% brže od odgovarajućeg C programa (mada prevodioci postaju sve “pametniji”);

- kako programi na asemblerskom jeziku nemaju osobinu samodokumentovanosti (čitljivost im nije jača strana), neophodno je istaći ogroman značaj koji ima dokumentacija, komentarisanje koda, itd.

- u programima na asemblerskom jeziku najbitnije je maksimalno iskorišavanje računarskih resursa, pa se (ne vodeći računa o čitljivosti) mogu koristiti sve dosetke koje ubrzavaju rad algoritma, ili smanjuju veličinu zahtevanih resursa.

Zbog svih ovih karakteristika, jasno je da se programira na asemblerskom jeziku kada se pravi softver koji je u uskoj vezi sa hardverom, kao što su drajveri (veznici, pogonaši) za neke uređaje; kada se želi povećati iskorišćenost resursa; kada se želi ubrzati izvršavanje konkretnog algoritma.

Kada se govori o asemblerskom jeziku, često se može čuti maksima: “Pri programiranju na asemblerskom jeziku, ništa ne stoji između programera i računara. Međutim, ništa ne stoji ni između programera i greške”. Preciznije bi bilo da se reč “ništa” iz prve i iz druge rečenice maksime, zameni sa “skoro ništa”.

Sledeća shema prikazuje proces dobijanja izvršnog koda (izvršnog programa) na osnovu izvornih programa (asemblerskih programa):

 

                     Izvorni                            Objekt                                  Izvršni

 

              program                                kod                                     kod

 

- Prvo se preko nekog ulaznog uređaja unese izvorni program (na asemblerskom jeziku) u memoriju računara, i zapamti se u datoteku na nekom od uređaja spoljne memorije.

- Potom se pozove program koji prevodi (asemblira) izvorni program i, ukoliko tokom prevođenja nije bilo grešaka, kreira objekt program. Program koji vrši prevođenje naziva se asembler, a otud potiče i naziv za celu klasu jezika - asemblerski jezici. Asembler će oformljeni objekt program upisati u posebnu datoteku.

- Objekt program (objekt kod) još nije spreman za izvršavanje. Potrebno ga je povezati. To obavlja uslužni program nazvan povezivač (linker). Linker će, po potrebi, povezati i više modula sa objekt kodom. Tako će se, ukoliko prilikom povezivanja ne dođe do grešaka, oformiti izvršni program (izvršni kod) koji se upisuje u potrebnu datoteku, kako bi se kasnije mogao izvršavati.

Centralni predmet proučavanja u ovom kursu je asemblerski jezik procesora 80386. Tokom obrade gradiva, ukazivaće se na sličnosti i razlike između ovog procesora i njegovih prethodnika (8086, 80286). Isto tako, pri obradi procesora 80387 govoriće se i o sličnostima i razlikama između njega i njegovih prethodnika.

Brojevni sistemi

U ovom poglavlju se opisuju samo pozicioni brojni sistemi i predstavljanje celih brojeva. U tom slučaju, osnova brojevnog sistema jednoznačno identifikuje taj sistem. Cifre nekog prirodnog broja u tom brojevnom sistemu su ostaci pri deljenju tog broja sa stepenima osnove sistema. Dakle, isti broj će imati različite zapise u različitim brojevnim sistemima.

Biće ponovljene osnovne osobine i načini izvršenja operacija za sledeće brojevne sisteme: dekadni, binarni, oktalni i heksadekadni (heksadecimalni).

Osnovne aritmetičke operacije nad brojevima u nekom od prethodno pobrojanih pozicionih brojnih sistema izvode se potpuno analogno aritmetičkim operacijama nad dekadnim brojevima (dakle, onako kako smo i navikli da radimo).

Dekadni brojevi

Osnova brojnog sistema je 10. Cifre su: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

Binarni brojevi

Osnova brojnog sistema je 2. Cifre su: 0 i 1.

Pri radu sa binarnim brojevima kod procesora 80386 razlikuju se:

bit (eng. binary digit)

1

bajt (oktet, eng. byte)

8

polubajt (kvartet. eng. nibble)

4

reč (eng. word)

16

dvostruka reč (eng. double word)

32

Svaka klasa ovakvih binarnih brojeva ima svoju dužinu, i može predstavir određen opseg brojeva

Ako se posmatraju brojevi u odgovarajućem opsegu, može se govoriti o neoznačenim i označenim brojevima. Stoga, ista bitovna niska može predstavljati jedan broj ako se tumači kao neoznačen, a sasvim drugi broj ukoliko se tumači kao označen.

Postoji i više načina za predstavljanje označenih brojeva (znak i apsolutna vrednost, nepotpuni komplement, potpuni komlement). Kod procesora 80386 označeni brojevi se čuvaju u formatu potpunog komplementa (komplemet dvojke, eng. two’s complement).

Oktalni brojevi

Osnova brojnog sistema je 8. Cifre su: 0, 1, 2, 3, 4, 5, 6, 7.

Heksadekadni brojevi

Osnova brojnog sistema je 16. Cifre su: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E , F. Cifre A, B, C, D, E, F imaju numeričku vrednost 10, 11, 12, 13, 14, 15 respektivno.

Arhitektura procesora 80386

Procesor 80386 je 32-bitni procesor. To znači da maksimalna dužina niza bitova sa kojom ovaj procesor operiše u jednoj instrukciji iznosi 32. Stoga, i registri ovog procesora imaju dužinu 32. Težina bitovnih mesta je određena tako da krajnje desni bit registra predstavlja bit najmanje težine.

Procesor 80386 sadrži devet 32-bitnih registara i deset jednobitnih flegova (zastavica, eng. flag). Flegovi se nalaze u tzv. registru flegova.

31

                   16

15                 8

7                   0

 

 

 

         AH     A

X       AL                  

EAX

 

 

         BH     B

X       BL          

EBX

 

 

         CH     C

X       CL          

ECX

 

 

         DH     D

X       DL          

EDX

 

 

S

I

ESI

 

 

D

I

EDI

 

 

B

P

EBP

 

 

S

P

ESP

 

 

 

 

 

31

                   16

15

0

 

 

 

 

 

EIP

 

 

 

 

EFLAGS

Osam od ovih devet opštih registara su tzv. registri opšte namene. Za najveći broj instrukcija procesora, ovi registri mogu biti korišćeni bez obzira na vrstu instrukcije. Ali, kao što će se kasnije detaljnije videti, postoje i neke, veoma važne, instrukcije, koje su orjentisane na specifične registre. Te instrukcije koriste konkretne registre na specificiran način, i pri izvršenju tih instrukcija konkretan registar ne može biti zamenjen nijednim drugim registrom. Deveti registar, nazvan brojač naredbi (pokazivač instrukcije, eng. instruction pointer), nije direktno pristupačan programeru.

Opšti registri

Kad procesori ne bi posedovali opšte registre, svaka instrukcija bi dohvatala svoje operande iz meorije, i vraćala bi rezultat u memoriju. Ali, pristup meoriji oduzima vreme. To vreme potrebno za dohvatanje i smeštaj operanada može biti redukovano privremenim čuvanjem često korišćenih podataka i međurezultata na mestu kome se može brže pristupiti. Takvo mesto je, kod procesora 80386, skup njegovih opštih registara.

Opšti registri procesora 80386 su 32-bitni registri EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP. Slovo E na početku oznake je skraćenica od reči raširen (eng. extended), jer je svaki od ovih registara raširenje nekog 16-bitnog registra koji su postojali kod starijih procesora u ovoj familiji. Ti 16-bitni registri (nazvani AX, BX, CX, DX, SI, DI, BP i SP) su donje polovine ovih raširenih registara. Prva četiri 16-bitna registra se dalje dele na 8-bitne registre. Polovine registara manje težine označavaju se sa Al, BL, CL, DL (L od nizak - eng. low), dok se podregistri veće težine označavaju sa AH, BH, CH, DH (H od visok - eng. high).

Sposobnost procesora 80386 da adresira 8-bitovne i 16-bitovne podskupove 32-bitnih opštih registara omogućuje da ovaj procesor rukuje bajtovima, rešima i dvostrukim rečima na uniforman način.

Za najveći broj instrukcija ma koji opšti registar može učestvovati kao operand.

Primer.

Instrukcija ADD može sabrati sadržaj ma kog 8, 16, 32-bitnog opšteg registra sa sadržajem ma kog registra iste dužine i smestiti rezultat u odgovarajući registar (te dužine).

Ipak, kako je i istaknuto u prethodnom poglavlju, postoji nekoliko instrukcija koje određene, fiksirane registre, koriste za određenje svrhe.

Primer.

Instrukcije za rad sa niskama (stringovima, eng. string) zahtevaju da registar ECX sadrži broj elemenata niske. Nijedan od drugih registara se ne može koristiti u tu svrhu pri izvršavanju instrukcija za rad sa niskama.

Specijalizovana upotreba registra ECX dovodi do toga da ga u literaturi često nazivaju brojač (eng. counter). Specijalizovano korišćenje registara EAX, EBX, EDX, koje će biti kasnije objašnjeno, nameće da se za njih koriste opisna imena akumulator (eng. accomulator), baza (eng. base), podatak (eng. data) redom.

Flegovi

Procesor 80386 sadrži deset flegova koji se koriste za čuvanje informacija o statusu procesora (takvi flegovi su statusni flegovi, tj. statusne zastavice) ili za kontrolu operacija procesora (kontrolni flegovi, tj. kontrolne zastavice).

Statusni flegovi, u opštem slučaju,  po izvršenju aritmetičke ili logičke instrukcije dobijaju vrednost koja odslikava određene osobine rezultata takvih operacija.

Statusni flegovi su:

CF - fleg prenosa (eng. carry flag), koji indicira da je izvršena instrukcija generisala prenos sa mesta najveće težine;

AF - pomoćni fleg prenosa (eng. auxilary carry flag), koji ukazuje da je izvršenje instrukcije generisalo prenos sa mesta najveće težine polubajta najmanje težine, tj. prenos sa bita na poziciji ;

OF - fleg prekoračenja (eng. overflow flag), koji ukazuje da lli je instrukcija oformila rezultata u obliku označenog celog broja, koji je izašao iz okvira (opsega);

ZF - nula fleg (eng. zero flag), ukazuje na to da li je instrukcija generisala rezultat koji je nula, tj. da li se rezultat sastoji od svih nula;

SF - fleg znaka (eng. sign flag), ukazuje da je instrukcija svojim izvršavanjem generisala negativan rezultat; vrednost flega znaka poklapa se sa vrednošću bita najveće težine rezultata;

PF - fleg parnosti (eng. parity flag), indicira da je instrukcija svojim radom generisala rezultat koji ima paran broj jedinica.

Kontrolni flegovi, kao što im ime kaže, kontrolišu način izvršavanja pojedinih instrukcija. Stoga se njihova vrednost postavlja na jedan (još se kaže “fleg se postavlja”, eng. set) ili na nulu (koristi se izraz “fleg se briše”, eng. clear) pre izvršenja instrukcije. U kontrolne flegove spadaju:

DF - fleg pravca (eng. direction flag), kontroliše pravac izvršenja instrukcija za manipulaciju niskama;

IF - fleg omogućavanja prekida (eng. interrupt enable flag) omogućava ili onemogućava spoljašnje prekide;

TF - zamka fleg (eng. trap flag), prebacuje procesor u jednokoračni mod, radi dibagiranja programa;

RF - fleg nastavljanja (eng. resume flag), prekida rad ugrađenog procesorovog dibagera.

Svi ovi flegovi, kao i neki drugi koje zasad nećemo pominjati, zauzimaju bitovna mesta u raširenom registru flegova - EFLAGS.

Unutrašnja memorija

Da bi se moglo govoriti o načinu izvršenja instrukcija procesora, mora se znati na koji se način u unutrašnjoj memoriji računara čuvaju podaci, tj. nizovi bitova.

Fizička memorija računarskog sistema baziranog na procesoru 80386 je organizovana kao sekvenca bajtova. Svakom bajtu je dodeljena jedinstvena adresa u intervalu od 0 do 232-1 (dužina opsega je 4 GB).

Zapis bajta, reči i dvostruke reči

Svaki bajt u memoriji ima svoju adresu. Delovi memorije koji imaju manju adresu, tj. čija je adresa bliža nuli, nazivaće se viša memorija i smatraće se da se oni nalaze “iznad” delova memorije koji imaju veću adresu. U tom smislu, kod dva susedna bajta u memoriji, viši bajt će biti onaj koji ima manju adresu. Analogna konvencija se uspostavlja za reči i dvostruke reči.

Isto kao kod registara, u okviru svakog bajta krajnje desno nalazi bit najmanje težine, levlje su sve značajniji bitovi, da bi krajnje levo bio bit najveće težine.

Reč se čuva u memoriji (u dva susedna bajta) tako što se niži bajt reči upiše u viši bajt memorije, a viši bajt reči u niži bajt memorije.

Dvostruka reč se čuva u memoriji u četiri uzastopna bajta. Bajt najmanje težine dvostruke reči čuva se najvišem mestu u memoriji, sledeći bajt se čuva na sledećem mestu itd. Bajt najveće težine dvostruke reči čuva se na najnižem mestu u memoriji.

Dakle, pri smeštaju reči i dvostruke reči u memoriju, prvo se smesti niži bajt, a potom viši bajt itd, sve do bajta najveće težine .

Primer.

On jasno ilustruje način čuvanja bajta u memoriji. Prikazuje sadržaj memorije pre i posle izvršenja instrukcija za prenos bajta iz opšteg registra u memoriju i instrukcija za prenos i memorije u registre. Sadržaj jednog bajta zapisuje se pomoću dve heksadecimalne (heksadekadne, heksa) cifre.

Početno stanje

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

c

c

b

b

a

a

4

0

a:

7

8

 

 

 

 

 

 

 

 

 

 

 

1

2

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

MOV a, AL

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

c

c

b

b

a

a

4

0

a:

4

0

 

 

 

 

 

 

 

 

 

 

 

1

2

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

MOV AX, a

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

c

c

b

b

1

2

4

0

a:

4

0

 

 

 

 

 

 

 

 

 

 

 

1

2

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

MOV EAX, a

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

5

6

3

4

1

2

4

0

a:

4

0

 

 

 

 

 

 

 

 

 

 

 

1

2

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

MOV AX, 0F1E2H

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

5

6

3

4

F

1

E

2

a:

4

0

 

 

 

 

 

 

 

 

 

 

 

1

2

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

MOV a, EAX

 

 

 

 

 

 

 

 

 

 

 

...

 

 

eax:

5

6

3

4

F

1

E

2

a:

E

2

 

 

 

 

 

 

 

 

 

 

 

F

1

 

 

 

 

 

 

 

 

 

 

 

3

4

 

 

 

 

 

 

 

 

 

 

 

5

6

 

 

 

 

 

 

 

 

 

 

 

...

 

Modeli organizacije memorije

Asemblerski programi za prosesor 80386 se mogu kreirati tako da budu nezavisni od fizičkog adresnog prostora. Ovo znači da se programi mogu pisati bez poznavanja tačnih podataka o tome gde su u fizičkoj memoriji smeštene instrukcije i podaci.

Model organizacije memorije, onako kako ga vidi aplikativni programer, određen je od strane dizajnera sistemskog softvera. Arhitektura procesora 80386 daje dizajneru slobodu izbora modela za svaki od zadataka. Model organizacije memorije se kreće između sledeća dva ekstrema:

1.              Ravan adresni prostor, koji se sastoji od jednog niza veličine do 4 GB

2.              Segmentirani adresni prostor, koji se sastoji od skupa koji sadrži ne više od 16383 linearnih adresa veličine do 4GB.

Oba modela obezbeđuju memorijsku zaštitu. Različiti poslovi mogu koristiti različite modele memorijske organizacije.

Ravan model

U ravnom modelu organizacije memorije, aplikacioni programer vidi memoriju kao jedinstven niz maksimalne veličine 4 GB (=232 bajtova). Obično je veličina memorije mnogo manja od 4GB, pa procesor mapira (eng. map - preslikavanje) ravan prostor od 4 GB u fizički adresni prostor. Mehanizam adresnog preslikavanja, tj. adresne translacije, će biti opisan u nekom od sledećih poglavlja. Aplikativni programeri ne moraju da znaju detalje mapiranja.

Pokazivač na objekat u ovom ravnom adresnom prostoru je 32-bitni neoznačen ceo broj. On se kreće između 0 i 232-1. U ovom slučaju relokacija razdvojeno asembliranih modula mora biti izvršena od strane sistemskog softvera.

Segmentirani model

U segmentiranom modelu organizacije memorije adresni prostor, onako kako ga vidi aplikacija, je mnogo veći nego u prethodnom slučaju. Taj prostor se naziva logički adresni prostor i kod ovog modela organizacije njegova veličina može da ide i do 64TB (=246 bajtova). I u ovom modelu se pomoću mehanizma adresne translacije vrši preslikavanje logičkog u fizički adresni prostor.

Slično kao u prethodnom slučaju, aplikativni programeri ne moraju da znaju detalje mapiranja. Oni će logički adresni prostor procesora 80386 videti kao skup od maksimalno 16383 jednodimenzionalnih podprostora, nazvanih segmenti. Segment je, dakle, jedinica neprekidnog adresnog prostora. Njegova veličina može varirati od jednog bajta do četiri gigabajta.

Kompletan pokazivač na objekte u ovom adresnom prostoru se sastoji od dva dela:

1. Segmentni selektor, 16-bitno polje koje identifikuje segment.

2. Ofset (eng. offset - pomeraj, pomak) u segmentu, 32-bitni neoznačen ceo broj koji adresira bajtove u okviru segmenta.

Tokom izvršavanja programa, procesor asocira segmentni selektor sa fizičkom adresom početka segmenta. Odvojeno asemblirani moduli mogu, izmenom bazne adrese segmenta, biti relocirani u vremenu izvršavanja.

Operandi kod instrukcija procesora 80386

Instrukcije procesora 80386 se obično izvršavaju nad dva, jednim ili nijednim operandom. Sintaksa ovih instrukcija se, korišćenjem modifikovane Bekusove notacije, zapisuje na sledeći način:

[<prefiks ponavljanja>]<mnemonik><odredišni operand>[[,<pomoćni operand>],<izvorni operand>]] đ

[<prefiks ponavljanja>]<mnemonik><izvorni operand>

Procesor 80386 dopušta veliku širinu u izboru operanda koji se mogu koristiti sa instrukcijama.

Ukoliko mnemonik instrukcije prate tri operanda, tada prvi operand predstavlja odredišni operand i označava se sa D (eng. destination - odredište), drugi operand, u oznaci H (eng. help - pomoć) je pomoćni, dok je treći operand specificira izvor i označava se sa S (eng. source - izvor).

Ako mnemonik instrukcije prate dva operanda, onda ti operandi predstavljaju odredište i izvor.

Ako instrukcija ima jedan operand, taj operand kod nekih instrukcija specificira izvor, a kod drugih odredište.

Postoje i instrukcije koje nemaju operande.

Treba napomenuti da, iako programer o mnemonicima (tj. mnemotehničkim skraćenicama) razmišlja kao o jednoj instrukciji, pa smatra da jednom mnemoniku odgovara jedan operacioni kod (jedan opkod, tj. jedan niz nula i jedinica), kod procesora 80386 to nije slučaj. Naime, tu preslikavanje skupa mnemonika u skup opkodova nije funkcija. Drugim rečima, preslikavanje skupa opkodova u skup mnemonika nije injekcija.

Primer.

 Mnemonik asemblerske instrukcije MOV ima 17 različitih opkodova.

Dakle, generisanje koda prilikom asembliranja ne zavisi samo od mnemonika, već i od načina adresiranja, veličine operanda, itd.

Načini adresiranja kod instrukcija procesora 80386

Razlikuju se sledeći načini adresiranja (tj. načini modifikacije operanada):

1) Neposredno adresiranje

2) Registarsko adresiranje

3) Direktno memorijsko adresiranje

4) Indirektno memorijsko adresiranje

     1. baza

     2. (skalirani) indeks

     3. baza+(skalirani) indeks

     4. baza+pomeraj

     5. (skalirani) indeks+pomeraj

     6. baza+(skalirani) indeks+pomeraj

Neposredno adresiranje

Ova vrsta adresiranja označava da je operand konstanta inkorporirana u instrukciju, tj. konstanta koja predstavja deo instrukcije. Neposredni operandi su najčešće celi brojevi ili pokazivači na memoriju koji su specificirani kao konstante korišćenjem pseudoinstrukcije OFFSET (sve pseudoinstrukcije, pa i pseuudoinstrukcija OFFSET biće opisane u jednom od sledećih poglavlja).

Primer.

Neka je NIZ ime memorijske lokacije. Neposredno adresiranje je zastupljeno kod sledećih instrukcija:

MOV CL, 100

MOV ESI, OFFSET NIZ

Registarsko adresiranje

Ovo adresiranje označava da je operand registar, pa se operacija koja je specificirana instrukcijom vrši nad sadržajem registra-operanda. U slučaju registarskog adresiranja, instrukcija će sadržati naziv registra-operanda.

Primer.

U sledećim instrukcijama koristi se registarsko adresiranje

ADD AX,BX

MOV ECX, EDX

Direktno memorijsko adresiranje

Ovo adresiranje označava da se direktno pristupa memorijskoj lokaciji. Za pristup memorijskoj lokaciji koristi se uređeni par sledećeg oblika:

segment:offset.

- Segment može biti naziv bilo kog 16-bitnog segmentnog registra (CS, DS, SS, ES, FS, GS), ili ime segmenta (koje je u okviru asemblerskog programa definisano korišćenjem pseudoinstrukcije SEGMENT), ili ime grupe (definisano u okviru asemblerskog programa pomoću pseudoinstrukcije GROUP). Kako je kod prethodnika procesora 80386 memorija bila segmentizovana, to se način specificiranja adrese pomoću para segment:pomeraj zadržao i nadalje.

- Offset (pomeraj) mora biti ceo broj ili izraz čija je vrednost u intervalu 0000H do 0FFFFH za 16-bitni segment, odnosno 00000000H do 0FFFFFFFFH za 32-bitni memorijski segment.

Primer.

Neka je DATA ime prethodno definisanog memorijskog segmenta. Sledeće instrukcije predstavljaju primer korišćenja direktno memorijskog adresiranja:

MOV EBX, DS:0

MOV AL, DATA:11

Indirektno memorijsko adresiranje

Kod indirektnog memorijskog adresiranja, efektivna odresa se gradi pomoću nekih od sledećih komponeneti: baza, (skalirani) indeks i pomeraj.

Baza

Za razliku od njenih prethodnika, kod procesora 80386 se svaki od 32-bitnih opštih registara može koristiti kao baza. Baza (eng. base) je, ukoliko je prisutna, sadržaj 32-bitnog opšteg registra (nazivama se bazni registar) u trenutku kada se instrukcija izvršava. Ona se, ukoliko postoji, sabira sa ostalim komponentama kako bi se izračunala efektivna adresa. Programer specificira bazu tako što ime registra čiji sadrežaj treba da predstavlja bazu uokviri uglastim zagradama.

Primer.

Sledeća instrukcija prebacuje u registar EBX dvostruku reč iz memorije na koju ukazuje registar EDX:

MOV EBX,[EDX]

Zagrade u ovom primeru saopštavaju asembleru da registar-izvorni operand ne sadrži podatke koji će se premestati, već pokazivač na lokaciju u memoriji iz koje se podaci pomeraju.

Skalirani indeks

Indeks (eng. index) je, slično kao baza, vrednost koja se određuje u trenutku izvršavanja instrukcije i dodaje se pri izračunavanju efektivne adrese. Kao i kod baze, vrednost indeksa je vrednost nekog 32-bitnog opšteg registra. Taj registar se naziva indeks registar. Za indeksiranje se može koristiti ma koji opšti registar, sem registra ESP.

Pre dodavanja na druge komponente adrese, indeks se pomnoži sa faktorom skaliranja (koji može biti 1, 2, 4 ili 8). Programer specificira indeks koristeći za skaliranje uobičajenu multiplikativnu notaciju, a potom stavljajući izraz u uglaste zagrade. Ukoliko se skaliranje eksplicitno ne navede, podrazumeva se da je faktort skalliranja 1.

Primer.

Instrukcija za prenos bajta iz memorije u registar AL, koristeći EBP za bazu, a EDX za indeks sa faktorom skaliranja 2 je:

MOV AL, [EBP][EDX*2]

Ova instrukcija se može zapisati i na drugi način

MOV AL, [EBP+EDX*2]

Pomeraj

Treća i završna komponenta koja se dodaje na memorijsku adresu je pomeraj (eng. displacement). Pomeraj je konstanta, dužine do 32 bita, koja je enkodirana u instruciju.

Pomeraj se u programima javlja bilo kao eksplicitna konstanta, bilo kao naziv promenljive čija pozicija (adresa, tj. preciznije offset) u memoriji predstavlja pomeraj.

Primer.

Pokazuje kako sve pomeraj može da figuriše u okviru instrukcija procesora 80386:

MOV AX, [EBP+8]                              ; konstantni pomeraj cija je vrednost 8

MOV AX, NIZ[ECX*2]             ; vrednost pomeraja je adresa lokacije NIZ

MOV AX, NIZ[ECX+8]                        ; vrednost pomeraja je i konstanta 8 i adresa lokacije NIZ

MOV AX, NIZ[EBX+ECX*4+8]           ; prisutne su sve komponente pri racunanju efektivne adrese

Primer.

Pokazuje različite načine kombinovanja baze, indeksa i pomeraja u zapisu asemblerskih instrukcija:

MOV AX, [BX]                         ; baza

MOV EAX, [ECX]+16              ;baza+pomeraj

MOV BX, 32[ECX]                              ; baza+pomeranje

MOV AX, [BP][SI]                               ; baza+indeks

MOV AX, NIZ[EBX+ECX*2]   ; baza+skalirani indeks + pomeraj

Primer.

Pokazuje različite načine zapisa jedne iste instrukcije:

MOV AX, NIZ[BX][DI]

MOV AX, NIZ[BX+DI]

MOV AX, [NIZ+BX+DI]

MOV AX, [BX][DI].NIZ

MOV AX, [BX][DI]+ NIZ

MOV AX, NIZ[DI][BX]

Primer.

a) ako se radi o nizu bajtova

MOV BL, X

MOV A[ESI], BL

b) ako se radi o nizu reči

MOV BX, X

MOV A[ESI*2], BX

c) ako se radi o nizu dvostrukih reči

MOV EBX, X

MOV A[ESI*4], EBX

Ilustruje kako bi izgledao asemblerski kod ekvivalentan naredbi dodele A(I)=X u nekom višem programskom jeziku, tj. kako se realizuje dodela vrednosti nekom elementu datog niza. Jasno je da se promenljiva iz višeg programskog jezika realizuje pomoću fiksirane lokacije u memoriji (sadržaj te lokacije je vrednost promenljive), a da se niz realizuje preko uzastopnih memorijskih lokacija, Dakle, ako se pretpostavi da su X i A lokacije u memoriji, a da se za pristup elementima niza koristi registar ESI, onda se gornja naredba dodele realizuje na sledeći način:

 

Veličina operanda kod instrukcija procesora 80386

Operandi instrukcija procesora 80386 mogu da se nađu u trima veličinama: bajt, reč i dvostruka reč.

Kako se često javlja slučaj da instrukcije nad podacima veličinama podataka imaju isti mnemonik a ražličiti opkod, asembler tokom asmbliranja pojdeine instrukcije mora znati veličinu operanada. Inače, asembler neće biti u stanju da korektno generiše objekt kod.

Pravila na osnovu kojih asembler zaključuje o dužini operanda su:

1) Ako postoji još neki od operanada u instrukciji (obično registar), kome se zna dužina,tada  nepoznata veličina operanda mora biti jednaka poznatoj veličini operanda (sem u nekoliko retkih izuzetaka);

2) Ako je operand ime koje je prethodno definisano korišćenjem neke od pseudoinstrukcija tj. direktiva DB, DW, DD, onda se veličina operanda izvodi iz vrste direktive koja je korišćena onda kadaje definisano ime;

3) Programer je eksplicitno dao dužinu operanda.

Primer.

U sledećim instrukcijama je eksplicitno data dužina operanda.

INC BYTE PTR[EBX]

INC WORD PTR[EBX]

INC DWORD PTR[EBX]

Asembler ne bi mogao samostalno (tj. primenom prvog i drugog pravila) dokučiti  da li da generiše kod za inkrementiranje bajta, reči ili dvostruke reči na koje ukazuje EBX.

Sa tačke gledišta mašine, tj. pri izvršavanju kreiranog izvršnog koda, nema dileme o veličinama operanada. Tu je specifikacija veličine operanda eksplicitna. Već po bitovima u opkodu je jasno da li se radi o bajt-operandu, illi o reč/dvostruka reč operandu.

Još se postavlja pitanje kako mašina razlikuje reči od dvostrukih reči. Za razlikovanje služi prefiks veličine operanda, koji se nalazi pre opkoda.

Značenje tog prefiksa zavisi od stanja procesora 80386.

1) Ako procesor 80386 emulira neki od svojih prethoodnika, tada je podrazumevajuuća veličina za ne bajt operande jednaka 16, tj. podrazumeva se da se radi sa rečima. Prisustvo prefiksa označava da se radi sa dvostrukim rečima

2) Ako procesor 80386 ne emulira prethodnike, tada je podrazumevajuća veličina ne bajt operanada dvostruka reč (tj. 32). Dakle, odsustvo prefiksa za veličinu operanda označava da se radi o dvostrukim rečima, a prisustvo da se radi o rečima.

Način korišćenja programerskih alata

Uputstvo za Turbo Asembler

Pisanje, prevođ enje i linkovanje programa

 

Programi u asembleru se pišu i prevode slicno kao i u drugim programskim jezicima. Taj  postupak se sastoji iz nekoliko koraka:

1. U editoru teksta uneti kod izvornog programa (source) i dobijeni fajl sacuvati sa ekstenzijom .asm (npr. ime_fajla.asm). Moze se koristiti bilo koji editor, na primer Notepad ili Ultraedit koji rade pod operativnim sistemom Windows. Ako se koristi Notepad, prilikom snimanja  preporucljivo je kompletan naziv fajla staviti u navodnike (npr. ” vezba1.asm„).

2. Pomoću prevodioca prevesti izvorni fajl u objektni. To se radi iz DOS prompta (do kog se dolazi sa Start -> Programs ->Command Prompt), izvrsavanjem naredbe:

                 tasm /zi/w/t ime_fajla

Primetiti da nije potrebno navoditi ekstenziju fajla. Ukoliko prevođenje prođe bez grešaka, dobija se objektni fajl sa ekstenzijom .obj (npr. ime_fajla.obj).

 

3. Pomoću linkera povezati objektni program i prevesti ga u izvrs ni. To se takođe radi iz DOS prompta, komandom:

      tlink /n/x/v ime_fajla

 

I ovde primetiti da nije potrebno navoditi ekstenziju fajla. Dobijeni izvrs ni fajl ime_fajla.exe se izvrs ava unos enjem imena fajla u DOS promptu i pritiskom na taster

<Enter>.

Debagovanje programa

Pod debagovanjem se podrazumeva kontrolisano izvrs avanje programa radi njegovog testiranja i otklanjanja eventualnih gres aka. Jedan od alata koji to omogu´ava kod

asemblerskih programa je Turbo Debugger, koji se iz DOS prompta poziva sa:

             td ime_fajla

 

Pored navedenog, ovaj debager omogu´ava pra´ enje i izmenu sadrzaja registara, flegova, memorijskih lokacija i varijabli, postavljanje prekidnih tacaka itd. U nastavku ´ će ovo biti detaljnije objas njeno.

Nakon pokretanja, dobija se osnovni prozor debagera, prikazan na slici .

 

 

 

 

 

Osnovni prozor se sastoji od pet manjih prozora. Njihov broj i polozaj nije fiksan ć neki se mogu izbaciti, a neki se mogu dodati, u zavisnosti od potrebe. Korisnik se moze kretati kroz te prozore pritiskom na taster <Tab>.

Sa 1 je oznacen prozor instrukcija. U njemu su prikazane instrukcije programa u simbolickom, ali i u mas inskom obliku. Pored njih se nalaze ofset adrese instrukcija u

kodnom segmentu. Na adresu instrukcije koja se nalazi u programskom brojacu, pokazuje simbol u obliku strelice. To je instrukcija koja se izvrs ava u narednom koraku. Simbol ¨ oznacava instrukciju koja se nalazi u izvornom fajlu.

Prozor 2 je registarski prozor. U njemu je prikazano trinaest registara x86 procesora.Sadrzaj svakog od njih, moze se izmeniti selektovanjem odgovaraju´eg registra i upisom vrednosti u heksadecimalnom formatu.

Prozor 3 se zove indikatorski prozor. On prikazuje trenutno stanje flegova indikatorskog (status) registra. Stanje svakog od flegova se moze promeniti, na isti nacin kao kod registarskog prozora.

Memorijski prozor oznacen je brojem 4. U njemu je mogu´ e prikazati sadrzaj proizvoljne memorijske lokacije u heksadecimalnom i ASCII obliku. To se postize klikom na desni taster misa u ovom prozoru (ili <Alt> + <F10>). U dobijenom meniju treba selektovati opciju Goto, upisati memorijsku adresu npr. ES:0 i pritisnuti <Enter>. Ukoliko zelimo izmeniti sadrzaj neke memorijske lokacije, treba je selektovati i upisati vrednost u heksadecimalnom formatu sa nulom ispred.

Na kraju, peti prozor je stek prozor i on prikazuje sadrzaj steka. Strelica pokazuje na vrh steka, tj. na adresu koja se nalazi u SP registru.

Glavni meni u kome se nalaze opcije za konfigurisanje i rad debagera, aktivira se tasterom <F10> ili sa <Alt> i pocetnim slovom podmenija. U podmeniju Run se nalaze naredbe Run (<F9>), koja omogu´ ava izvrs enje celog programa, Step over (<F8>) i Trace into (<F7>) koje izvrsavaju program instrukciju po instrukciju i Execute to...<Alt>+<F9> koja izvrsava program do instrukcije na zadatoj adresi.

Tacke prekida (breakpoints) su mesta na kojima korisnik zeli da zaustavi izvrsavanje programa tokom debagovanja. Postavljaju se selektovanjem instrukcije u prozoru

instrukcija na kojoj program treba da se zaustavi i selektovanjem opcije Toggle iz menija Breakpoints, ili pritiskom na taster <F2>.

Ukoliko zelimo pratiti vrednost neke promenljive ili celog izraza u toku izvrsavanja programa, to mozemo uraditi selektovanjem opcije Add Watch iz menija Data i unos enjem naziva promenljive odnosno izraza, u odgovaraju´ e polje.

Izgled ekrana u toku izvrs avanja programa, preko koga se vrs i komunikacija korisnika sa programom, dostupan je iz podmenija Window, izborom opcije User screen ili pritiskom na kombinaciju tastera <Alt> + <F5>.

Iz debagera se izlazi biranjem opcije Quit podmenija File, ili sa <Alt> + <X>.

Za sve ostale opcije i nacine njihovog koris tenja, korisnik se upu´uje na Help fajl  integrisan u okviru ovog softverskog alata.

 

Opsta struktura asemblerskog programa

TITLE 'Ovde upisati naziv programa'

;Ime i prezime, broj indexa,

;************************************************************

;Sekcija za definisanje stek segmenta

SSEG SEGMENT STACK

DW 100 DUP(0FFFFH)

SSEG ENDS

;************************************************************

;Sekcija za definisanje segmenta podataka

DSEG SEGMENT 'data'

; ovde se pisu podaci

DSEG ENDS

;************************************************************

;Ova sekcija je kodni segment. Podprocedure definisati nakon

;glavne procedure MAIN

CSEG SEGMENT 'code'

ASSUME CS:CSEG,DS:DSEG,SS:SSEG

;********************************

;Glavna procedura

MAIN PROC FAR

MOV AX,DSEG

MOV DS,AX

;

Ovde se pise kod programa

CALL IME_PROCEDURE

EXIT: MOV AX,4C00H ;Povratak u DOS nakon

INT 21H ;zavrsetka programa

MAIN ENDP

;*********************************

;Podprocedura

; ulazni parametri:

;

; izlazni parametri:

;

IME_PROCEDURE PROC NEAR

; Ovde se pise kod procedure

RET

IME_PROCEDURE ENDP

;**********************************

CSEG ENDS

END MAIN

Mikroprocesorska elektronika ć Vezba 2 16

VEZBA BROJ 1.

Rad sa tastaturom i monitorom

Uvod

Ova vezba opisuje osnovne DOS funkcije za rad sa tastaturom i monitorom racunara.

Koris ´enjem ovih funkcijskih poziva, omogu´ava se implementacija unosa i prikaza

podataka preko tastature i monitora, cime se ostvaruje jednostavna komunikacija

korisnika sa programom. Pored toga, u vezbi ´ e biti navedeni neki BIOS funkcijski

pozivi koji vrs e iste operacije, ali se koriste u slucaju kada dobijeni kod ne sme da zavisi

od operativnog sistema racunara.

Prikaz karaktera

Za ispis ASCII kodiranog podatka na monitoru racunara, koriste se DOS funkcije 02h i

06h prekida (interapta) 21h. Jedna od razlika izmeČu njih je u tome, s to se izvrs enje

funkcije 02h moze prekinuti pritiskom na kombinaciju tastera <Ctrl> +<Break>, dok se

izvrs enje funkcije 06h ne moze prekinuti. Njihovim izvrs enjem prikazuje se karakter na

trenutnoj poziciji kursora. Da bi izvrs ili ove funkcije, potrebno je:

1. Registar AH napuniti vrednos ´u 02h, odnosno 06h koriste´ i instrukcije MOV

AH,02H odnosno MOV AH,06H

2. U registar DL upisati ASCII kodiran karakter koji treba prikazati. Na primer, ukoliko

treba prikazati broj 2, koristiti instrukciju MOV DL,32H ili MOV DL,2.

3. Nakon toga izvrs iti prekid 21H, kako bi pristupili monitoru i prikazali ASCII kodiran

karakter.

 

 

Prikaz stringa karaktera

Primenjuje se kada je potrebno prikazati vis e od jednog karaktera. Za realizaciju ove

operacije, koristi se DOS funkcijski poziv sa brojem 09h. String karaktera koji treba

prikazati, mora se zavrs avati znakom $ (odnosno 24h). Pri tome, treba uraditi slede´ e:

1. U registar AH upisati vrednost 09h instrukcijom MOV AH,09H

2. Napuniti adresu segmenta i ofseta stringa karaktera koga treba prikazati u registarski

par DS:DX. To se ostvaruje izvrs avanjem instrukcije MOV DX,OFFSET STRING1

3. Na kraju, izvrs iti INT 21H kako bi se na monitoru prikazao string karaktera -

STRING1

Na slici 2 dat je primer ispisa stringa. Primetiti da string osim slovnih, sadrzi jos neke

karaktere. Broj 13 (0Dh) predstavlja carriage return - specijalni karakter koji pomera

kursor na krajnju levu ivicu ekrana, dok 10 (0Ah) predstavlja line feed ć karakter koji

CODE SEGMENT 'code'

ASSUME CS:CODE

MAIN PROC FAR

MOV AH,06H ;prikaz slova A

MOV DL,'A'

INT 21H

MOV DL,'B' ;prikaz slova B

INT 21H

MOV DL,'C' ;prikaz slova C

INT 21H

MOV AX,4C00H ;izlazak u DOS

INT 21H

MAIN ENDP

CODE ENDS

END MAIN

omogu´ ava prelazak u novi red. Vazno je napomenuti da su ASCII karakteri oznaceni sa

apostrofima ().

Unos karaktera

Za ovu svrhu se koriste DOS funkcije 01h i 07h. Funkcija 01h cita jedan karakter sa ehom

(cita ga i prikazuje na ekranu). Funkcija 07h cita unet karakter bez eha. Ako znak nije

unet, ova funkcija ceka dok se on ne unese. Bez obzira na to koja se funkcija koristi za

unos karaktera, treba uraditi slede´ e:

1. U registar AH smestiti vrednost 01h, odnosno 07h

2. Pozvati INT 21h da bi unet karakter bio procitan.

Procitan ASCII kodiran karakter vra´ a se u registru AL.

Na slici 3 dat je primer programa koji omogu´ava unos i prikaz unetih karaktera, sve dok

korisnik ne pritisne taster <Enter>.

CODE SEGMENT 'code'

ASSUME CS:CODE

STRING1 DB 13,10,10,'Hello world!',13,10,10,'$'

MAIN PROC FAR

MOV AX,CS

MOV DS,AX

MOV AH,9

MOV DX,OFFSET STRING1

INT 21H

MOV AX,4C00H

INT 21H

MAIN ENDP

CODE ENDS

END MAIN

Ukoliko treba napisati program tako da on ne zavisi od operativnog sistema racunara na

kome se on izvrs ava, moraju se koristiti BIOS (Basic I/O System) funkcijski pozivi. Oni

direktno upravljaju radom hardverskih resursa, s to ima za posledicu smanjenje vremena

izvrs enja operacija. BIOS ekvivalent DOS 07h funkcijskom pozivu je 00h funkcijski

poziv, koji se aktiviraju sa INT 16h prekidom. Nacin koris ´ enja ovih funkcija je slican

kao i kod DOS funkcija ć u AH registar se postavi odgovaraju´ a vrednost (00h) i izvrs i se

INT 16H.U AL registru se vra´a ASCII ekvivalent unetog karaktera, a u AH registru se

vra´ a njegov skan kod.

Unos stringa karaktera

Za unos stringa karaktera koristi se 0Ah DOS funkcijski poziv prekida 21h. On

omogu´ ava citanje stringa sa ehom i njegovo smes tanje u memoriju. Ukoliko doČe do

gres ke prilikom unosa, mogu´ e je vratiti kursor i ispraviti pogres no unet karakter. Drugim

recima, izvrs enjem ove funkcije, dobija se jedna vrsta linijskog editora. Algoritam

koris tenja ove DOS funkcije, sastoji se iz nekoliko koraka:

1. U AH upisati vrednost 0Ah instrukcijom MOV AH,0AH

CODE SEGMENT 'code'

ASSUME CS:CODE

MAIN PROC FAR

MOV AH,1 ;citanje slova sa ehoom

INT 21H

CMP AL,0dh ;test za izlazak iz petlje

JNE MAIN ;skok ako nije 0dh (Enter)

MOV AX,4C00H

INT 21H

MAIN ENDP

CODE ENDS

END MAIN

Slika 3

2. U DS:DX registarski par upisati segmentnu i ofset adresu prve memorijske lokacije

bafera za smes taj podataka koji se unose pomo´u tastature. Pomenuti bafer mora

sadrzati prostor za podatke koji se unose, kao i za dodatne informacije vezane za

maksimalnu i stvarnu duzinu stringa karaktera.

3. Izvrs iti INT 21h instrukciju kako bi se podaci procitali i smestili na unapred zadato

mesto u memoriji. Unos se prekida ukoliko se pritisne taster <Enter> ili se prepuni

bafer za prijem podataka.

Slika

Na slici  dat je primer koji omogu´ava unos maksimalno deset karakera i smes ta ih u

memorijski bafer BUF. Prvi bajt bafera sadrzi broj koji govori koliko maksimalno

karaktera mozemo upisati, a drugi bajt govori koliko je zaista karaktera uneto, pre nego

s to je pritisnut taster <Enter>. Od tre´ eg bajta pa nadalje nalaze se ASCII kodovi unetih

karaktera.

Primetiti da se kao poslednji karakter u unetom stringu, u memoriju upisuje 0Dh, odnosno

carriage return. To znaci, kada string unet na ovaj nacin treba prikazati koriste´ i 09h

funkcijski DOS poziv, neophodno je 0Dh zameniti sa 24h tj $znakom.

CODE SEGMENT 'code'

ASSUME CS:CODE

BUF DB 10 ;broj karaktera koje treba procitati

DB ?

DB 11 DUP(?)

MAIN PROC FAR

MOV AX,CS

MOV DS,AX

MOV AH,0AH

MOV DX,OFFSET BUF

INT 21H

MOV AX,4C00H

INT 21H

MAIN ENDP

CODE ENDS

END MAIN

 

 

 

Programerski alati koji će se koristiti u ovladavanju sadržajima ovog kursa su:

EDIT - Editor (može se korisititi i neki drugi)

MASM - Makro asembler verzija 5.10

LINK - Segmentno-izvršni linker verzija 5.01.20

LIB - Program za rad sa bibliotekom asemblerskih procedura verzija 3.17

CREF - Korisnički program za razrešavanje unakrsnih referenci

CV - Dibager “Pogled u kod” verzija 2.2

Asembler MASM

Način korišćenja:

masm [/options] source(.asm)[,[out(.obj)],[list(.lst)],[cref(.crf)][;]]

Korektne opcije su:

/a

Upisuje segmente po alfabetskom redosledu

/c

Kreira datoteku sa ukrštenim referencama

/d

Kreira listing i pri prvom prolasku

/D<simbol>[=<vrednost>]

Definiše simbol

/e

Generiše kod koji emulira instrukcije u pokretnom zarezu

/h

Prikazuje stranu koja opisuje način korišćenja asemblera

/I<put>

Postavlja put do direktorijuma koji može da sadrži datoteke koje se uključuju

/l[a]

Generiše listing (a iznačava da listing sadrži sve)

/M{lxu}

Postavlja osetljivost na velika i mala slova kod labela

/n

Ne prikazuje tabelu sibola u asemblerskom listingu

/p

Proverava čistoću koda

/s

Upisuje segmente po redosledu čitanja

/t

Ne prikazuje poruku da je asembliranje uspešno proteklo

/v

Prikazuje ekstra statistiku o izvornom kodu

/w{012}

Postavlja nivo upozorenja: 0-Nema, 1-Ozbiljna, 2-Saveti

/z

Prikazuje izvornu liniju u kojo se dogodila grška

/Zi

Kreira simboličke informacije za CodeView

/Zd

Kreira informacije o broju linija

Ukoliko se u komandnoj liniji ne navedu naziv objekt-datoteke, datoteke sa listingom ni datoteke sa unakrsnim referencama, asembler će tokom rada programera pitati da li želi kreiranje ovih datateka, i kako da se zovu.

Asembliranje se izvršava u dve faze: u prvoj se generiše tabela simbola, a u drugoj sa generiše kod.

Ako se program po kreiranju izvršnog koda treba dibagirati pomoću Code View-a, poželjno je da se uključi opcija /Zi

Linker LINK

Način korišćenja:

link [/options] object(.obj) [+object(.obj)...] [,[execute(.exe)], [mapping(.map)],[library(.lib)[+ library(.lib)...]]]

Neke od najvažnijih opcija su:

/CODEVIEW (/CO)

Prenosi informacije o objektima, tako da Code View može  bolje da radi

/CPARMAXALLOC (/CP:n)

Postavlja maksimalan broj ekstra memorijskih paragrafa na zadatu vrednost

/DOSSEG (/DO)

Uređuje segmente u skladu sa konvencijom za Microsoftove  jezike

/EXEPACK (/E)

Kompresuje ponavljajuće sekvence bitova

/FARCALLTRANSLATION (/FC)

Generše se kod sa prevođenjem poziva u daleke pozive

/HELP (/HE)

Prikazuje stranu koja opisuje način korišćenja linkera

/HIGH (/HI)

Smešta izvršni kod u što je moguće višu memoriju

/LINENUMBERS (/LI)

Kopira informacije o brojevima linija

/MAP (/M)

Kopira u datoteku mapiranja listu svih javnih simbola deklarisanih u objekt datoteci

/NODEFAULTLIBRARYSEARCH (/NOD)

Pretaga za bibliotekama se svodi na pretragu biblioteka specificiranih u komandnoj liniji

/NOFARCALLTRANSLATION (/NFC)

Ne generše se kod sa prevođenjem poziva u daleke pozive

/NOIGNORECASE (/NOI)

Pravi razliku između velikih i malih slova

/PAUSE (/P)

Pauzira i pita korisnika da promeni disk pre upisa izvršne  datoteke

/SEGMENTS:n (/SE:n)

Postavlja maksimalan broj segmenata koji mogu biti obrađeni

/STACK (/ST:n)

Postavlja veličinu steka

Ako se program po kreiranju izvršnog koda treba dibagirati pomoću Code View-a, poželjno je da se uključi opcija /CO

Program za rad sa bibliotekama LIB

Način korišćenja:

lib [/options]  library [options] [commands] [,listfile [,newlibrary]]

Neke od najvažnijih opcija su:

/IGNORECASE

Ignoriše razliku između velikih i malih slova

/NOEXTDICTIONARY

Ne gradi rašireni rečnik

/NOIGNORECASE

Ne ignoriše razliku između velikih i malih slova

/NOLOGO

Ne prikazuje logo

/PAGESIZE:n

Postavlja veličinu strane u biblioteci

Komande su:

+name

Dodaje objekt datoteku u biblioteku

-name

Briše objekt datoteku iz biblioteke

-+name

Zamenjuje objekt datoteku u biblioteci

*name

Kopira (ekstrahuje) objekt datoteku iz biblioteke

-*name

Premešta (ekstrahuje i briše) objekt datoteku iz biblioteke

Dibager Code View

Način korišćenja:

cv [/options] file [arguments]

Neke od najvažnijih opcija su:

/T

Startuje dibager u terminalskom modu

/43

Radi u 43-kolonskom formatu, tj. prikaz teksta ide u 43 kolone

/50

Radi u 50-kolonskom formatu, tj. prikaz teksta ide u 50 kolona

Ako dibager Code View ne radi u terminalskom modu, pojavljuju se komandni (terminalski) prozor, prozor sa registrima (uključujući i registar flegova), te programski prozor. Prelazak iz jednog u drugi prozor realizuje se pritiskom na taster F6. Pored toga, postoji i padajući meni iz kog se opcije biraju na standardni način.

SKUP INSTRUKCIJA PROCESORA 80386

Instrukcije prenosa podataka

Instrukcije prenosa podataka se dele u tri grupe: prenos opšte namene, prenos specificiran akomulatorom i prenos flegova.

Prenos opšte namene

Prenos između registara i memorije

MOV D, S (eng. move - prenos) - S ® D. Ova dva operanda instrukcije MOV moraju biti iste dužine. Jedan od operanada mora biti registarski ili neposredno specificiran.

MOVZX D, S (eng. move zero extended - prenos sa raširenom nulom) - S ® (nulom raširen) D. Jedan od operanada ove instrukcije mora biti registarski ili neposredno specificiran. Ova instrukcija nije postojala kod prethodnika procesora 80386.

MOVSX D, S (eng. move sign extended - prenos sa raširenim znakom) - S ® (znakom raširen) D. Jedan od operanada ove instrukcije mora biti registarski ili neposredno specificiran. Ni ova instrukcija nije postojala kod prethodnika procesora 80386.

XCHG D, S (eng. exchange - razmena) - S « D. Razmenjuju se vrednosti izvornog i odredišnog operanda. Kod ove instrukcije jedan od operanada mora biti registarski ili neposredno specificiran.

Primer.

U sledećim instrukcijama je ilustrovan način korišćenja instrukcija MOV, MOVZX, MOVSX, XCHG.

 

MOV AH, BH

MOV BX, DX

MOV EAX, ESI

MOV BL, 35

MOV CX, 850

MOV EAX, mem

MOVSX AX, BL

MOVZX BX, AL

MOVSX EDX, mem

MOVZX ECX, CX

 

 

 

 

 

XCHG AL, AH

XCHG CX, DX

XCHG EAX, ESI

CBW (eng. convert byte to word - konvertuj bajt u reč) - AL ® (znakom raširen) AX. Instrukcija nema operanada.

CWD (eng. convert word to doubleword - konvertuj reč u dvostruku reč) - AX ® (znakom raširen) DXAX. Instrukcija nema operanada.

Ove dve prethodno pomenute instrukcije su postojale i kod prethodnika procesora 80386. Sa stanovišta procesora 80386, prethodno obrađena instrukcija MOVSX predstavlja uopštenje ovih instrukcija. O instrukcijama CBW i CWD će biti reči i pri obrađivanju instrukcija za celobrojno množenje i deljenje.

Prenos sa steka i na stek

Da bi se moglo izvršavati guranje elemenata na stek, i skidanje elemenata sa steka, potrebno je specificirati veličinu memorijskog prostora odvojenog za stek. Nadalje, potrebno je postaviti segmentni registar SS na segmentnu adresu početka steka, tj. 16-bitni registar SS treba da pokazuje na početak prostora u memoriji (segmenta) u kom se stek nalazi (SS je tada stek segment, odnosno selektor steka). Na kraju, treba postaviti registar ESP (odnosno SP kod 16-bitnih segmenata) tako da ukazuje na vrh steka. Taj registar neće sadržati apsolutnu adresu vrha steka, već vrednost offset-a u odnosu na početak memorijskog segmenta koji je odvojen za stek (tj. offset-a u odnosu na vrednost registra SS). Dakle, ESP će pokazivati na poslednji element (reč ili dvostruku reč) koja je unesena na stek.

Ovo odvajanje memorijskog prostora i postavljanje vrednosti registara se može izvršiti automatski pomoću odgovarajućih pseudooperacija.

Primer.

Registri SS i SP će biti “automatski” postavljeni na prave vrednosti, zahvaljujući asembleru MASM i linkeru LINK, ako se u izvornom kodu nalazi sledeći konstrukt:

STEK SEGMENT STACK

            DW 100H DUP(?)

STEK ENDS

Za ovako oformljen stek biće odvojeno 256 reči (512 bajtova), čija vrednost nije inicijalizovana.

Instrukcije za guranje na stek i skidanje sa steka su:

PUSH S (eng. push - gurni) - S ® stek. Izvorni operand se smešta na stek. Argumenat ove instrukcije je reč ili dvostruka reč, a počev od procesora 80386 kod ove instrukcije može figurisati i neposredno adresiranje.

POP D (eng. pop - skini) - stek ® D. Vrednost sa vrha steka se smešta u odredišni operand. Argumenat ove instrukcije je reč ili dvostruka reč.

Primer.

Opisuje način realizacije PUSH instrukcije.

Početno stanje

 

 

 

 

 

 

 

 

 

 

 

...

 

 

esp:

f

f

f

f

9

0

7

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

eax:

1

2

3

4

5

6

7

8

 

 

 

 

ebx:

9

a

b

c

d

e

f

0

 

 

 

 

 

 

 

 

 

 

 

 

 

ffff9070:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

...

 

PUSH EAX

 

 

 

 

 

 

 

 

 

 

 

...

 

 

esp:

f

f

f

f

9

0

6

c

ffff906c:

7

8

 

 

 

 

 

 

 

 

 

 

 

5

6

 

eax:

1

2

3

4

5

6

7

8

 

3

4

 

ebx:

9

a

b

c

d

e

f

0

 

1

2

 

 

 

 

 

 

 

 

 

 

ffff9070:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

...

 

POP BX

 

 

 

 

 

 

 

 

 

 

 

...

 

 

esp:

f

f

f

f

9

0

6

e

 

7

8

 

 

 

 

 

 

 

 

 

 

 

5

6

 

eax:

1

2

3

4

5

6

7

8

ffff906e:

3

4

 

ebx:

9

a

b

c

5

6

7

8

 

1

2

 

 

 

 

 

 

 

 

 

 

ffff9070:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

...

 

Primećuje se da se pri stavljanu na stek vrednost ESP smanjuje, a da se pri skidanju sa steka vrednost ESP povećava.

Izvršenje instrukcije PUSH započinje sa umanjenjem sadržaja ESP za potrebnu veličinu, pa se tek potom vrši prenos u memoriju. Kod instrukcije POP se prvo vrši prenos podataka, a potom sa uvećava ESP.

PUSHAD (eng. push all doublewords - gurni sve dvostruke reči) - opšti registri ® stek. Sadržaj opštih registara se gura na stek. Ova instrukcija nema operanada. Ona postoji kod procesora 80386 i njegovih sledbenika (potomaka).

POPAD (eng. pop all doublewords - skini sve dvostruke reči) - stek ® opšti registri. Vrednosti sa steka se smeštaju u opšte registre. Ni ova instrukcija nema operande. Ta instrukcija nije postojala kod prethodnika procesora 80386.

Instrukcija PUSHAD će registre na stek gurnuti po sledećem redosledu: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, pri čemu se na stek gura vrednost koju je ESP imao pre izvršenja instrukcije PUSHAD. Instrukcija POPAD će, naravno, vrednosti sa steka skidati u obrnutom redosledu.

PUSHA (eng. push all - gurni sve) - 16-bitni opšti registri ® stek. Sadržaj opštih registara se gura na stek. Ova instrukcija nema operanada.

POPA (eng. pop all - skini sve) - stek ® 16-bitni opšti registri. Vrednosti sa steka se smeštaju u opšte registre. Ni ova instrukcija nema operande.

Instrukcije PUSHA i POPA izvršavaju ekvivalentne operacije kao PUSHAD i POPAD, samo sa 16-bitnim registrima, a osnovni razlog njihovog postojanja je kompatibilnost sa prethodnicima procesora 80386.

Primer.

PUSH AX

PUSH ECX

POP BX

POP EBP

POPAD

POPA

PUSHAD

PUSHA

Ilustruje primenu instrukcija za prenos podataka sa steka i na stek.

Prenos specificiran akumulatorom

Kod ovih prenosa samo akumulator (registar AL, AX, EAX) može da se javi kao operand.

IN D, S (eng. in - u) - ulazni port ® akumulator. Ova instrukcija realizuje prenos odredjenog broja bitova sa ulaznog porta u akumulator (tj. registar AL, AX, EAX). Broj porta sa kog se unose podaci može biti specificiran bilo direktno, bajtom (tada je najveći broj porta 255), bilo indirektno, sadržajem DX registra.

OUT D, S (eng. out - napolje, van) - akumulator ® izlazni port. Instrukcija OUT realizuje prenos odredjenog broja bitova iz akumulatora (tj. registra AL, AX, EAX) u izlazni port. Broj porta na koji se šalju podaci može biti odredjen bilo direktno, bajtom (tada je najveći broj porta 255), bilo indirektno, sadržajem DX registra.

DX registar je jedini od registara koji kod ove dve instrukcije može služiti za specificiranje porta.

Primer.

IN AL, 1

IN AX, 10

IN EAX, 8

OUT 50, AL

OUT 30, AX

OUT 5, EAX

MOV DX, 7

IN EAX, DX

MOV DX, 5H

OUT DX, AL

Ilustruje način korišćenja instrukcija IN i OUT.

XLATB (eng. translate - prenos prevodjenje) - niz (AL) ® AL. Prevodi vrednost AL-a. Ova instrukcija nema operande.

Ova instrukcija vrši prevodjenje tako što se vrednost u registru AL zameni sa AL-tim bajtom iz niza u memoriji na koji pokazuje registar EBX. Odbrojavanje u nizu počinje od 0. Kod ove instrukcije nijedan drugi registar sem EBX ne može da se koristi kao pokazivač na niz u memoriji. Dakle, ovakvo korišćenje registra EBX predstavlja još jedan slučaj specijalizovanog korišćenja registra (specijalizovano korišćenje registara je postojalo i kod insttrukcija IN i OUT).

Primer.

Ilustruje izvršavanje XLATB instrukcije.

Početno stanje:

 

 

 

 

 

 

 

 

 

 

 

...

 

 

ebx:

5

6

3

4

F

1

E

2

 

E

2

 

 

 

 

 

 

 

 

 

 

5634f1e2:

F

1

 

eax:

a

a

b

b

5

5

0

4

 

3

4

 

 

 

 

 

 

 

 

a

l

 

5

6

 

 

 

 

 

 

 

 

 

 

 

7

8

 

 

 

 

 

 

 

 

 

 

5634f1e6

9

A

 

 

 

 

 

 

 

 

 

 

 

0

1

 

 

 

 

 

 

 

 

 

 

 

0

2

 

 

 

 

 

 

 

 

 

 

 

0

3

 

 

 

 

 

 

 

 

 

 

 

...

 

XLATB

 

 

 

 

 

 

 

 

 

 

 

...

 

 

ebx:

5

6

3

4

F

1

E

2

 

E

2

 

 

 

 

 

 

 

 

 

 

5634f1e2:

F

1

 

eax:

a

a

b

b

5

5

9

A

 

3

4

 

 

 

 

 

 

 

 

a

l

 

5

6

 

 

 

 

 

 

 

 

 

 

 

7

8

 

 

 

 

 

 

 

 

 

 

5634f1e6

9

A

 

 

 

 

 

 

 

 

 

 

 

0

1

 

 

 

 

 

 

 

 

 

 

 

0

2

 

 

 

 

 

 

 

 

 

 

 

0

3

 

 

 

 

 

 

 

 

 

 

 

...

 

Dakle, izvršenjem instrukcije XLATB, vrednost registra AL se od 04H transformisala u 9AH.

Instrukcije prenosa flegova

Značaj i uloga flegova je opisana u poglavlju  koje se odnosilo na arhitekturu procesora 80386.

Primer.

Pokazuje kako su raspoređene pozicije ćelija koje predstavljaju flegove u registru flegova EFLAGS.

0

0

0

0

0

0

0

0

0

0

0

0

0

0

VM

RF

0

NT

IO

PL

OF

DF

IF

TF

SF

ZF

0

AF

0

PF

1

CF

LAHF (eng. load AH with flags - napuni AH sa fllegovima) - SF, ZF. 0, AF, 0, PF, 1, CF ® AH. Bajt najmanje težine iz registra flegova EFLAGS se premešta u registar AH. Ova instrukcija nema operande.

SAHF (eng. store AH into flags - smesti AH u fllegove) - AH ® SF, ZF. X, AF, X, PF, X, CF. Sadržaj registra AH premešta u bajt najmanje težine registra flegova EFLAGS. Ni ova instrukcija nema operande.

Primer.

Ilustruje na kojim pozicijama se čuvaju flegovi u registru AH, po izvršenju instrukcije LAHF.

SF

ZF

0

AF

0

PF

1

CF

PUSHFD (eng. push flags doubleword - gurni dvostruku reč flegova) - EFLAGS ® stek. Sadržaj registra EFLEGS ide na stek. Ova instrukcija nema operande. Ona postoji tek kod skupa instrukcija procesora 80386.

POPFD (eng. pop flags doubleword - skini dvostruku reč flegova) - stek ® EFLAGS. Sa steka se skidaju 4 bajta koji se smeštaju u registar EFLAGS. Ni ova instrukcija nema operande, a postoji tek kod procesora 80386 i njegovih potomaka.

PUSHF (eng. push flags - gurni flegove) - 0, NT, IOPL, OF, DF, IF, TF, SF, ZF, 0, AF, 0, PF, 1, CF ® srek. Reč manje težine iz registra EFLAGS smešta se na stek. Instrukcija ne sadrži operande.

POPF (eng. pop flags - skini flegove) - stek ® 0, NT, IOPL, OF, DF, IF, TF, SF, ZF, 0, AF, 0, PF, 1, CF. Sa steka se skidaju 2 bajta i smeštaju u donju polovinu registra EFLAGS. Instrukcija nema operande.

Primer.

Ilustruje na kako se flegovi čuvaju na steku.

 

 

 

 

.

.

.

 

 

ESP®

SF

ZF

0

AF

0

PF

1

CF

 

0

NT

IO

PL

OF

DF

IF

TF

 

0

0

0

0

0

0

VM

RF

 

0

0

0

0

0

0

0

0

 

 

 

 

.

.

.

 

 

Aritmetičke instrukcije

Aritmetičke instrukcije delimo u tri grupe: instrukcije sabiranja, instrukcije oduzimanja i instrukcije množenja i deljenja.

[est statusnih flegova su postavljeni ili obrisani (tj. statusne zastavice su dignute ili spuštene) kada se pri izvršenju instrukcije prepoznaju sledeći uslovi:

1) CF se postavlja kada rezultat operacije, tumačen kao neoznačen broj, dovede do iskakanja iz opsega.

2) OF se postavlja kada rezultat operacije, tumačen kao označen bbroj dovede do iskakanja iz opsega.

3) ZF se postavlja ako je rezultat operacije 0 tj. ako su sve binarne cifre rezultata nule.

4) SF se postavlja ako je bit najveće težine 1, i na taj način indicira da je rezultat negativan.

5) PF se postavlja ukoliko 8 bitova najmanje težine kod rezultata sadrži paran broj jedinica.

6) AF se postavlja kada je potrebna korekcija za decimalne operacije.

Već je istaknuto da PF ukazuje na parnost broja jedinica u poslednjem bajtu rezultata. To je kod rodonačelnika ove familije procesora omogućavalo kontrolu parnosti osmobitnog serijskog ulaza podataka. Iako se potreba vodjenja kontrole na ovakav način već odavno izgubila, fleg je ostao zbog očuvanja kompatibilnosti.

Rad sa brojevima dužim od 32 bita se izvršava tako što se ti brojevi razbijaju na delove dužine 8, 16, 32 i potom se operacije izvršavaju na tako dobijenim delovima, počev od delova najmanje težine.

Instrukcije sabiranja

Tu spadaju instrukcije ADD, ADC, INC.

ADD D, S (eng. add - saberi) - D+S ® D.

ADC D, S (eng. add with carry - saberi sa prenosom) - D+S+CF ® D.

INC D (eng. inerement - inkrementiraj, uvećaj za 1) - D+1 ® D.

Prve dve medju ovim instrukcijama imaju tačno dva operanda. One zahtevaju da bar jedan od operanada bude registarski ili neposredno adresiran.

Instrukcija INC ima jedan operand. Ova instrukcija je po svom dejstvu ista kao ADD insstrukcija čiji je drugi operand 1, osim što pri kodiranju zahteva manje bajtova i što njeno izvršenje ne utiče na CF.

Instrukcije oduzimanja

Tu spadaju: SUB, SBB, DEC, NEG, CMP.

SUB D, S (eng. subtract - oduzmi) - D-S ® D.

SBB D, S (eng. subtract with borrowe - oduzmi sa pozajmljivanjem) - D-S-CF ® D.

DEC D (eng. decrement - dekrementiraj, umanji za 1) - D-1 ® D.

NEG D (eng. negate - negiraj, promeni znak) - 0-D ® D.

CMP D, S (eng. compare - uporedi) - odredi se D-S i u skladu sa tim postave se odgovarajući flegovi.

Prve tri medju ovim instrukcijama su analogne odgovarajućim, prethodno opisanim instrukcijama sabiranja.

Intrukcija NEG vrši promenu znaka operanda, pod uslovom da se broj tumači kao označen broj. Faktički, ova instrukcija u odredišni operand smešta njegov potpuni komplement.

Primer.

Ilustruje način izvršenja instrukcije NEG.

Početno stanje:

al:

0

0

0

0

0

0

1

1

=

3

NEG AL

al:

1

1

1

1

1

1

0

1

=

-3

Instrukcija CMP odgovara instrukciji oduzimanja, samo što se dobijeni rezultat ne smešta nigde. Naime, odredišni operand ostaje nepromenjen. Značaj ove instrukcije je u postavljanju flegova. Flegovi indiciraju stanje razlike, koje faktički pokazuje kakav je odnos između operanada instrukcije CMP.

Postavljanje flegova je prikazano sledećom tabelom:

 

 

CF

ZF

SF

OF

 

jednako

0

1

0

0

 

manji

-

0

1

0

Označeni operandi

manji

-

0

0

1

 

veći

-

0

0

0

 

veći

-

0

1

1

 

jednako

0

1

0

0

Neoznačeni operandi

ispod

1

0

-

-

 

iznad

0

0

-

-

Instrukcije množenja i deljenja

To su operacije: MUL, IMUL, DIV, IDIV.

MUL S (eng. multiply - pomnoži) -

AL*S8 ® AX,

ili AX*S16 ® DXAX,

ili EAX*S32 ® EDXEAX.

MUL D, S (eng. multiply - pomnoži) - D*S ® D. Ovakva forma instrukcije karakteriše procesor 80386 i njegove potomke.

MUL D, H, S (eng. multiply - pomnoži) - H*S ® D. Ovde S predstavlja neposredno zadat operand (tj. broj), a H je bilo memorijski bilo registarski operand. Ovakva forma instrukcije takođe karakteriše procesor 80386 i njegove potomke.

IMUL S (eng. imteger multiply - celobrojno množenje, množenje označenih brojeva) -  

AL*S8 ® AX,

ili AX*S16® DXAX,

ili EAX*S32 ® EDXEAX.

IMUL D, S (eng. imteger multiply - celobrojno množenje, množenje označenih brojeva) - D*S ® D. Ovakva forma instrukcije karakteriše procesor 80386 i njegove potomke.

  

 

IMUL D, H, S (eng. imteger multiply - celobrojno množenje, množenje označenih brojeva) - H*S ® D. Kao i kod instrukcije MUL, i ovde S predstavlja neposredno zadat operand (tj. broj), a H je bilo memorijski bilo registarski operand. Ovakva forma instrukcije takođe postoji isključivo kod procesora 80386 i njegovih potomaka.

 

DIV S (eng. divide - podeli) -

AX div S8 ® AL i AX mod S8 ® AH,

ili DXAX div S16 ® AX i DXAX mod S16 ® DX,

ili EDXEAX div S32 ® EAX i EDXEAX mod S32 ® EDX.

IDIV S (eng. integer divide - celobrojno deljenje, deljenje označenih brojeva) -

AX div S8 ® AL i AX mod S8 ® AH,

ili DXAX div S16 ® AX i DXAX mod S16 ® DX,

ili EDXEAX div S32 ® EAX i EDXEAX mod S32 ® EDX.

 

 


Instrukcije deljenja za procesor 80386 (a i za njegove prethodnike) su dizajnirane tako da ponište ono što je urađeno instrukcijom množenja. Sledeće sheme prikazuju izvršenje operacije deljenja:

Ima jedna “nezgoda” sa instrukcijom deljenja. Ona se naziva prekoračenje pri deljenju (eng. divide overflow). Prekoračenje pri deljenju nastupa onda kada je količnik pri deljenju suviše veliki tako da se ne može smestiti u željeni registar (to se događa kada se nešto suviše veliko deli sa nečim mnogo malim). Za razliku od prekoračenja pri sabiranju i oduzimanju, nema smislenog načina za nastavak rada sa ovako dobijenim rezultatom, pa u ovom slučaju procesor generiše prekid (eng. interupt) tipa 0. Deljene sa nulom je samo jedna, ali ne i jedina mogućnost prekoračenja pri deljenju.

Da bi se pri radu sa označenim brojevima dobili tačni rezultati, potrebno je koristiti instrukcije IMUL i IDIV. [to se celobrojnog deljenja tiče, treba napomenuti da se ono izvršava tako da dobijeni količnik i ostatak budu istog znaka.

Primer.

Mada obe jednakosti važe, celobrojno deljenje se kod procesora 80386 realizuje na drugi način:

(-26):7=-4(+2)

(-26):7=-3(-5)

Primer.

mov al, 56

cbw

idiv bl

 

mov AX, 56

cwd

IDIV BX

MUL BL                                   ; AL*BL->AX

IMUL CX                                 ; AX*CX->DXAX

IMUL EBX                               ; EAX*EBX->EDXEAX

IMUL DX, BX,300                   ; BX*300->DX

IMUL CX,3                              ; CX*3->CX

IMUL EAX, EDX, 100000        ; EDX*100000->EAX

IMUL EBP,500                                    ; EBP*500->EBP

IMUL BX, CX                           ; BX*CX->BX

IMUL EDX, EBP                      ; EDX*EBP->EDX

Ilustruje korišenje instrukcija množenja i deljenja.

 

Primer.

mov al, 56

MOV AH, 0

div bl

mov AX, 56

MOV DX, 0

DIV BX

Ilustruje potrebu da se delilac proširi do potrebne dužine pre nego što se izvrši deljenje (korišćenjem forme instrukcije DIV ili IDIV sa jednim operandom).

Zadatak. Opisati sadržaj opštih registara po izvršenju svake od instrukcija u sledećem segmentu asmblerskog koda:

MOV AX, 5

MOV BX, 4

SUB AX, 2

IMUL BX

MOV BX, AX

MOV CX, AX

MOV DX, AX

INC CX

a)                                                                                 b)

                                                c)

MOV DX, 8

MOV AX, 9

SUB DX, 4

MUL DX

MOV CX, DX

INC CX

SUB CX, 1

MOV CX, 3

ADD CX, 5

MOV BX, CX

INC BX

MOV AX, BX

MOV EAX, 6

MOV EBX, 4

MOV ECX, 5

ADD EAX, EBX

SUB EAX, 3

IMUL EBX

d)                                                                                 e)

Zadatak. Napisati program na asemblerskom jeziku koji u registar CX smešta vrednost izraza 5*(7+1)-6.

Instrukcije za rad sa efektivnom adresom

Već je istaknuto da postoji više načina modifikacije operanda, tj. više različitih adresnih modova. Pokazano je da adresiranje pomoću neki od tih adresnih modova zahteva sabiranje vrednosti i/ili množenje vrednosti sa faktorima skaliranja. Stoga, mora da postoji hardver koji podržava te operacije, pa je poželjno da se programeru omogući direktniji pristup ovim mehanizmima.

LEA D, S (eng. load effective adress - napuni efektivnu adresu) - adresa(S) ® D. Ova instrukcija u odredište smešta efektivnu adresu izvornog memorijskog operanda.

Primer.

Opisuje najčešći način korišćenja instrukcije LEA: za dobijanje pokazivača na neku memorijsku adresu. Tako će registar ESI će sadržati efektivnu memorijsku adresu lokacije NIZ po izvršenju instrukcije

LEA ESI, NIZ.

Treba napomenuti da isti efekat ima i korišćenje pseudoinstrukcije OFFSET, pa se prethodna instrukcija može zameniti sa MOV ESI, OFFSET NIZ, koja će imati isti efekat. Druga varijanta oformljuje za bajt kraći program, ali ima situacija u kojima se ona ne može primeniti, već se mora raditi sa instrukcijom LEA.

Primer.

MOV ESI, 10

ADD ESI, EBX

ADD ESI, EDI

 

LEA ESI,[EBX+EDI+10]

Ilustruje korišenje instrukcije LEA. Sledeća dva segmenta asemblerskog koda realizuju isti posao: smeštaju u ESI zbir EDI+EBX+10

 

Primer.

Ilustruje važnu osobinu instrukcije LEA: prilikom njenog izvršenja ne postavljaju se niti brišu flegovi. Neka treba uvećati sadržaj registra EBX za 4. Neka je već napravljen test memorijske lokacije na koju pokazuje EBX i neka tako dobijene flegove ne treba menjati (jer u zavisnosti od vrednosti tako postavljenih flegova se preduzimaju dalje akcije).

- jedan dobar način za uvećanje vrednosti EBX za 4, a da se ne promene vrednosti flegova je izvršenje PUSHFD (ili PUSHF) pre uvećanja EBX, i izvršenje POPFD (POPF) posle uvećanja EBX.

- drugi, bolji, način za postizanje istog cilja je instrukcija LEA EBX, [EBX+4].

Instrukcije za rad sa binarno kodiranim dekadnim brojevima

Dekadni brojevi se dugo i mnogo koriste u računarstvu. Oni su izuzetno važni u poslovnim primenama računara.

                        0          1          2          3          4          5          6          7          8          9

                        0000    0001    0010    0011    0100    0101    0110    0111    1000    1001


Binarno kodirani dekadni (BCD) brojevi predstavljaju najpopularnije kodiranje dekadnih brojeva:

Kod BCD brojeva razlikuju se pakovani i nepakovani BCD brojevi. Kod pakovanih BCD brojeva, BCD cifra se pakuje (smešta) u polubajt. Kod nepakovanih BCD brojeva se u jedan bajt smešta jedna cifra.

Obično se decimalni brojevi kodiraju tako što se smeste u niz uzastopnih bajtova, pri čemu je na prvom mestu binarni broj koji predstavlja broj cifara potrebnih za zapis dekadnog broja.

Primer.

Broj -125 se na sledeći način predstaviti kao pakovani BCD broj:

tri cifre

minus

1

2

5

0011

1000

0001

0010

0101

Odmah se, logično, postavlja pitanje načina realizacije osnovnih aritmetičkih operacija sa pakovanim i nepakovanim BCD brojevima. Jasno je da se operacije sa BCD brojevima moraju izvršavati cifra po cifra. Ostaje tada pitanje načina izvršavanja operacija sa BCD ciframa. Treba istaći da ne postoje specijalne operacije za sabiranje, oduzimanje, množenje cifara BCD brojeva, već se na cifre primene poznate instrukcije ADD, SUB, MUL (IMUL) i DIV(IDIV). Budući da tako dobijeni rezultat (tumačen sa stanovišta BCD brojeva) nije korektan, potrebno je dodati popravku.

Primer.

Ilustruje kakve se popravke trebaju uvesti u raznim slučajevima sabiranja cifara pakovanih BCD brojeva.

1) Pri sabiranju dvocifrenih pakovanih BCD brojeva 23 i 14, treba da se dobije 37. Prostim bitovnim sabiranjem, tj. instrukcijom ADD se i dobija ta vrednost, tj. korektan rezultat.

2) Neka treba sabrati dva dvocifrena pakovana BCD broja 75 i 29. Po izvršenju bitovnog sabiranja, bajt rezultata će sadržati 9E. Korektan rezultat bi bio 04, pri čemu bi trebalo (jer ima prenosa sa mesta najveće težine rezultata) da se CF postavi na 1.

3) Neka treba sabrati dva dvocifrena pakovana BCD broja 38 i 29. Po izvršenju bitovnog sabiranja, bajt rezultata će sadržati 61. Korektan rezultat bi bio 67.

Dakle, uvođenje popravke kod sabiranja cifara pakovanih BCD brojeva svodi se na dodavanje broja 6 na donji polubajt rezultata, ukoliko je vrednost tog donjeg polubajta rezultata veća ili jednaka od deset ili je AF postavljen na 1. Potom se doda broj 6 na gornji polubajt, pod uslovom da je vrednost gornjeg polubajta ne manja od 10.

Na analogan način se može opisati kakve je vrste popravka koju treba uvesti pri sabiranju nepakovanih BCD brojeva, ili pri oduzimanju, množenju i deljenju. Instrukcije procesora 80386 za uvođenje popravki su:

DAA (eng. decimal adjust after adition - decimalno podešavanje posle sabiranja) - AL ® popravljen AL. Ova instrukcija u AL smešta popravljenu vrednost AL-a, da odgovara zbiru parova pakovanih BCD cifara, po prethodno izvršenom binarnom sabiranju. Dakle, ona vrši konverziju binarnog broja u odgovarajući pakovani BCD broj. Instrukcija nema operanada. Po uvođenju popravke, CF će biti postavljen ukoliko stvarno treba biti prenosa pri sabiranju pakovanih BCD cifara. U suprotnom, CF će biti obrisan. 

DAS (eng. decimal adjust after subtraction - decimalno podešavanje posle oduzimanja) - AL ® popravljen AL. Instrukcija DAS smešta u AL popravljenu vrednost AL-a, da odgovara razlici parova pakovanih BCD cifara, po prethodno izvršenom binarnom oduzimanju. Ni ova instrukcija nema operanada. Po uvođenju popravke, CF će biti postavljeno ukoliko stvarno treba biti prenosa pri oduzimanju pakovanih BCD cifara. U suprotnom, CF će biti obrisano.

Primer.

MOV AL, 75D

MOV BL, 29

ADD AL, BL

DAA

MOV AL, 75D

MOV BL, 29

SUB AL, BL

DAS

Napisati delove asemblerskog koda za sabiranje i za oduzimanje brojeva 75 i 29, i testirati njegov rad.

Množenje i deljenje BCD brojeva moguće je samo u nepakovanom obliku.

Sledeća tabela pokazuje ASCII kodove svih sekadnih cifara (vidimo da se donji polubajt ASCII koda poklapa sa vrednošću odgovarajuće dekadne cifre).

cifra

ASCII kod (heksadekadni)

ASCII kod (dekadni)

cifra

ASCII kod (heksadekadni)

ASCII kod (dekadni)

0

30H

48

5

35H

53

1

31H

49

6

36H

54

2

32H

50

7

37H

55

3

33H

51

8

38H

56

4

34H

52

9

39H

57

Dakle, prelazak između ASCII koda cifre i njenog nepakovanog BCD zapisa je krajnje jednostavan, direktan i kratkotrajan.

Očigledno je da se za slučaj nepakovanih BCD brojeva popravka radi dobijanja korektnog zbira, odnosno korektne razlike, mora izvršiti drugačije nego u pakovanom slučaju.

Stoga, za uvođenje te popravke procesor 80386 ima druge instrukcije:

AAA (eng. ASCII adjust after adition - ASCII podešavanje posle sabiranja) - AL ® popravljen AL. Ova instrukcija u AL smešta popravljenu vrednost AL-a, da odgovara zbiru nepakovanih BCD cifara, po prethodno izvršenom binarnom sabiranju. Dakle, ona vrši konverziju binarnog broja u odgovarajući nepakovani BCD broj. Instrukcija nema operanada. Po uvođenju popravke, CF će biti postavljeno ukoliko stvarno treba biti prenosa pri sabiranju pakovanih BCD cifara. U suprotnom, CF će biti obrisano. 

AAS (eng. ASCII adjust after subtraction - ASCII podešavanje posle oduzimanja) - AL ® popravljen AL. Instrukcija AAS smešta u AL popravljenu vrednost AL-a, da odgovara razlici pakovanih BCD cifara, po prethodno izvršenom binarnom oduzimanju. Ni ova instrukcija nema operanada. Po uvođenju popravke, CF će biti postavljeno ukoliko stvarno treba biti prenosa pri oduzimanju pakovanih BCD cifara. U suprotnom, CF će biti obrisano.

AAM (eng. ASCII adjust after multiplication - ASCII podešavanje posle množenja) - AX ® popravljen AX. Instrukcija AAM konvertuje binarni broj iz AX u odgovarajući dvocifren nepakovan BCD broj. Ona smešta u AX popravljenu vrednost iz AX, tako što se izvrši celobrojno deljenje broja u AL sa10, količnik se smesti u AH, a ostatak u AL. Dakle, ova instrukcija radi isto što i instrukcija deljenja, samo što se rezultati smeštaju u neke druge registre.

Primer.

Neka treba pomnožiti brojeve 9 i 4. Tada se u registar BL smesti broj 09H (MOV BL, 9), a u registar AL broj 04H (MOV AL, 4). Izvršenjem instrukcije IMUL BL dobija se 36D u registru AX, tj. 16-bitni registar AX sadrži 0024H. Jasno je da ovaj rezultat ne može da se tumači kao BCD broj. Međutim, po primeni instrukcije AAM dobija se u AL vrednost 06, a u AH 03, pa sada dva bajta registra AX sadrže cifre proizvoda u nepakovanom BCD formatu.

AAD (eng. ASCII adjust before division - ASCII podešavanje pre deljenja) - AX ® popravljen AX. Instrukcija AAM konvertuje dvocifren nepakovan BCD broj iz AX u odgovarajući binarni broj. Za razliku od prethodnih instrukcija, ovde dodavanje popravke treba izvršiti pre, a ne posle deljenja. Instrukcija AAD se izvršava tako što se vrednost iz AH pomnoži sa 10 i doda na vrednost u registru AL. Zbir se potom smesti u AX.

Primer.

Neka treba podeliti BCD brojeve 42 i 6. Dakle, količnik treba da bude 7, a ostatak 0. Tada se u registar AX smesti broj 0402H=1050D (što i predstavlja nepakovan BCD zapis broja 42D), a u registar AL broj 06H. Jasno je da će se, ukoliko se odmah izvrši deljenje, dobiti nekorektan rezultat. Popravka se uvodi izvršenjem instrukcije AAD. Po izvršenju ove instrukcije se u AX registar smešta 10*4+2=42D=002AH. Ako se sada primeni instrukcija IDIV, dobiće se korektan količnik (u registru AL) i ostatak (u registru AH).

Zadatak. Opisati sadržaj opštih registara po izvršenju svake od instrukcija u sledećem segmentu asmblerskog koda:

                        MOV AX, 8

                        ADD AL, 4

                        AAA

                        ADD AL, 04

                        AAA

                        MOV AX, 5

                        SUB AL, 4

                        AAS

                        SUB AL, 04

                        AAS

a)                                                                                 b)

 

                                                c)

MOV AX, 0805H

AAD

AAM

Logičke instrukcije

Ove instrukcije se dele u dve grupe: Bulove instrukcije i instrukcije pomeranja i rotacije.

Bulove instrukcije

Ova grupa instrukcija izvodi logičke operacije nad parovima odgovarajućih bitova operanada, a rezultat se (sem kod instrukcije TEST) smešta u odredišni operand.

AND D, S (eng. and - i) - D Ů S® D. Ova instrukcija oformljuje bitovnu konjukciju odredišnog i izvornog operanda, pa dobijeni rezultat smešta u odredišni operand.

Instrukcija AND je pogodna za brisanje specifičnih pozicija (tzv. maskiranih pozicija) u sadržaju registra: jedan operand specificira bitovne pozicije (on se često naziva maska), dok drugi operand sadrži vrednost.

Primer.

Brisanje tri bita najveće težine u bajtu se može realizovati tako što se izvrši konjukcija tog bajta i broja 00011111B. Po izvršenju instrukcije AND, biće CF=OF=0, a flegovi SF, ZF i PF biće postavljeni u skladu sa dobijenim rezultatom.

Ova instrukcija se često koristi za brisanje gornjeg polubajta (polubajta veće težine) u bajtu pre izvršenja aritmetičkih instrukcija nad nepakovanim BCD brojevima.

OR D, S (eng. or - ili) - D Ú S® D. Instrukcija OR oformljuje bitovnu disjunkciju odredišnog i izvornog operanda, pa dobijeni rezultat smešta u odredišni operand.

Instrukcija OR se koristi za postavljanje bitova na maskiranim pozicijama. U tom slučaju izvorni operand (tj. maska) će sadržati jedinice na onim bitovnim pozicijama koje se postavljaju, dok će na pozicijama koje trebaju ostati nepromenjene u maski stajati 0.

XOR D, S (eng. exclusive or - ekskluzivno ili) - D Ú S® D. Ova instrukcija oformljuje bitovnu ekskluzivnu disjunkciju (u žargonu se često umesto ekskluzivna disjunkcija koristi izraz “ksorovanje”) odredišnog i izvornog operanda, pa dobijeni rezultat smešta u odredišni operand.

Instrukcija XOR koristi se za komplementiranje bitova na maskiranim pozicijama. Tada maska sadrži jedinice na onim bitovnim pozicijama koje se komplementiraju, dok za bitovne pozicije koje trebaju ostati nepromenjene u maski stoji 0.

XOR takođe omogućuje da se na efikasan način sadržaj određenog operanda postavi na nulu.

NOT D (eng. not - ne) - ŘD ® D. Instrukcija NOT formira bitovnu negaciju odredišnog operanda i smešta je u odredište.

Dakle, instrukcija NOT komplementira svaki bit odredišta. Kako je komplementiranje bita ekvivalentno sa eksluzivnom disjunkcijom sa jedinicom, to je izvršenje komplementiranja ekvivalentno “ksorovanju” kod koga se izvorni operand sastoji isključivo od jedinica.

TEST D, S (eng. test - testiranje, provera) - D Ů S® ?. Ova instrukcija oformljuje bitovnu konjukciju odredišnog i izvornog operanda i u zavisnosti od dobijene vrednosti postavljaju se flegovi: OF i CF se brišu, vrednosti SF, ZF i PF se postavljaju sa obzirom na dobijeni rezultat.

Dakle, instrukcija TEST kombinuje osobine instrukcija AND i CMP. Kao i AND instrukcija, TEST izvodi konjukciju; a slično CMP instrukciji, rezultat se nige ne smešta, već se ažuriraju odgovarajući flegovi. Ova instrukcija je korisna za utvrđivanje da li se na specificiranim bitovnim pozicijama u odredištu nalaze nule illi jedinice.

Zadatak. Opisati sadržaj opštih registara po izvršenju svake od instrukcija u sledećem segmentu asmblerskog koda:

MOV EAX, 0F0F011EEH

AND AX, 0FFFCH

AND AX, 0F5F5H

AND AX, 3E12H

AND EAX, 00F011EEH

MOV AX, 0F1D2H

XOR AX, 11H

XOR AL 0F2H

XOR AH, AH

 

a)                                                                                 b)

 

Instrukcije pomeranja i rotacije

Dužina odredišnog operanda kod ovih instrukcija može biti 8, 16 ili 32. Izvorni operand specificira broj mesta za koje sa vrši pomeranje ili rotacija. Taj operand može biti zadat bilo neposredno, bilo pomoću registra CL. Nijedan drugi registar osim registra CL se ne može koristiti za određivanje broja mesta pri pomeranju ili rotaciji.

Instrukcije pomeranja (još se nazivaju i instrukcije šiftovanja) su:

SHL D, S (eng. shift logical left - pomeri logički ulevo) - CF ¬ D ¬ 0. Realizuje šiftovanje odredišnog operanda za određeni broj pozicija ulevo. Na mesta koja su “ispražnjena” prilikom pomeranja ulevo, smeštaju se nule. Bit koji je poslednji “izbačen” iz odredišnog operanda biva smešten u CF.

SHR D, S (eng. shift logical right - pomeri logički udesno) - 0 ® D ® CF. Realizuje šiftovanje odredišnog operanda za određeni broj pozicija udesno. Na mesta koja su “ispražnjena” prilikom pomeranja udesno, smeštaju se nule. Bit koji je poslednji “izbačen” iz odredišnog operanda biva smešten u CF.

SAL D, S (eng. shift arithmetic left - pomeri aritmetički ulevo) - CF ¬ D ¬ 0. Radi isto što i instrukcija SHL, tj. ima potpuno isto dejstvo. Različitim mnemonicima SHL i SAL odgovara isti opkod, tj. mnemonici SAL i SHL su sinonimni.

SAR D, S (eng. shift arithmetic right - pomeri aritmetički udesno) - SF ® D ® CF. Realizuje šiftovanje odredišnog operanda za određeni broj pozicija udesno. Na mesta koja su “ispražnjena” prilikom pomeranja udesno, smeštaju se nule, ako je inicijalno vrednost bita najveće težine bila nula. Međutim, ako je inicijalna vrednost bita najveće težine operanda bila jedinica, tada se “ispražnjene” pozicije popunjavaju sa jedinicama. Bit koji je poslednji “izbačen” iz odredišnog operanda biva smešten u CF.

Instrukcije pomeranja daju vrlo efikasan mehanizam za dupliranje i polovljenje celih brojeva, odnosno za njihovo množenje i deljenje stepenima dvojke. Taj mehanizam počiva na činjenici da se celi brojevi čuvaju u sistemu sa osnovom dva.

Budući da se pri pomeranju mora voditi računa o tome da li se sadržaj operanda tumači kao neoznačen ili kao označen broj, to se razlikuju logičko pomeranje (ne vodi računa o znaku) i aritmetičko pomeranje (vodi računa o znaku operanda). Uočava se da se razlikuju samo aritmetičko i logičko pomeranje u desnu stranu.

Polovljenje negativnih brojeva instrukcijom SAR ne mora dati isti rezultat kao celobrojno deljenje tog istog broja sa brojem 2.

Primer.

MOV AL, -5

MOV BL, 2

IDIV BL

MOV AL, -5

SAR AL, 1

 

Pokazuje da se aritmetičkim šiftovanjem broja -5 za jedno mesto udesno ne dobija isto kao pri celobrojnom deljenu tog istog broja sa 2.

Po izvršenju segmenta asemblerskog koda na levoj strani, u AL će se nalaziti vrednost -3, a po izvršenju koda na desnoj strani, AL će sadržati -2.

Instrukcije rotacije obezbeđuju mogućnost rearanžiranja redosleda bitova. U instrukcije rotacije spadaju:

ROL D, S (eng. rotate left - rotiraj ulevo) -  Realizuje rotaciju odredišnog operanda za određeni broj pozicija ulevo.

ROR D, S (eng. rotate right - rotiraj udesno) - . Realizuje rotaciju odredišnog operanda za određeni broj pozicija udesno.

RCL D, S (eng. rotate through carry left - rotiraj kroz fleg prenosa ulevo) - . Rotira odredišni operand zajedno sa flegom prenosa za određeni broj pozicija ulevo.

RCR D, S (eng. rotate through carry right - rotiraj kroz fleg prenosa udesno) - . Rotira odredišni operand zajedno sa flegom prenosa za određeni broj pozicija udesno.

Pored prethodno pobrojanih, u instrukcije šiftovanja i rotacije spadaju i SHLD i SHRD. Ove instrukcije se koriste za premeštanje blokova dužine do 64 bita, tj. koriste se za efikasan transfer bitova. One postoje samo kod procesora 80386 i njegovih potomaka i njihov rad je usko vezan sa instrukcijama za rad sa bitovnim nizovima. Stoga će instrukcije SHLD i SHRD biti obrađene kasnije, kada se bude opisivao rad procesora 80386 sa nizovima bitova.

Instrukcije za rad sa niskama

Niska (eng. string) je sekvenca bajtova, reči ili dvostrukih reči u memoriji. Pored naziva niska, kod nas je u širokoj upotrebi i naziv string. Operacije nad niskama su operacije koje se izvode nad svakim elementom niske.

Skup instrukcija procesora 80386 bitno umanjuje vreme potrebno za izvršenje instrukcije nad niskama. To ubrzanje je postignuto pomoću:

1) formiranja moćnog skupa primitivnih instrukcija (tzv. niska-primitive ili string-primitive)

2) eliminisanja potrebe za održavanjem i zaglavljem koji se obično izvode između obrađivanja uzastopnih članova.

Elementarne instrukcije za rad sa niskama

Da bi se ilustrovalo kako instrukcije za rad sa niskama ubrzavaju obradu niski, razmotrimo postupak za premeštanje neke sekvence bajtova.

Primer.

Neka neku nisku bajtova treba prebaciti sa jedne na drugu lokaciju u memoriji. Potrebno je na neki način označiti gde su bajtovi sada i gde bi trebali da budu. Neka se za tu svrhu koriste ESI i EDI. Neka na početku ESI pokazuje na prvi bajt u niski koji treba premestiti, dok EDI pokazuje na mesto na koje niska odlazi. Registar ECX će sadržati broj elemenata (u ovom slučaju broj bajtova) koji se premeštaju. Koraci pri izvršenju premeštanja su sledeći:

1. ?ECX=0, ako da kraj

2. dohvati bajt na koji ukazuje ESI

3. smesti bajt u lokaciju na koju pokazuje EDI

4. uvećaj ESI za 1

5. uvećaj EDI za 1

6. umanji ECX za 1

7. idi na korak 1

Uočava se da su kod ovog algoritma koraci 4-6predstavljaju održavanje, a da korak 7 predstavlja zaglavlje. Može se oformiti sekvenca asemblerskih instrukcija kojom se realizuje ovaj algoritam, tako da svakom od koraka algoritma odgovara tačno jedna asemblerska instrukcija. Ali, to nije najbrži način za realizaciju ovog algoritma na asemblerskom jeziku.

Kod familije INTEL-ovih procesora uvode instrukcije kod kojih su koraci 2 i 3, te koraci održavanja 4 i 5 hardverski realizovani. Dakle, izvršenjem jedne instrukcije se izvrše koraci 2, 3, 4 i 5 iz algoritma u prethodnom primeru.

Takve instrukcije, tj. niska-primitive su:

MOVS (eng. move string element - premesti elemenat niske) - [ESI]®[EDI], i ažuriraju se vrednosti u ESI, EDI. Dakle, primitiva prenosa premešta elemenat niske na koji pokazuje ESI u lokaciju na koju pokazije EDI, uz ažuriranje sadržaja registara ESI i EDI.

CMPS (eng. compare string elements - uporedi elemente niski) - računa se [ESI]-[EDI], u zavisnosti od rezultata se postavljaju flegovi, i ažuriraju se vrednosti u ESI, EDI. Dakle, primitiva poređenja upoređuje elemenat niske na koji pokazuje ESI sa elementom koju pokazije EDI, uz ažuriranje sadržaja registara ESI i EDI.

SCAS (eng. scan string element - skeniraj elemenat niske) - računa se akumulator-[EDI], u zavisnosti od rezultata se postavljaju flegovi, i ažurira se vrednost u EDI. Dakle, primitiva skeniranja elemenat niske na koji pokazuje EDI poredi sa vrednošu u akumulatoru, uz ažuriranje sadržaja registra EDI.

INS (eng. input string element - unesi elemenat niske) - ulazni port ®[EDI], i ažurira se vrednost u EDI. Dakle, primitiva unosa sa ulaznog porta specificiranog registrom DX premešta elememenat niske u lokaciju na koju pokazuje EDI, uz ažuriranje sadržaja registra EDI.

OUTS (eng. output string element - pošalji elemenat niske) - [ESI] ® izlazni port, i ažurira se vrednost u ESI. Dakle, primitiva odašiljanja šalje elememenat niske na koji pokazuje ESI u izlazni port specificiran registrom DX, uz ažuriranje sadržaja registra ESI.

STOS (eng. store string element - smesti elemenat niske) - akumulator ®[EDI], i ažurira se vrednost u EDI. Dakle, primitiva smeštanja premešta elememenat niske u lokaciju na koju pokazuje EDI u akumulator, uz ažuriranje sadržaja registra EDI.

LOADS (eng. load string element - uzmi elemenat niske) - [ESI] ® akumulator, i ažurira se vrednost u ESI. Dakle, primitiva uzimanja prenosi elememenat niske na koji pokazuje ESI u akumulator, uz ažuriranje sadržaja registra ESI.

Termin akumulator označava registrar AL, AX, EAX, u zavisnosti od toga da li se operacija skeniranja vrši nad bajtovima, rečima ili dvostrukim rečima.

Ove instrukcije nemaju operande. One manipulišu sa bitovnim niskama dužine 8, 16 ili 32. Postoje posebni opkodovi i posebni mnemonici za svaku od ovih istrukcija i fiksiranu veličinu bitovnog niza. Naime mnemonik sa sufiksom B eksplicitno označava da se niska primitiva vrši nad bajtovima, mnemonik sa sufiksom W označava da instrukcija operiše sa rečima, dok mnemonik sa sufiksom D označava da se radi o string primitivi nad dvostrukim rečima. Tako, pored već pobrojanih niska-primitiva, kod procesora 80386, postoje i instrukcije MOVSB, MOVSW, MOVSD, CMPSB, CMPSW, CMPSD, SCASB, SCASW, SCASD, INSB, INSW, INSD, OUTSB, OUTSW, OUTSD, STOSB, STOSW, STOSD, LODSB, LODSW, LODSD.

Preciznije rečeno, instrukcije kod kojih nije eksplicitno specificirana dužina elementa niske se tokom asembliranja svode na neku od prethodno popisanih instrukcija.

Prefiksi ponavljanja

Da bi se ilustrovao značaj i način korišćenja prefiksa ponavljanja, ponovo razmotrimo postupak za premeštanje neke sekvence bajtova.

Primer.

Neka neku nisku bajtova treba prebaciti sa jedne na drugu lokaciju u memoriji. Neka na početku ESI pokazuje na prvi bajt u niski koji treba premestiti, dok EDI pokazuje na mesto na koje niska odlazi. Registar ECX će sadržati broj elemenata (u ovom slučaju broj bajtova) koji se premeštaju. Sada, kada raspolažemo sa primitivom prenosa, koraci pri izvršenju premeštanja će biti:

1. ?ECX=0, ako da - kraj

2. izvrši primitivu prenosa

3. umanji ECX za 1

4. idi na korak 1

Uočavamo da se opet može oformiti sekvenca asemblerskih instrukcija kojom se realizuje ovaj algoritam, tako da svakom od koraka algoritma odgovara tačno jedna asemblerska instrukcija. Tako napravljen asemblerski kod radio brže od asemblerskog koda iz prethodnog primera.

Koraci 1,3 i 4 se mogu eliminisati, jer je primitiva prenosa pomeša sa testiranjem, umanjivanjem i ponavljanjem baziranim na ECX, a sve to se može postići pomoću prefiksa ponavljanja REP.

REP (eng repeat - ponavljanje) - ukazuje da se primitiva ponavlja ECX puta.

Primer.

Algoritam iz prethodnog primera realizuje se jednom instrukcijom: REP MOVS.

Kao što je već istaknuto, niska-primitive mogu da se izvršavaju nad bajtovima, rečima ili dvostrukim rečima. Primitiva prenosa kod reči i dvostrukih reči radi slično kao primitiva prenosa kod bajtova, s tim što se EDI i ESI ne uvećavaju (odnosno umanjuju) za 1, već za 2 (kod reči) ili za 4 (kod dvostrukih reči).

Primer.

MOV ESI, OFFSET MEM_DWORD1

MOV EDI, OFFSET MEM_DWORD2

MOV ECX, DWORDS_BROJ

REP MOVS

MOV ESI, OFFSET MEM_WORD1

MOV EDI, OFFSET MEM_WORD2

MOV ECX, WORDS_BROJ

REP MOVS

Ilustruje zajedničko korišćenje niska-primitiva i prefiksa ponavljanja:

MOV ESI, OFFSET MEM_BYTE1

MOV EDI, OFFSET MEM_ BYTE2

MOV ECX, BYTES_BROJ

REP MOVS

Asembler će na osnovu konteksta da odredi broj bitova kod elementa niske i da u objekt datoteci generiše ispravan opkod. Naravno, moguće je koristiti i mnemonike koji tačno specificiraju veličinu operanda, tj. umesto REP MOVS koristiti REP MOVSB ili REP MOVSW ili REP MOVSD

Prilikom premeštanja podataka može se javiti problem ako se prostor koji na početku zauzima niska preklapa sa prostorom koji niska treba zauzeti posle premeštanja.

Primer.

Kao što se vidi, bajt iz lokacije 100 se kopira u lokaciju 102, pa u 104, itd. Na taj način je originalni sadržaj lokacija 102 i 104 uništen.

 

 

Ponekad je preklapanje poželjno, npr. kada ponavljajući obrazac bajtova mora smestiti u memoriju. Ali, jasan je značaj pravca prenošenja bajtova i potreba da se nekad prenos vrši unapred, a nekad unazad.

Registar flegova procesora 80386 sadrži DF (fleg pravca), koji upravlja pravcem obrade niski. Ako je DF=0, niske će se obrađivati od početka prema kraju, tj. ESI i EDI će se pri radu uvećavati. Ako je DF=1, onda se obrada vrši otpozadi, pa se ESI i EDI umanjuju. Ažuriranje registara ESI i EDI, koje se pominje u opisu niska-primitiva, se svodi na jednu od sledećih operacija: uvećanje za 1 (ako se radi sa bajtovima i DF=0), uvećanje za 2 (ako se radi sa rečima i DF=0), uvećanje za 4 (ako se radi sa dvostrukim rečima i DF=0), umanjenje za 1 (ako se radi sa bajtovima i DF=1), umanjenje za 2 (ako se radi sa rečima i DF=1) i umanjenje za 4 (ako se radi sa dvostrukim rečima i DF=1).

Dakle, kada je EDI<ESI a prostor koji zauzima izvorna niska se preklapa sa prostorom koji će zauzimati odredišna niska, prenos treba izvršiti unapred. Kada je EDI>ESI a prostor koji zauzima izvorna niska se preklapa sa prostorom koji će zauzimati odredišna niska, prenos treba izvršiti unazad.

Instrukcije kojima se postavlja, odnosno briše, registar flegova DF će biti razmatrane kasnije - u paketu sa ostalim instrukcijama za rad sa flegovima.

Razmotrimo sad drugu operaciju nad niskama: skeniranje niske u potrazi za bilo kojom vrednošću različitom od zadate.

Primer.

Neka treba naći prvi elemenat u datom nizu bajtova koji ima zadatu vrednost. Neka se ta zadata vrednost nalazi u registru AL. Neka EDI pokazuje na nisku i neka ECX sadrži broj bajtova u sekvenci.  Koraci algoritma za izvršenje skeniranja su

1. ?ECX=0, ako da - kraj

2. uporedi AL sa bajtom na koji pokazuje EDI

3. uvećaj (umanji ako je DF=1) EDI za 1

4. umanji ECX za 1

5. ?ZF=1, ako da - nađen bajt, ako ne - idi na korak 1

Uočava se da je kod ovog algoritma “u igri” i nula fleg ZF, tj. tokom skaniranja se testira postavljenje nula flega.

Kod procesora 80386, stoga, postoje prefiksi ponavljanja koji tokom ponavljanja primitive testiraju vrednost nula flega. Način testiranja vrednosti nula flega je određen nazivom prefiksa ponavljanja. Dakle, prefiks ponavljanja mora iskazati koja od vrednosti ZF izaziva ponavljanje.

Mnemonici za ova ponavljanja su:

REPZ (eng repeat while ZF is set- ponavljanje sve dok je nula fleg postavljen) - ukazuje da se primitiva ponavlja sve dok je ZF=1, a najviše ECX puta.

REPE (eng repeat while equal- ponavljanje sve dok je jednako) - ukazuje da se primitiva ponavlja sve dok su prethodno upoređeni elementi jednaki, a maksimalno ECX puta. Ovaj prefiks ponavljanja je sinoniman prefiksu REPZ.

REPNZ (eng repeat while not ZF is set- ponavljanje sve dok nije nula fleg postavljen) - ukazuje da se primitiva ponavlja sve dok je ZF=0, a najviše ECX puta.

REPNE (eng repeat while not equal- ponavljanje sve dok nije jednako) - ukazuje da se primitiva ponavlja sve dok su prethodno upoređeni elementi različiti, a maksimalno ECX puta. Ovaj prefiks ponavljanja je sinoniman prefiksu REPNZ.

Primer.

Algoritam iz prethodnog primera realizuje se jednom instrukcijom:

REPNZ SCAS.

Kako se u prošlom primeru radilo o skeniranju niske bajtova, to se gornja instrukcija može zameniti sa nešto eksplicitnijim:

REPNZ SCASB.

Razmotrimo sad operaciju poređenja niski. U tom slučaju, neophodno je odrediti poziciju prvog elementa na kom se dve niske razlikuju.

Primer.

Neka treba za dva data niza bajtova jednake dužine odrediti na kojoj se poziciji te niske počinju razlikovati. Neka ESI pokazuje na prvu, a EDI na drugu nisku, i neka ECX sadrži broj bajtova u njoj. Koraci algoritma su:

1. ?ECX=0, ako da - kraj

2. dohvati bajt na koji pokazuije ESI

3. uporedi sa bajtom na koji ukazuje EDI

4. ažuriraj ESI

5. ažuriraj EDI

6. umanji ECX za 1

7. ?ZF=1, ako da - idi na 1

Ovaj algoritam se realizuje jednom instrukcijom:

REPZ CMPS

ili

REPZ CMPSB.

Primećuje se da se na ovaj način prešlo preko pozicije na kojoj se elementi razlikuju, ali da su na ovaj način flegovi postavljeni upravo tako da odslikavaju leksikografski poredak prve i druge niske.

Kompleksne instrukcije za rad sa niskama

Nisu napravljene, niti je moguće napraviti, primitive za realizaciju svake od potreba koja može iskrsnuti pri radu sa niskama. Tako se neke druge operacije moraju realizovati kao sekvenca više asemblerskih instrukcija.

Primer.

Neka treba komplementirati elemente datog niza bajtova i prepisati ih na neko drugo mesto u memoriji. Neka ESI pokazuje na nisku koja se komplementira i prepisuje, a EDI na lokaciju u memoriji od koje se trebaju smestiti bajtovi niske, i neka ECX sadrži broj bajtova u njoj. Koraci algoritma su:

1. ?ECX=0, ako da - kraj

2. dohvati bajt na koji pokazuije ESI

3. komplementiraj dohvaćeni bajt

4. smesti bajt u lokaciju na koju pokazuje EDI

5. ažuriraj ESI

6. ažuriraj EDI

7. umanji ECX za 1

8. ?ECX=0, ako ne - idi na 2

Analogno prethodnim primerima, bilo bi logično koristiti primitivu koja bi izvršila korake 2, 3, 4, 5, 6. Međutim, takva primitiva ne postoji! Prirodno je i logično da ne mogu postojati primitive za sve potrebe.

Primer.

Za rešavanje problema postavljenog u prethodnom primeru koraci 2 i 5 mogu biti zamenjeni sa load primitivom, koraci 4 i 6 sa store primitivom, a korak 3 sa instrukcijom NEG. Ovo prethodni algoritam uprošćava na:

1. ?ECX=0, ako da - kraj

2. izvrši load primitivu

3. komplementiraj bajt u AL-u

4. izvrši store primitivu

5. umanji ECX za 1

6. ?ECX=0, ako ne - idi na 2

Koraci 1, 5 i 6 su u prethodnim primerima bili obezbeđeni mešanjem string primitive sa prefiksom ponavljanja. Kako se u ovom slučaju telo petlje sastoji od više instrukcija, to prefiks ponavljanja ne može biti korišćen.

Dakle, neophodno je postojanje efikasnih instrukcija koje će simulirati kompleksne akcije prefiksa ponavljanja.

Analiza prethodnog primera ukazuje na željene osobine koje bi trebalo da imaju te nove instrukcije.

Korak 1 zahteva postojanje takvog uslovnog prelaska, da se skok izvršava u slučaju kada je ECX=0. Odredište skoka bi trebalo da bude specificirano u što je moguće manje bitova.

JECXZ D (eng. jump if ECX is zerro - skoži ukoliko je ECX nula) - izvršava skok na labelu datu odredišnim operandom ukoliko je ECX nula.

JCXZ D (eng. jump if CX is zerro - skoži ukoliko je CX nula) - izvršava skok na labelu datu odredišnim operandom ukoliko je sadržaj registra CX nula.

Odredište skoka je enkodira u jednom bajtu instrukcije. Taj bajt sadrži označen broj koji predstavlja rastojanje (u bajtovima) od J(E)CXZ instrukcije do odredišta. Iz ovoga je jasno da je odredište J(E)CXZ instrukcije specificirano neposredno.

Koraci 5 i 6 zahtevaju da postoji i instrukcija koja umanjuje ECX i potom skače ukoliko ECX nije nula.

LOOP D (eng. loop - petlja) - umanjuje ECX i potom izvršavanje prelazi na neposredno zadato odredište ukoliko ECX nije nula.

Odredište prelaska (skoka) u LOOP instrukciji je specificirano na isti način kao i kod JECXZ instrukcije.

Primer.

Algoritam iz prethodnog primera može da se realizuje i na sledeći način:

1. JECXZ preko sledećih koraka

2. izvrši load primitivu

3. komplementiraj bajt u AL-u

4. izvrši store primitivu

5. LOOP nazad na 2

Kako u ovom algoritmu svaki korak predstavlja jednu instrukciju, to se algoritam može predstaviti sledećom sekvencom naredbi:

            JECXZ DALJE

PETLJA:

            LODS

            NEG AL

            STOS

            LOOP PETLJA

DALJE:

Uočava se da dejstvo prethodno uvedena LOOP instrukcije zavisi isključivo od sadržaja registra ECX. Međutim, već je istanuto da je kod nekih operacija za rad sa niskama poželjno da se odluka o ostanku u petlji donese i na osnovu postavljenja flega ZF.

LOOPZ D (eng loop while ZF is set- petlja sve dok je nula fleg postavljen) - umanjuje se ECX i realizuje prelazak izvršavanja na labelu specificiranu odredištem ako je ZF=1 i ECX<>0.

LOOPE D (eng loop while equal - petlja sve dok je jednako) - umanjuje se ECX i vrši se prelazak na labelu specificiranu odredištem ako su prethodno upoređeni elementi jednaki i ECX<>0. Ova instrukcija je sinonimna instrukciji LOOPZ.

LOOPNZ D (eng loop while not ZF is set- petlja sve dok nije nula fleg postavljen) - umanjuje se ECX i realizuje prelazak izvršavanja na labelu specificiranu odredištem ako je ZF=0 i ECX<>0.

LOOPNE D (eng loop while not equal - petlja sve dok je različito) - umanjuje se ECX i vrši se prelazak na labelu specificiranu odredištem ako su prethodno upoređeni elementi različiti i ECX<>0. Ova instrukcija je sinonimna instrukciji LOOPNZ.

Primer.

            0          0000    0000

            1          0001    0001

            2          0010    0011

            3          0011    0010

            4          0100    0110

            5          0101    0100

            6          0110    0101

            7          0111    0111

            8          1000    1111

            9          1001    1110

            10        1010    1100

            11        1011    1101

            12        1100    1001

            13        1101    1011

            14        1110    1010

            15        1111    1000

Vrši se konverzija niza brojeva iz intervala između 0 i 15 u odgovarajući Grejov kod, te njihov prepis u neku drugu lokaciju. Grejov kod (tj. jedna njegova varijanta) data je sledećom tabelom:

Kao što se i može videti iz prethodne tabele, osnovna osobina Grejovog koda je da se bitovni zapisi susednih brojeva razlikuju na tačno jednom bitovnom mestu. Neka sekvenca bajtova, koja sadrži binarne brojeve između 0 i 15, počinje od memorijske lokacije MEMBYTE1. Neka je broj bajtova u sekvenci koji treba konvertovati sadržan u registru ECX, i neka je MEMBYTE2 lokacija počev od koje treba smestiti konvertovane bajtove. Nadalje, neka je GRAY niz bajtova koji sadrži tabelu Grejovih kodova.

Tada su koraci kojima se realizuje konverzija i prenos sledeći:

            MOV ESI, OFFSET MEMBYTE1

            MOV EDI, OFFSET MEMBYTE2

            MOV EBX, OFFSTE GRAY

            JECX GOTOVO

PETLJA:

            LODS

            XLATB

            STOS

            LOOP PETLJA

GOTOVO:

Instrukcije bezuslovnog prelaska

Glavni tipovi instrukcija bezuslovnog prelaska procesora 80386 su skokovi, pozivi i vraćanja.

JMP D (eng. jump - skok) - D ® EIP. Naredba bezuslovnog skoka učitava vrednost odredišta u brojač naredbe EIP i na taj način prekida se sekvencijalno izvršavanje instrukcija.

CALL D (eng call - poziv) - D ® stek, D ® EIP. Naredba poziva radi isto što i naredba skoka, ali prvo se gurne tekuća vrednost brojača naredbe EIP na stek, tako da se, u nekom trenutku u budućnosti, izvršavanje može nastaviti od mesta gde je bilo prekinuto.

RET D (eng return - povratak) - stek ® EIP; ako je specifcirano D, D+ESP ® ESP. Naredba vraćanja se dešava u tom trenutku u budućnosti. Ona uklanja prethodno gurnuti elemenat sa steka i uklonjenu vrednost smešta u brojač naredbi EIP.

Operandi instrukcija skokova i poziva javljaju se kao direktni i indirektni. Najveći broj je direktan i direktno specificiran operand odmah kaže gde se izvršavanje nastavlja. Indirektni prelazak se ređe koristi, npr. indirektan prelazak je od koristi kada se ne zna gde će se nastaviti izvršavanje, već se to mora prvo izračunati.

Primer.

Indirektan skok

JMP NIZ[EBX*4]

dohvata odredište iz niza NIZ u memoriji koji je indeksiran pomoću EBX registra (sa faktorom skaliranja 4).

[to se načina izvršavanja svih instrukcija tiče, prvo se kod svih njih uveća EIP, kako bi pokazivalo na sledeću naredbu. Da bi dizajn procesora ostao jednostavan, uvećavanje EIP će se izvršavati i kod ovih instrukcija prelaska - iako izvršenjem instrukcija prelaska sadržaj EIP biva ponovo modifikovan.

Koraci JMP instrukcije su:

1) Uvećava se sadržaj registra EIP;

2) U registar EIP se smešta vrednost odredišnog operanda.

Koraci CALL instrukcije su:

1) Uvećava se sadržaj registra EIP;

2) Prethodno povećana vrednost EIP se gura na stek;

3) U registar EIP se smešta vrednost odredišnog operanda.

Koraci RET instrukcije su:

1) Uvećava se sadržaj registra EIP;

2) U registar EIP se smešta vrednost skinuta sa steka.

Direktni skokovi i pozivi ne specificiraju odredište eksplicitno, već kao razliku, tj. rastojanje od odredišta skoka do tekuće pozicije. Ukoliko je rastojanje (iskazano u bajtovima) toliko da se može smestiti u 8 bitova (što je vrlo čest slučaj), onda se može koristiti kraći oblik instrukcije skoka. Taj kraći oblik instrukcije je za tri bajta kraći od regularnog oblika. U tom slučaju (kao i u svim ostalim) se prvo uveća EIP, pa se odredište računa tako što se na prethodno već uvećanu vrednost EIP dodaje pomeranje tj. razlika. Tako, razlika nije razlika od odredišta do instrukcije bezuslovnog skoka, već od odredišta do instrukcije koja neposredno sledi iza instrukcije bezuslovnog skoka.

Pri asemblerskom programiranju ne mora da se računa razlika tj. rastojanje, već se (korišćenjem simboličkih imena adresa) ostavlja asembleru da sam razreši ova pitanja.

Kod indirektnih skokova i poziva se, naravno, ne koriste relativna pomeranja, jer indirektni operand samo ukazuje gde se nalazi odredište.

[to se instrukcije vraćanja tiče, uočava se da postoji varijanta ove instrukcije koja, posle obnavljanja brojačan naredbi EIP skidanjem njegove vrednosti sa steka, dodaje konstantu (neposredno specificiranu odredišnim operandom) na pokazivač steka ESP. Ovim se postiže efekat skidanja i uništavanja dodatnih elemenata na steku. Takvi elementi su se mogli naći na steku odmah po izvršenju CALL instrukcije i služiti za prenos parametara iz pozivajuće procedure. Kad procedura završi sa radom i kad usledi povratak, te vrednosti više neće biti potrebne, pa se ovaj oblik instrukcije vraćanja predstavlja uobičajen način da procedura poništi svoje parametre.

Instrukcija vraćanja u varijanti povratka i poništenja koristi 16 bitova za smeštaj neposredno zadatog operanda, tj. za smeštaj vrednosti koja se treba dodati na ESP. Na odluku o ovakvom efektu instrukcije vraćanja je presudno uticalo to što, iako je za specificiranje broja bajtova koji se skidaju sa steka najčešće dovoljan jedan bajt, slučaj kada jedan bajt nije dovoljan za smeštaj operanda postaje izuzetno nezgodan za rad.

Primer.

CALL PROGLOK

CALL [EBX]

CALL MEMDWORD

JMP PROGLOK

JMP [EBX]

JMP MEMDWORD

Raznovrsni načini korišćenja instrukcija skoka, poziva i vraćanja:

RET

RET 17

Podprogrami

Podprogram (još se koristi i izraz procedura) na asemblerskom jeziku je, jednostavno, sekvenca asemblerskih instrukcija u kojoj prva ima simboličko ime (labelu), a kod koje je poslednja instrukcija instrukcija povratka.

Primer.

Procedura za sabiranje registara AX, BX, CX i DX je:

zbir_regist:

            MOV SI, 0

            ADD SI, AX

            ADD SI, BX

            ADD SI, CX

            ADD SI, DX

            RET

Izračunati rezultat je, kao što se vidi, smešten u registru SI. Ovako oformljena procedura bi se mogla pozvati na sledeći način:

MOV AX, 0

MOV BX, 0

MOV CX, 0

MOV DX, 1

CALL zbir_regis ;SI ce biti postavljen na 1

MOV AX, 2

CALL zbir regis ;SI ce biti postavljen na 3

MOV BX, 3

MOV CX, 4

CALL zbir regis ;SI ce biti postavljen na 10D

Sledeći dijagram opisuje tok izvršavanja jednog dela prethodnog asemblerskog programa:

 

Bliski i daleki pozivi i vraćanja

Primena instrukcija CALL i RET u prethodno urađenom primeru je unutarsegmentna primena CALL i RET instrukcija.

Međutim, dosta često se procedure u jednom segmentu pozivaju iz drugog memorijskog segmenta. Instrukcije međusegmentnih poziva i povrataka se na nivou objektnog koda razlikuju od unutarsegmentnih poziva i povrataka.

Da bi asembler unapred znao da li se poziv pretvara u međusegmentni, potrebno je da programer koji želi da radi sa više segmenata mora da zatvori svaki deo koda tako da asembleru bude očigledno šta je međusegmentno (eng. far - daleko), a šta je unutarsegmentno (eng. near - blisko).

Primer.

PODPROGRAM PROC NEAR

            MOV AX, 4

            INC BX

           

RET

PODPROGRAM ENDP

PODPROGRAM:

            MOV AX, 4

            INC BX

           

RET

Uočimo sedeće podprograme:

PODPROGRAM PROC FAR

MOV AX, 4

INC BX

RET

PODPROGRAM ENDP

Svaki od ovih tri podprograma prilikom asemliranja dovode do istog objektnog koda, s tim što će u prvom i drugom slučaju instrukcija RET biti unutarsegmentna, dok će u trećem slučaju biti generisana međusegmentna instrukcija povratka.

Napomena.

Razlika između unutarsegmentne i međusegmentne instrukcije može se videti i pri radu sa dibagerom.

Uloga steka kod podprograma

Najjednostavniji način za prenos parametara između pozivajuće i pozvane procedure je preko opštih registara: pre poziva procedure parametri se smeste u opšte registre, a po povratku u pozivajuću proceduru izmenjeni sadržaji registara predstavljaju vrednosti izlaznih parametara. Pri ovakvom prenosu parametara, opšti registri mogu sadržati bilo vrednosti parametara, bilo adrese parametara. Ovim putem se argumenti relativno lako prenose, ali problem je relativno mali broj registara opšte namene.

Pojavljuje se još jedan problem: treba podržati kreiranje i rad sa rekurzivnim procedurama. Već je poznato da programi na višim programskim jezicima imaju mogućnost za smeštaj parametara i lokalnih promenljivih procedure tako da ne mođe doći do uništenja (ili oštećenja) starih vrednosti zato što se pre kraja izvršenja procedure pozvala neka druga, ili čak ista procedura, eventualno sa drugim parametrima.

Dakle, procesor i asemblerski jezik moraju imati i mogućnost prenosa parametara i smeštaja lokalnih promenljivih tako da se uspešno mogu kreirati rekurzivne procedure. Tu se pri svakom pozivu procedure treba alocirati memorija za parametre i lokalne promenljive. Niz memorijskih lokacija koji služi u ovu svrhu se naziva aktivacijski slog. Kako kompajleri aktivacijski slog obično drže na steku, to se ponegde u literaturi aktivacijski slog još naziva i stek-okvir (eng. stack-frame).

Uloga steka pri prenosu parametara

Način korišćenja steka u mehanizmu poziva neke procedure i povratka u pozivajuću proceduru direktno prizilazi iz efekata CALL i RET instrukcija. Jednostavnije iskazano, pri izvršenju instrukcije CALL se na vrhu steku sačuva adresa instrukcije koja neposredno sledi iza instrukcije poziva (tj. adresa povratka), sve dok se ne izvrši instrukcija povratka RET. Da bi se korektno vratilo u pozivajuću proceduru, potrebno je da se u trenutku izvršenja instrukcije RET na vrhu steka nalazi adresa povratka.

U slučaju kada se vrednosti parametara (bilo ulaznih, bilo izlaznih) prenose preko steka, potrebno je da se te vrednosti gurnu na stek neposredno pre poziva procedure. Postavlja se pitanje: na koji način će pozvana procedura pristupiti njenim parametrima?

Napomena.

Korišćenje neke od varijanti POP instrukcija neće dati zadovoljavajući rezultat - pojavljuje se previše komplikacija. Jer, sa steka biva skinuta adresa povratka, koja potom treba biti sačuvanana na nekom drugom mestu, a po “uzimanju” parametara ta adresa treba biti ponovo gurnuta na stek - kako bi korektno funkcionisala instrukcija RET. Sadržaj stek-memorije pri pozivu neke procedure prikazan je na sledećem dijagamu:

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

(E)SP®

 

 

adresa

 

 

 

 

povratka

 

 

 

 

parametrri

 

 

...

 

procedure

 

 

 

 

 

 

 

 

 

elementi na

 

 

 

 

steku pre

 

 

...

 

poziva

Uobičajen je, dakle, drugi mehanizam: procedura će vrednostima parametara pristupati korišćenjem registra pokazivač baze (E)BP. Taj registar se postavi tako da pokazuje na vrh steka, a potom se (adresiranjem baza+pomeraj) lako radi sa parametrima.

Primer.

Sledeća instrukcija učitava u AX reč čija je adresa BP.

MOV AX, [BP]

Instrukcija

MOV AX, [BP+2]

učitava u AX reč čija je adresa određena zbirom vrednosti BP i 2.

Primer.

Sledeći dijagram prikazuje korišćenjeregistra (E)BP za pristup parametrima procedure:

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

(E)BP, (E)SP®

 

 

adresa

 

 

 

 

povratka

 

[BP+2]:

 

 

 

 

 

 

 

 

 

[BP+4]:

 

 

parametri

 

 

 

 

procedure

 

[BP+6]:

 

 

 

 

 

 

 

 

 

 

...

 

 

Gornji dijagram je korektan samo ukoliko su sadrtžaji registara (E)BP i (E)SP jednaki.

Još se postavlja pitanje kako sa steka skinuti elemente koji su na njega gurnuti pre poziva procedure. To se najlakše, najjednostavnije i najbrže radi korišćenjem instrukcije RET X. Ta instrukcija na uobičajen način izvrši povratak, a zatim uveća (E)SP za X.

Primer.

Dijagram prikazuje efekat izvršenja instrukcije RET X:

Početno stanje

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

(E)SP®

 

 

adresa

 

 

 

 

povratka

 

n:

 

 

parametri

 

 

...

 

procedure

 

 

 

 

 

 

n+X

 

 

elementi na

 

 

 

 

steku pre

 

 

...

 

poziva

RET X

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

n:

 

 

 

 

 

...

 

 

 

 

 

 

 

 

(E)SP®

 

 

elementi na

 

 

 

 

steku pre

 

 

...

 

poziva

Uloga steka za smeštaj lokalnih promenljivih

Veoma često je neophodno da se lokalni parametri procedure smeštaju na stek. Na ovaj način procedura postaje nezavisnija u svom radu. Kod rekurzivnih procedura, zbog očiglednih razloga, i nije moguće smeštati lokalne parametre u fiksne memorijske lokacije, a istovremeno se zahteva da se u okviru te procedure lokalnim parametrima pristupa na uniforman način.

Stoga se lokalne promenljive procedure čuvaju na steku, i to neposredno iznad aktuelnog vrha steka u trenutku poziva procedure.

Primer.

Dijagram prikazuje prostor u kom treba smestiti lokalne promenljive:

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

lokalne

 

 

...

 

promeljive

 

 

 

 

procedure

 

(E)SP®

 

 

adresa

 

 

 

 

povratka

 

 

 

 

parametri

 

 

...

 

procedure

 

 

 

 

 

 

 

 

 

elementi na

 

 

 

 

steku pre

 

 

...

 

poziva

Da bi smeštaj lokalnih parametara na stek bio korektno izvršen, potrebno je da se odmah po ulasku u proceduru veličina registra (E)SP umanji za broj bajtova koje zauzimaju lokalne promenljive, i na taj način preduprredi eventualno “gaženje” vrednosti lokalnih promenljivih sa novogurnutim vrednostima. Naravno, neposredno pre povratka u pozivajuću proceduru treba vrednost (E)SP uvećati za istu vrednost za koju je bila prethodno umanjena.

Sam pristup lokalnim promenljivima se obično izvodi preko registra (E)BP - potpuno analogno pristupu parametrima procedure (s tim što se umesto uvećanja vrednosti (E)BP vrši njeno umanjenje).

Primer.

Sledeći dijagram prikazuje korišćenjeregistra (E)BP za pristup lokalnim promenljivama procedure:

 

 

...

 

 

 

 

 

 

 

 

 

 

 

 

 

(E)SP®[BP-6]:

 

 

 

 

 

 

 

lokalne

 

[BP-4]:

 

 

promenljive

 

 

 

 

procedure

 

[BP-2]:

 

 

 

 

 

 

 

 

 

(E)BP ®

 

 

adresa

 

 

 

 

povratka

 

 

...

 

 

Naravno, gornji dijagram je korektan samo ukoliko su sadrtžaji registara (E)BP i (E)SP postavljeni kao na slici.

Instrukcije uslovnog skoka

Procesor 80386 obezbeđuje instrukcije uslovnog skoka koje, zajedno sa instrukcijama poređenja, realizuju prelaske na osnovu odnosa dva broja.

Ovo se radi u dva koraka:

- porede se brojevi tako što se oformi njihova razlika i u zavisnosti od te razlike postave se flegovi;

- izvršava se instrukcija uslovnog skoka koja testira vrednosti flegova i izvodi skok ukoliko flegovi indiciraju da upoređeni brojevi zadovoljavaju odgovarajuću relaciju.

Kod instrukcija uslovnog skoka može biti samo jedan operand, i to mora biti direktan memorijski operand.

Uslovni skokovi su:

JE D (eng. jump on equal - skoči ukoliko su jednaki) - ? ZF, ako da D® EIP.

JNE D (eng. jump on not equal - skoči ukoliko nisu jednaki) - ? ŘZF, ako da D® EIP.

JL D (eng. jump on less than - skoči ukoliko je manji) - ? (SFÚOF), ako da D® EIP.

JNL D (eng. jump on not less than - skoči ukoliko nije manji) - ? Ř(SFÚOF), ako da D® EIP.

JG D (eng. jump on greater than - skoči ukoliko je veći) - ? Ř((SFÚOF)ÚZF), ako da D® EIP.

JNG D (eng. jump on not greater than - skoči ukoliko nije veći) - ? ((SFÚOF)ÚZF), ako da D® EIP.

JB D (eng. jump on below - skoči ukoliko je ispod) - ? CF, ako da D® EIP.

JNB D (eng. jump on not below - skoči ukoliko nije ispod) - ? ŘCF, ako da D® EIP.

JA D (eng. jump on above - skoči ukoliko je iznad) - ? Ř(CFÚZF), ako da D® EIP.

JNA D (eng. jump on not above - skoči ukoliko nije iznad) - ? (CFÚZF), ako da D® EIP.

Mnemonici prethodnih instrukcija uslovnog skoka imaju svoje sinonime:

JE « JZ (eng. jump on zerro - skoči ukoliko je postavljen nula fleg).

JNE « JNZ (eng. jump on not zerro - skoči ukoliko nije postavljen nula fleg).

JL « JNGE (eng. jump on not greater or equal - skoči ukoliko nije veći ili jednak).

JNL « JGE (eng. jump on greater or equal - skoči ukoliko je veći ili jednak).

JG « JNLE (eng. jump on not less or equal - skoči ukoliko nije manji ili jednak).

JNG « JLE (eng. jump on less or equal - skoči ukoliko je manji ili jednak).

JB « JNAE (eng. jump on not above or equal - skoči ukoliko nije iznad ili jednak).

JNB « JAE (eng. jump on above or equal - skoči ukoliko je iznad ili jednak).

JA « JNBE (eng. jump on not bellow or equal - skoči ukoliko nije ispod ili jednak).

JNA « JBE (eng. jump on bellow or equal - skoči ukoliko je ispod ili jednak).

Postoje instrukcije uslovnih skokova kod kojih izvršavanje prelaska zavisi isključivo od postavljanja flegova. Uočava se da su takve i prethodno opisane instrukcije JZ (JE) i JNZ (JNE) koji testiraju sadržaj nula-flega, te JB (JNAE) i JNB (JAE) koje testiraju sadržaj CF. Pored prethodno pobrojanih, uslovni prelasci koji zavise isključivo od postavljanja jednog flega su:

JS D (eng. jump on sign - skoči ukoliko je postavljen fleg znaka) - ? SF, ako da D® EIP.

JNS D (eng. jump on not sign - skoči ukoliko nije postavljen fleg znaka) - ? ŘSF, ako da D® EIP.

JO D (eng. jump on overflow - skoči ukoliko je postavljen fleg prekoračenja) - ? OF, ako da D® EIP.

JNO D (eng. jump on not overflow - skoči ukoliko nije postavljen fleg prekoračenja) - ? ŘOF, ako da D® EIP.

JP D (eng. jump on parity - skoči ukoliko je postavljen fleg parnosti) - ? PF, ako da D® EIP.

JNP D (eng. jump on not parity - skoči ukoliko nije postavljen fleg parnosti) - ? ŘPF, ako da D® EIP.

Mnemonici instrukcija uslovnog skoka koji testiraju fleg parnosti imaju svoje sinonime:

JP « JPE (eng. jump on parity even - skoči ukoliko je parnost parna).

JNP « JPO (eng. jump on parity odd - skoči ukoliko je parnost neparna).

Kao i kod instrukcija bezuslovnog skoka, odredišni operand je enkodiran relativno u odnosu na instrukciju koja neposredno sledi iza instrukcije skoka.

Dok su prethodnici procesora 80386 dopuštali samo kraći oblik instrukcija uslovnog prelaska (pa se odredište moralo nalaziti do 128 bajtova ispred, odnosno 127 bajtova iza linije koja sledi instrukciju uslovnog skoka), kod ovog procesora se dopušta da odredište ma koje instrukcije uslovnog skoka (sem instrukcija JCXZ i JECXZ) bude bilo gde u memorijskom prostoru. Korištenje te duže forme, naravno, ima svoju cenu: u tom slučaju instrukcija zauzima tri bajta više nego odgovarajuća kraća forma, jer iza 16-bitnog opkoda sledi četvorobajtni pomak.

Postavlja se pitanje: zašto uvoditi nove opkodove, tj. zašto dodavati duži oblik za uslovne prelaske? Zar najveći broj uslovnih prelazaka nisu skokovi na bliske instrukcije, a skokovi na daleke labele se mogu realizovati preko sekvence instrukcija, kao kod sledećeg primera:

Primer.

            JNC L1

            JMP ODRED

L1:

 

JC ODRED ;

Realizovanje dugog uslovnog pomoću kratkog uslovnog i bezuslovnog skoka.

Odgovor zašto su instrukcije baš ovako dizajnirane, počiva na sledećim argumentima:

- uočeno je da prevodioci sa jezika visokog nivoa generišu veliki broj dalekih uslovnih skokova, koristeći sekvencu instrukcija analogno prethodnom primeru;

- nova forma dalekog skoka je, zbog arhitekture procesora 80386, efikasnija od njene alternative.

Primer.

            CLD

            MOV DI, 200H

            MOV CX, 201H

SLEDECI:

            MOV AL, ‘X’

            REPNZ SCASB

            JNZ KRAJ

            DEC DI

            MOV AL, ‘Y’

            STOSB

            INC CX

            LOOP SLEDECI

KRAJ: 

            CLD

            MOV DI, 200H

            MOV CX, 201H

SLEDECI:

            MOV AL, ‘X’

            REPNZ SCASB

            JNZ KRAJ

            DEC DI

            MOV AL, ‘Y’

            STOSB

            JCXZ KRAJ

            JMP SLEDECI

KRAJ: 

Pretražuje se 200 bajtova iz opsega 200H - 400H (relativno u odnosu na ES registar) i svaka pojava ASCII koda slova X biva zamenjena slovom Y:

Instrukcije uslovnog postavljanja bajtova

Svaka od prethodno opisanih instrukcija uslovnog skoka ima analognu instrukciju uslovnog postavljanja bajtova. Ove instrukcije nisu postojale kod prethodnika procesora 80386, a dodate su kako bi prevodioci za jezike visokog nivoa lakše evaluirali bulove izraze.

Primer.

Neka je u nekom jeziku visokog nivoa deklarisana logička promenljiva UGRANICAMA, i naka je deklarisana celobrojna promenljiva PROM. Razmotrimo kako bi prevodilac generisao kod za naredbu dodele: UGRANICAMA = (PROM <= 10000).

Ukoliko ne bi postojala instrukcija uslovnog postavljanja bajtova, prevodioc bi generisao kod sledećeg oblika:

            CMP PROM, 1000

            MOV UGRANICAMA, 1

            JG L1

            DEC UGRANICAMA

L1:

Kod sličan onom iz prethodnog primera se pojavljuje vrlo često. Na primer, u prevođenju naredbe IF(PROM<=10000)OR(PROM>=20000) će najverovatnije na prethodno opisan način biti obrađen svaki od uslova PROM<=10000 i PROM>=20000.

Instrukcije za uslovno postavljanje bajtova su:

SETE D (eng. set on equal - postavi ukoliko su jednaki) - ? ZF, ako da 1® D, ako ne 0® D.

SETNE D (eng. set on not equal - postavi ukoliko nisu jednaki) - ? ŘZF, ako da 1® D, ako ne 0® D.

SETL D (eng. set on less than - postavi ukoliko je manji) - ? (SFÚOF), ako da 1® D, ako ne 0® D.

SETNL D (eng. set on not less than - postavi ukoliko nije manji) - ? Ř(SFÚOF), ako da 1® D, ako ne 0® D.

SETG D (eng. set on greater than - postavi ukoliko je veći) - ? Ř((SFÚOF)ÚZF), ako da 1® D, ako ne 0® D.

SETNG D (eng. set on not greater than - postavi ukoliko nije veći) - ? ((SFÚOF)ÚZF), ako da 1® D, ako ne 0®D.

SETB D (eng. set on below - postavi ukoliko je ispod) - ? CF, ako da 1® D, ako ne 0® D.

SETNB D (eng. set on not below - postavi ukoliko nije ispod) - ? ŘCF, ako da 1® D, ako ne 0® D.

SETA D (eng. set on above - postavi ukoliko je iznad) - ? Ř(CFÚZF), ako da 1® D, ako ne 0® D.

SETNA D (eng. set on not above - postavi ukoliko nije iznad) - ? (CFÚZF), ako da 1® D, ako ne 0® D.

SETS D (eng. set on sign - postavi ukoliko je postavljen fleg znaka) - ? SF, ako da 1® D, ako ne 0® D.

SETNS D (eng. set on not sign - postavi ukoliko nije postavljen fleg znaka) - ? ŘSF, ako da 1® D, ako ne 0®D.

SETO D (eng. set on overflow - postavi ukoliko je postavljen fleg prekoračenja) - ? OF, ako da 1® D, ako ne 0®D.

SETNO D (eng. set on not overflow - postavi ukoliko nije postavljen fleg prekoračenja) - ? ŘOF, ako da 1®D, ako ne 0® D.

SETP D (eng. set on parity - postavi ukoliko je postavljen fleg parnosti) - ? PF, ako da 1® D, ako ne 0® D.

SETNP D (eng. set on not parity - postavi ukoliko nije postavljen fleg parnosti) - ? ŘPF, ako da 1® D, ako ne 0® D.

Mnemonici prethodnih instrukcija za uslovno postavljanje bajtova imaju svoje sinonime:

SETE « SETZ (eng. set on zerro - postavi ukoliko je postavljen nula fleg).

SETNE « SETNZ (eng. set on not zerro - postavi ukoliko nije postavljen nula fleg).

SETL « SETNGE (eng. set on not greater or equal - postavi ukoliko nije veći ili jednak).

SETNL « SETGE (eng. set on greater or equal - postavi ukoliko je veći ili jednak).

SETG « SETNLE (eng. set on not less or equal - postavi ukoliko nije manji ili jednak).

SETNG « SETLE (eng. set on less or equal - postavi ukoliko je manji ili jednak).

SETB « SETNAE (eng. set on not above or equal - postavi ukoliko nije iznad ili jednak).

SETNB « SETAE (eng. set on above or equal - postavi ukoliko je iznad ili jednak).

SETA « SETNBE (eng. set on not bellow or equal - postavi ukoliko nije ispod ili jednak).

SETNA « SETBE (eng. set on bellow or equal - postavi ukoliko je ispod ili jednak).

SETP « SETPE (eng. set on parity even - postavi ukoliko je parnost parna).

SETNP « SETPO (eng. set on parity odd - postavi ukoliko je parnost neparna).

Dakle, instrukcija postavljanja bajta na osnovu uslova uprošćava sekvencu instrukcija dopuštanjem da se smeste rezultati ma kog testa direktno u registar ili memorijsku promenljivu. Uslov koji se postavlja je određen kao deo mnemonika, dok je odredište registar ili memorijska promenljiva dužine jednog bajta, u koju će se smestiti 1 ukoliko je spsecificirani uslov ispunjen, odnosno 0 ukolliko taj uslov nije ispunjen.

Primer.

Za slučaj naredbe iz prethodnog primera, generiše se otprilike sledeći kod:

CMP PROM, 1000

SETLE UGRANICAMA

Primer.

SETZ AL

SETGE CH

SETO BL

SETC BVAR

SETNZ BVAR

SETA BVAR

Ilustruje razne varijante korišćenja instrukcija za uslovno postavljanje bajtova:

Instrukcije za rad sa flegovima

Procesor 80386 ima instrukcije za brisanje i postavljanje flega prenosa (CF), flega pravca (DF), flega omogućavanja prekida (IF).

CLC (eng. clear carry flag - obriši fleg prenosa) - 0® CF.

CMC (eng. complement carry flag - komplementiraj fleg prenosa) - 1-CF® CF.

STC (eng. set carry flag - postavi fleg prenosa) - 1® CF.

CLD (eng. clear direction flag - obriši fleg pravca) - 0® DF.

STD (eng. set direction flag - postavi fleg pravca) - 1® DF.

CLI (eng. clear interrupt enable flag - obriši fleg omogućavanja prekida) - 0® IF.

STI (eng. set clear interrupt enable flag - postavi fleg omogućavanja prekida) - 1® IF.

Primer.

Ilustruje razne varijante korišćenja instrukcija za uslovno postavljanje bajtova:

CLD

CMC

STI

Prekidi

Razlikuju se dva načina rada sa spoljašnjim uređajima: poliranje (ili prozivanje, eng. polling) i prekidi (eng. interrupts).

U prvom slučaju procesor u regularnim vremenskim trenutcima proverava da lli je izvršena operacija sa spoljašnjim uređajem. Kako će se u najvećem broju slučajeva dobiti negativan odgovor, jasno je da se nepotrebno gubi vreme.

Kod prekida postoji mehanizam pomoću koga procesor dopušta spoljašnjem uređaju (npr. tastaturi, zvučnoj kartici itd.) da privuče procesorovu pažnju. Najveći broj modernih procesora radi sa spoljašnjim uređajima pomoću prekida.

Na procesoru 80386 postoje dva pina (eng. pin - iglica), nazvani NMI (eng. nonmaskable interrupt - nemaskirajući prekid) i INTR (eng. interrupt - prekid), koji omogućavaju da sa spoljašnjih uređaja dođu signali do procesora.

Kada spoljašnji uređaj pošalje signal na NMI pin, procesor će se zaustaviti bez obzira šta da je radio (naravno, neće se zaustaviti na polovini izvršenja jedne instrukcije) i povešće računa o prekidu. Međutim, može se dogoditi da se ovako procesor prekida u sred nekog veoma važnog posla, tako da se ovaj način prekidanja rada procesora treba izvršiti samo u stvarno kritičnim slučajevima. Takav slučaj je gubitak napona do kog dolazi neposredno pred nestanak struje (eng. power faliture), kada treba “javiti” procesoru da “spašava što se spasti može”.

Dakle, u najvećem broju slučajeva, spoljašnji uređaji trebaju slati signale na INTR pin procesora. Za signale koji dolaze kroz taj pin, može se postaviti da (ako je to potrebno) ti signali budu ignorisani od strane mikroprocesora. To ignorisanje postiže se brisanjem IF flega, tj. flega za omogućavanje prekida. Dakle, prekidi kroz INTR pin će biti omogućeni samo ukoliko je IF postavlljen. Instrukcije za postavljanje i brisanje flega za omogućavanje prekida biće opisane nešto kasnije.

Pored slanja signala na INTR pin, spoljašnji uređaj mora saopštiti i razlog za prekid rada procesora. Za procesor 80386 se razlog za prekid rada procesora naziva tip prekida i to je broj 0-255. Za svaki od tipova prekida procesor ima program koji mora izvršiti pre povratka na normalne zadatke. Rad tih programa često zavisi i od sadržaja opštih registara. Adrese početaka tih programa nalaze se u tabeli od 256 elementa, pri čemu je lokacija tabele određena operativnim sistemom. Programe koji se izvršavaju kada dođe do prekida nazivaju se prekidne procedure, ili prekidne rutine, ili rutine za opsluživanje prekida.

[ta će se, dakle, dogoditi kada procesor primi signal za prekid na svoj INTR pin, pri čemu je IF već postavljen? Po završetku izvršavanja tekuće instrukcije, procesor zaustavlja tekući rad i sprema se da izvrši proceduru koja odgovara tipu prekida:

1) Procesor sačuva sve relevantne informacije o tome šta radi, tako da se po završetku izvršavanja prekidne procedure može da se vrati na prethodno prekinuti posao. Uobičajeno mesto na kom se čuvaju takve relevantne informacije je stek. Vrednosti koje se čuvaju su tekuće postavljenje svih flegova i sadržaj brojača naredbi.

2) Procesor prima od spoljašnjeg uređaja tip prekida i postavlja IP na vrednost koja u tabeli prekida odgovara broju prekida. Tako će sledeća instrukcija koja se izvršava biti prva instrukcija prekidne procedure koja odgovara signaliziranom tipu prekida.

[ta će se dogoditi ako procesor primi signal na njegov NMI pin? U tom slučaju se ne testira vrednost IF, jer zahtev za prekid mora biti opslužen. Postupak opsluživanja je isti kao u prethodno opisanom slučaju, s tim što se ne šalje tip prekida, već se zna da je prekid tipa 2 u tabeli prekida rezervisan za prekidnu proceduru koja obrađuje nemaskirajuće prekide, odnosno za NMI prekidnu proceduru.

Dosad se govorilo isključivo o spoljašnjim, tj. eksternim prekidima. U pojedinim situacijama, kada se pri izvršavanju instrukcija dogodi nešto neočekivano, i sam procesor generiše prekide. Ti prekidi se nazivaju unutrašnji, tj. interni prekidi. Primeri unutrašnjih prekida su već opisivani - prekoračenje prilikom deljenja dovodi do generisanja prekida tipa 0.

Kod procesora 80386 su prvih 32 elementa tabele prekida rezervisani za unutrašnje prekide i nemaskirajući prekid. Prethodnici procesora 80386 su imali rezervisana 32 elementa tabele, ali su u upotrebi bili samo prvih pet među njima (prekidi tipa 0-4).

Tip prekida

Rezervisano za

0

Divide overflow for DIV and IDIV

1

Debugger trapping

2

External NMI

3

One-byte debugger breakpoint trap

4

Overflow interrupt: executes INTO when OF=1

5

BOUND instruction fault

6

Illegal instruction fault

7

No floating point processor avaliable

8

Double fault

9

Floating point segment overrun fault

10

Invalid task state segment fault

11

Segment not present fault

12

Stack fault

13

General protection fault

14

Page fault

15

Reserved by INTEL for future use

16

Floating-point processor error

17-31

Reserved by INTEL for future use

Kao što je već poznato, u slučaju da dođe do prekoračenja ne generiše se odmah prekid, jer u mnogim slučajevima (uvek kada se radi sa neoznačenim brojevima) rezultat u kom je došlo do prekoračenja može smisleno da se obradi. Ipak, postoji efikasna (jednobajtna) instrukcija koja omogućava da dođe do prekida u zavisnosti od postavljenja OF.

INTO (eng. interrupt on overflow - prekid ukoliko je postavljen fleg prekoračenja) - ? OF, ako da procesor generiše prekid tipa 4.

Instrukcija INTO bi trebala da sledi iza svakog računanja sa označenim brojevima, kako bi se u tom slučaju obezbedilo da se ne dobije nekorektan rezultat usled prekoračenja.

Prekidna procesura treba da na kraju svog rada izvršavanje vrati tamo gde je prekinuto. To se svodi na restaurisanje vrednosti registra EIP i registra flegova, koji su do tada bili čuvani na steku. To restaurisanje sadržaja EIP i EFLAGS se realizuje pomoću posebne instrukcije.

IRETD (eng. interrupt return doublewors - povratak iz prekida sa dvostrukim rečima) - stek®EIP, stek®EFLAGS.

Instrukcija IRETD se razlikuje od instrukcije RET u tome što instrukcija povratak RET ne skida flegove sa steka.

Ukoliko procesor 80386 emulira nekog od prethodnika u familiji, tada je registar pokazivač insrukcije, isto kao i registar flegova, 16-bitan, pa se za povratak iz prekidne procedura koristi instrukcija IRET.

IRET (eng. interrupt return - povratak iz prekida sa) - stek®IP, stek®FLAGS.

Još jedna instrukcija koja se često javlja uz prekide je instrukcija zaustavljanja.

HLT (nem. halt - stani, zaustavi se) - zaustavlja procesor dok se ne dogodi prekid.

Instrukcija HLT zaustavlja procesor i EIP postavlja na adresu instrukcije koja neposredno sledi iza nje. Kada potom dođe do prekida, vrednost EIP i EFLAGS se šalju na stek, i procesor nastavlja sa izvršenjem instrukcija prekidne procedure. Po izvršenju IRETD instrukcije na kraju rada prekidne procedure, restauriše se vrednost EIP, pa se izvršavanje nastavlja od instrukcije koja se nalazi neposredno iza HLT instrukcije.

Kao što se iz dosada izloženog moglo zaključiti, u memoriji se nalaze 256 prekidnih procedura. Te procedure čekaju da se dogodi prekid, kako bi mogle da ga opsluže svojim izvršavanjem. ^esto bi imalo smisla pozvati neku od ovih procedura, čak iako se ne dogodi prekid. Budući da lokacija svake od ovih procedura postoji u tabeli, izgleda da bi se njihovo izvršavanje iz programerovog programa moglo lepo realizovati jednim indirektnim pozivom. Međutim, da bi sve to funkcionisalo (poznat je način funkcionisanja IRETD i IRET instrukcije) neophodno je da se pre izvršenja indirektnog poziva (E)FLAGS registar gurne na stek. Budući da se ovakva tehnika dosta često koristi, dizajneri procesora 80386 su predvideli jednu instrukciju koja radi sve što treba da se procesor ponaša kao da je dobio prekid sa spoljašnjeg uređaja, pri čemu je tip prekida specificiran u okviru same instrukcije.

INT D (eng. interrupt - prekid) - (E)FLAGS ® stek, (E)IP ® stek, tabela prekida(D) ® (E)IP.

Tip prekida je odredišni operand instrukcije, zadat je neposredno, i to je broj između 0 i 255. Prethodno opisani mehanizam poziva se pokazao toliko efikasnim da najveći broj današnjih računara ima prekidne porcedure koje se nikad ne izvršavaju na osnovu spoljašnjih zahteva.

Primer.

Ilustruje razne varijante korišćenja instrukcija vezanih za prekide:

INT 3 ; prekid tipa 3

INTO ; prekid pri prekoracenju

IRET

IRETD

HLT

DOS Prekidi

Način korišćenja prekida, pa i DOS prekida, u programima je standardizovan na sledeći način:

MOV AH, broj_funkcije

MOV ostali_registri, parametri

INT broj_prekida

Interapt 21H u sebi objedinjuje preko 80 funkcija. Pored njega, za realizaciju operacija koje zahteva DOS koriste se još i INT 20H (prekid programa), INT 25H (direktno čitanje sektora diska), INT 26H (direktan upis u sektore diska) i INT 27H (prekid programa sa permanentnim zadržavanjem u memoriji). Prvi i poslednji među pobrojanima su zamenjeni odgovarajućim funkcijama u okviru INT 21H koje pružaju i dodatne pogodnosti, tako da se sve ređe koriste.

Napomena.

U DOS sistemu za programera imaju veliku važnost dva prekida, iako se ne pozivaju direktno iz programa. To su INT 23H koji DOS poziva kada detektuje pritisak na <Ctrl>-C ili na <Ctrl>-<Break>, te INT 24H (prekid zbog kritične greške) koji se poziva kada nastane neka od alarmantnih situacija (npr. obraćanje disk jedinici u kojoj nema diskete, štampanje na neuključeni štampač itd.). Ova dva prekida imaju vrlo neugodne posledice u programima koji žele da imaju totalnu kontrolu nad računarom.

Napomena.

Veliki broj funkcija INT 21H odnosi se na rad sa datotekama. Datoteka sa podacima se na disku opisuje na klasičan način: prostim ređanjem podataka. U datoteci nema nikakvih zaglavlja niti drugih posebnih informacija. Podaci o svakoj datoteci su zapisani u direktorijumu koji čuva, između ostalog, i sledeće podatke:

1.                   naziv datoteke;

2.                   tačnu dužinu u bajtovima; prostor koji datoteka zauzima na disku je uvek veći, jer se odvajanje prostora vrši u tzv. jedinicama alokacije “klasterima” koji objedinjuju više fizičkih sektora diska;

3.                   vreme i datum nastanke/izmene datoteke

4.                   atribut datoteke (jedan bajt) u kom svaki od sledećih bitova ima tačno specificirano značenje: bit 0 označava da je datoteka samo za čitanje (eng. read only), bit 1 označava da je datoteka skrivena (eng. hidden), bit 2 označava da li je datoteka sistemska (eng. system), bit 3 ukazuje da ulaz u direktorijum nije datoteka već globalni naziv diskete (eng. volume), bit 4 označava da je datoteka poddirektorijum i da u sebi sadrži na isti način struktuirane podatke za sve datoteke koje se nalaze unutar tog poddirektorijuma (eng. sub directory), bit 5 je arhiv bit (eng. archive) koji ukazuje da je sadržaj datoteke menjan od poslednjeg pravljenja zaštitnih kopija tj. od poslednjeg bekapa (eng. back up).

DOS nudi dva pristupa podacima - sekvencijalan i direktan. Dužina sloga podataka koji se koristi u datotekama sa direktnim rpistupom nigde se ne zapisuje, tako da drugi programi koji koriste iste podatke moraju ovu informaciju imati ugrađenu kao unapred poznatu veličinu. U funkcijama višeg nivoa koje se danas koriste najpreciznije bi bilo reći da DOS koristi neku vrstu mešavine ova dva pristupa: mesto sa koga će sledeći podatak iz datoteke biti pročitan može se u bilo kom trenutku proizvoljno postaviti, kao što se u svakom trenutku može pročitati i proizvoljno dugačak slog.

U tabeli koji sledi opisane su neke od tzv. DOS funkcija, tj. rezultati koji se dobijaju pozivom prekidne procedure za prekid tipa 21H. Kao što već istaknuto, u registru AH se smešta tzv. broj funkcije.


011 - ^itanje znaka sa standardnog ulaza sa ehom

Izlaz: AL = znak

021 - Upis znaka na standardni izlaz

Ulaz: DL = znak

031 - ^itanje znaka sa RS232 interfejsa

Izlaz: AL = znak

041 - Upis znaka na RS232 interfejs

Ulaz: DL = znak

051 - Upis znaka na štampač

Ulaz: DL = znak

06 - Direktno čitanje/upis sa konzole

Ulaz: DL = znak - zahtev za upis

DL = FF - zahtev za citanje

Izlaz: ZF = 1 - taster nije pritisnut

ZF = 0 - taster jeste pritisnut

AL = taster

07 - Nefiltrirano čitanje sa standardnog ulaza bez eha

Izlaz: AL = znak

081 - Upis znaka sa standardnog ulaza bez eha

Ulaz: AL = znak

091 - Upis niske na standardni izlaz

Ulaz: DS:DX = niska (završava se sa $)

0A1 - ^itanje niske sa editovanjem

Ulaz: DS:DX = bafer

DS:[DX] = dužina bafera

Izlaz: DS:[DX+1] = dužina niske

DS:DX+2 = niska

0B - Status ulaza

Izlaz: AL = 0 - znak spreman za čitanje

AL = FF - nema spremnog znaka

0C - Restovanje ulaznog bafera i čitanje znaka ili niske

Ulaz: AL = broj funkcije za čitanje (01, 06, 07, 08, 0A)

Izlaz = kao kod pozvane funkcije

0D - Resetovanje disk jedinice

0E - Postavljanje aktivne disk jedinice

Ulaz: AL = broj disk jedinice (0=A, 1=B,...)

Izlaz: AL = broj logičkih disk jedinica u sistemu

0F2 - Otvaranje datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0 - FCB je popunjen

Greška: AL = FF - datoteka ne postoji

102 - Zatvaranje datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = FF - datoteka ne postoji

112 - Nalaženje prve odgovarajuće datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0 - DTA je popunjen kao standardni ili prošireni FCB

Greška: AL = FF - ni jedna datoteka ne odgovara postavljenom nazivu

122 - Nalaženje sledeće datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0 - DTA je popunjen kao standardni ili prošireni FCB podacima za sledeću datoteku

Greška: AL = FF - nema više datoteka čiji naziv odgovara

132 - Brisanje datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = FF - nijedna datoteka nije obrisana

142 - Sekvencijalno čitanje

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = 1 - kraj datoteke

   = 2 - prekoračenje granice segmenta

   = 3 - pročitan samo kraj bloka kad se naišlo na kraj datoteke

152 - Sekvencijalni upis

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = 1 - disk pun

   = 2 - prekoračenje granice segmenta

162 - Kreiranje datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = FF - nema mesta u direktorijumu

172 - Preimenovanje datoteke

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = FF - originalni naziv ne postoji, ili novi naziv već postoji

19 - Informacija o aktivnoj disk jedinici

Izlaz: AL = broj diska (0=A, 1=B,...)

1A2 - Postavljanje DTA

Ulaz: DS:DX = DTA

1B - Informacija o odvajanju prostora na aktivnom disku

Izlaz: AL = broj sektora po klasteru

CX = veličina fizičkog sektora na disku

DX = broj klastera na disku

DS:[BX] = FF - dvostrani flopi, 8 sektora po traci

   =FE - jednostrani flopi, 8 sektora po traci

   = FD - dvostrani flopi, 9 sektora po traci

   = FC - jednostrani flopi, 9 sektora po traci

   = F9 - dvostrani flopi, 15 sektora po traci

   = F8 - tvrdi disk.

1C - Informacija o odvajanju prostora na disku

Ulaz: DL = broj disk jedinice (0=A, 1=B,...)

Izlaz: AL = broj sektora po klasteru

CX = veličina fizičkog sektora na disku

DX = broj klastera na disku

DS:[BX] = FF - dvostrani flopi, 8 sektora po traci

   =FE - jednostrani flopi, 8 sektora po traci

   = FD - dvostrani flopi, 9 sektora po traci

   = FC - jednostrani flopi, 9 sektora po traci

   = F9 - dvostrani flopi, 15 sektora po traci

   = F8 - tvrdi disk.

212 - ^itanje sa direktnim pristupom

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = 1 - kraj datoteke

   = 2 - prekoračenje granice segmenta

   = 3 - pročitan samo kraj bloka kad se naišlo na kraj datoteke

222 - Upis sa direktnim pristupom

Ulaz: DS:DX = FCB

Izlaz: AL = 0

Greška: AL = 1 - disk pun

   = 2 - prekoračenje granice segmenta

232 - Veličina datoteke u slogovima

Ulaz: DS:DX = FCB

Izlaz: AL = 0

FCB popunjen od ofseta 21H

Greška: AL = FF - datoteka ne postoji

242 - Postavljanje rednog broj sloga

Ulaz: DS:DX = FCB

Izlaz: nodifikovani podaci u FCB

Greška: AL = FF - datoteka ne postoji

25 - Postavljanje vektora prekida, tj. elementa u tabeli prekida

Ulaz: DS:DX = tabela prekida

AL = broj prekida

Greška: AL = FF - datoteka ne postoji

27 - ^itanje proizvoljnog broja slogova

Ulaz: DS:DX = FCB

CX = broj slogova

Izlaz: AL = 0

CX = broj pročitanih slogova

Greška: AL = 1 - kraj datoteke

   = 2 - prekoračenje granice segmenta

   = 3 - pročitan samo kraj bloka kad se naišlo na kraj datoteke

28 - Upis proizvoljnog broja slogova

Ulaz: DS:DX = FCB

CX = broj slogova

Izlaz: AL = 0

CX = broj pročitanih slogova

Greška: AL = 1 - disk pun

   = 2 - prekoračenje granice segmenta

292 - Raščlanjivanje naziva datoteke

Ulaz: DS:DX = naziv

bit 3 AL-a = 1 - menja polje za ekstenziju samo ako je ona zadata u nazivu 

bit 3 AL-a = 0 - menja polje za ekstenziju u svakom slučaju, a ako ne postoji u nazivu popunjava prostor blankovima

bit 2 AL-a = 1 - menja polje za ime samo ako je isto zadato u nazivu

bit 2 AL-a = 0 - menja polje za ime u svakom slučaju, a ako ne postoji u nazivu popunjava prostor blankovima

bit 1 AL-a = 1 - menja broj diska samo ako je disk zadat u nazivu 

bit 1 AL-a = 0 - menja broj diska u svakom slučaju

bit 0 AL-a = 1 - ignoriše razmak ispred naziva

bit 0 AL-a = 0 - uzima i razmak ispred naziva

Izlaz: AL = 0 - sve u redu

AL = 1 - naziv sadrži džoker znake

ES:DI = FCB

Greška: AL = FF - oznaka diska je nevažeća

2A - ^itanje datuma sa sistemskog kalendara

Izlaz: CX = godina (1980-2099)

DH = mesec

DL = dan

AL = dan u nedelji (0=nedelja)

2B - Postravljanje datuma na sistemskom kalendaru

Ulaz: CX = godina (1980-2099)

DH = mesec

DL = dan

AL = dan u nedelji (0=nedelja)

Izlaz: AL = 0

Greška: AL = FF - neka od vrednosti je van opsega

2C - ^itanje vremena sa sistemskog časovnika

Izlaz: CH = sat (0-23)

CL = minut

DH = sekunda

DL = stotinka

2D - Postravljanje vremena na sistemskom časovniku

Ulaz: CH = sat (0-23)

CL = minut

DH = sekunda

DL = stotinka

Izlaz: AL = 0

Greška: AL = FF - neka od vrednosti je van opsega

2E - Određivanje da li vršiti proveru nakon upisa na disk

Ulaz: AL = 0 - isključi proveru nakon upisa

AL = 0 - uključi proveru nakon upisa

2F2 - Informacija o adresi aktivnog DTA

Izlaz: ES:BX = DTA

30 - Informacija o verziji operativnog sistema

Izlaz: AL = 0 - radi se o verziji 1.00

AL > 0 - tzv. viši broj verzije (npr. za MS DOS 6.20 će AL sadržati broj 6)

AH - tzv. niži broj verzije (npr. za MS DOS 6.20 će AH sadržati broj 2)

31 - Prekid programa uz njegovo zadržavanje u memoriji

Ulaz: AL = izlazni kod

DX = potrebna količina memorije u paragrafima

33 - ^itanje/postavljanje stanja posle <Ctrl>+<Break> prekida

Ulaz: AL = 0 - čita stanje

    = 1 - postavlja stanje

DL = 0 - isključuje proveru

    = 1 - uključuje proveru

35 - ^itanje vektora prekida, tj. elementa u tabeli prekida

Ulaz: AL = broj prekida

Izlaz: ES:BX = vektor prekida

36 - Informacija o količini slobodnog prostora na disku

Ulaz: DL = broj disk jedinice (0=aktivna, 1=A, 2=B,...)

Izlaz: AX = broj sektora po klasteru

BX = broj slobodnih klastera

CX = fizička veličina sektora

DX = ukupan broj klastera na disku

Greška: AX = FFFF - pogrešan broj disk jedinice

393 - Kreiranje poddirektorijuma

Ulaz: DS:DX = naziv poddirektorijuma

Greška: 3-5-6-16

3A3 - Brisanje poddirektorijuma

Ulaz: DS:DX = naziv poddirektorijuma

Greška: 3-5-6-16

3B3 - Postavljanje tekućeg direktorijuma

Ulaz: DS:DX = naziv direktorijuma

Greška: 3

3C3 4 - Kreiranje datoteke

Ulaz: DS:DX = naziv datoteke

CX = atribut koji će biti korišćen

   bit 0 - read only

   bit 1 - hidden

   bit 2 - system

   bit 3 - volume

   bit 4 - subdirectory (ignoriše se 1)

   bit 5 - archive (ignoriše se 1)

Izlaz: AX = rukovalac datoteke

Greška: 3-4-5

3D3 4 - Otvaranje datoteke

Ulaz: DS:DX = naziv datoteke

AL = 0 - samo čitanje

   = 1 - samo upisivanje

   = 2 - čitanje i upisivanje

Izlaz: AX = rukovalac datoteke

Greška: 1-2-3-4-5-12

3E3 4 - Zatvaranje datoteke

Ulaz: BX = rukovalac datoteke

Greška: 6

3F3 4 - ^itanje sadržaja datoteke

Ulaz: BX = rukovalac datoteke

CX = broj bajtova koji se čitaju

DS:DX = bafer

Izlaz: AX = broj pročitanih bajtova

Greška: 5-6

403 4 - Upis u datoteku

Ulaz: BX = rukovalac datoteke

CX = broj bajtova koji se upisuje

DS:DX = bafer

Izlaz: AX = broj upisanih bajtova

Greška: 5-6

AX = 0 - disk je pun

413 - Brisanje datoteke

Ulaz: DS:DX = naziv datoteke (mogu i džokeri)

Greška: 2-5

423 4 - Menjanje pokazivača pozicije za čitanje/upis kod datoteke

Ulaz: BX = rukovalac datoteke

CX = viša reč vrednosti pomeranja

DX = niža reč vrednosti pomeranja

AL = 0 - pomeranje se vrši apsolutno od početka datoteke

   = 1 - pomeranje se vrši relativno od tekuće pozicije

   = 2 - pomeranje se vrši apsolutno od kraja datoteke

Izlaz: DX = viša reč nove apsolutne pozicije u odnosu na početak datoteke

AX = niža reč nove apsolutne pozicije u odnosu na početak datoteke

Greška: 1-6

433 - ^itanje/postavljanje atributa datoteke

Ulaz: DS:DX = naziv datoteke

AL = 0 - čita atribut bajt

   = 1 - menja atribut bajt

CX = novi atribut (ako se radi o menjanju)

Izlaz: CX = pročitani atribut

Greška: 1-2-3-5

473 - ^itanje tekućeg direktorijuma

Ulaz: DS:DX = bafer

DL = broj disk jedinice (0=aktivna, 1=A, 2=B,...)

Izlaz: bafer popunjen nazivom tekućeg direktorijuma (sa celim putem).

Greška: 15

483 - Odvajanje memorijskog bloka

Ulaz: BX = veličina bloka u paragrafima

Izlaz: AX = segmentna adresa bloka

BX = maksimalna izdvojena veličina (ako nema dovoljno prostora)

Greška: 7-8

493 - Oslobađanje prethodno odvojenog memorijskog bloka

Ulaz: ES = segmentna adresa bloka

Greška: 7-8

4A3 - Menjanje količine dodeljene memorije

Ulaz: ES = segmentna adresa bloka

BH = nova veličina bloka (u paragrafima)

Izlaz: BX = maksimalna novoizdvojena veličina (ako nema dovoljno prostora)

Greška: 7-8

4B3 5 - Izvršavanje programa

Ulaz: AL = 0

ES = segmentna adresa parametar bloka

BX= ofset parametar bloka

DS = segmentna adresa naziva programa

DX= ofset naziva programa

Izlaz: Uništen je sadržaj svih registara sem CS i IP

4C - Prekidanje program i određivanje izlaznog statusa

Ulaz: AL = izlazni status


Napomene:

1) Broj 1 kod rednih brojeva funkcije označava da se detektuje pritisak na <Ctrl>+C ili na <Ctrl>+<Break>, pa se potom opslužuje prekid tipa 23.

2) Broj 2 kod rednih brojeva funkcije označava da se radi o starijim funkcijama za rad sa datotekama koje koriste FCB strukture (eng. file control block - blok za kontrolu datoteka). FCB struktura je u osnovnoj varijanti dugačka 37 bajtova, i sadrži sledeća polja:

5.    broj disk jedinice (ofset 00H),

6.    levo poravnato ime datoteke (ofset 01H),

7.    levo poravnata ekstenzija (ofset 09H),

8.    redni broj bloka koji se trenutno čita (ofset 0CH),

9.    dužina sloga (ofset 0EH),

10. veličina datoteke u bajtovima (ofset 11H),

11. datum kreiranja/izmene datoteke (ofset 14H),

12. vreme kreiranja/izmene datoteke (ofset 16H),

13. rezervisano sistemsko područje (ofset 18H),

14. redni broj sloga (ofset 20H),

redni broj sloga za datoteke sa direktnim pristupom (ofset 21H-24H).

Za korektan rad sa datotekama pomoću FCB strukture, neophodno je da postoji i DTA (eng. data transfer area - prostor za prenos podataka) deo memorije koji sluči za prenos podataka, tj. kao bafer (eng. buffer - bafer, tampon). Odgovarajućom DOS funkcijom se DOS-u stavlja na znanje koja je početna adresa ovog područja.

U ovom slučaju, postupak otvaranja datoteke teče na sledeći način:

1.    program odvaja 37 bajtova za FCB;

2.    program postavlja naziv i  ekstenziju datoteke;

3.    program poziva odgovarajuću DOS funkciju za otvaranje datoteke;

4.    DOS pronalazi datoteku na disku;

5.    DOS popunjava polja sa vremenom, datumom i dužinom datoteke;

6.    DOS postavlja dužinu sloga (ofset 0EH) na inicijalnu vrednost 128.

Pored standardne strukture FCB, uvedena je i proširena FCB. Kod proširenog FCB-a prvi bajt ima vrednost 0FFH (što ne može biti broj disk-jedinice, pa se tako prošireni FCB razlikuje od standardnog), zatim slede 5 bajtova rezervisanog DOS područja, pa atribut. Ostatak je identičan standardnom FCB. Ukupna dužina proširenog FCB je 44 bajta.

Rad sa datotekama pomoću FCB struktura karakterišu sledeći nedostaci:

ne može se koristiti hijerarhijska struktura direktorijuma, jer se u FCB definiše samo naziv datoteke, a ne i put - pa datoteka mora biti u aktivnom direktorijumu;

metod rada sa datotekama preko FCB struktura je veoma komplikovan i zahteva mnogo predradnji;

pozicioniranje i čitanje blokova unutar datoteke je nepraktično.

3) Broj 3 kod rednih brojeva funkcije označava da se radi o novom mehanizmu za prijavljivanje grešaka tokom izvršavanja prekidne procedure. Tu se koristi fleg prenosa CF. Ako je tokom izvršenja prekidne procedure došlo do greške, tada se CF postavlja, a u registru AX se nalazi broj greške.

Brojevi koji se prilikom pojave greške nalaze u AX imaju sledeća značenja:

1

nevažeći broj funkcije;

2

datoteka ne postoji;

3

staza (eng. path put) ne postoji;

4

previše otvorenih datoteka, pa nema slobodnih rukovaoca datoteka;

5

pristup nije odobren, što se javlja pri pokušaju upisa u datoteku sa postavljenim RO (eng. read only);

6

upotreblen je nepostojeći rukovalac datoteke;

7

uništeni su blokovi za kontrolu raspodele memorije;

8

nedovoljno memorije da se zadovolji zahtev;

9

upotrebljena je adresa koja ne odgovara nijednom od blokova u sistemu odvajanja memorije;

10

nevažeći blok okruženja (eng. enviroment);

11

nevažeći format;

12

nevažeći kod za pristup;

13

nevažeći podaci;

14

 

15

nevažeći broj disk jedinice;

16

pokušaj brisanja tekućeg direktorijuma;

17

ne radi se o istom uređaju;

18

nema više odgovarajućih datoteka.

4) Broj 4 kod rednih brojeva DOS funkcija za rad sa datotekama označava da se radi o novijim funkcijama za rad sa datotekama koje koriste rukovaoce datoteka (zastupnike datoteka - eng. file handler). Naime, za otvaranje datoteke dovoljno je zadati njen naziv, uključujući i put. Na osnovu ove informacije DOS interno kreira blokove podataka potrebne za rad sa datotekama, a programu vraća mali ceo broj kojim će u toku čitanja i pisanja identifikovati ovu vezu. Taj broj se naziva rukovalac datoteke. Kada treba pročitati n bajtova iz datoteke, program poziva odgovarajuću funkciju navodeći rukovalac datoteke, adresu od koje treba smeštati podatke i broj bajtova. Rukovalac datoteke je obavezno ulazni parametar svih funkcija ove vrste koje rade sa datotekama.

Prilikom podizanja DOS-a otvara se određen broj datoteka. Stoga su za rukovaoce datoteka upotrebljeni sledeći brojevi:

0 - CON kao ulaz                      - standardni ulaz

1 - CON kao izlaz                      - standardni izlaz

2 - CON kao izlaz                      - standardni kanal za ispis greške

3 - AUX kao ulaz/izlaz   - standardni pomoćni uređaj (RS232)

4 - LST kao izlaz                       - standardni kanal za ispis na štampač

Za prethodno popisane veze nije potrebno otvarati kanale - dovoljno je koristiti dati rukovalac datoteke.

Ovakvom metodom se može lako ostvariti preusmeravanje standardnog ulaza/izlaza. Osobina brojeva koji se koriste kao rukovaci datoteka je da se za svaku novu datoteku bira najmanji slobodan broj. Ako se tako, pomoću odgovarajuće DOS funkcije, zatvori veza za vrednost rukovaoca datoteke 1 i potom otvori ma koja druga datoteka, rukovalac nove datoteke će dobiti vrednost 1, čime je svaki ispis preko standardnog izlaza usmeren u nju. Ovakav metod koristi komandni interpretator COMMAND.COM, kada u komandnoj liniji naiđe na znak preusmeravanja. U tom kontekstu se nazire i smisao datoteke sa rukovaocem jednakim 2: ako se izlaz i preusmeri u neku datoteku, programu je i dalje na rasplolaganju kanal za ispis na ekran, kako bi poruke o greškama bile vidljive u toku rada programa.

5) Broj 5 kod DOS funkcije označava da parametar blok ima sledeću strukturu: segmentna adresa okruženja (ofset 0-1), ofset parametara programa (ofset 2-3), segmentna adresa parametara programa (ofset 4-5), ofset prvog FCB iz PSP (6-7), segmentna adresa prvog FCB iz PSP (8-9), ofset drugog FCB iz PSP (A-B), segmentna adresa drugog FCB iz PSP (C-D)

Instrukcije za podršku jezicima visokog nivoa

Procesor 80386 ima tri instrukcije za pojednostavljivanje koda potrebnog da podrži određene karakteristike viših programskih jezika. Te instrukcije služe za lakše izvršavanje provere da li je indeks niza izašao van za to predviđene dimenzije, kao i za lakšu implementaciju podrške za rad procedura i funkcija kod viših programskih jezika.

Nijedna od ovih instrukcija nije postojala kod 286-tice i njenih prethodnika. Prva među prethodno pomenutim instrukcijama je:

BOUND D, S (eng. bound - ograniči, omeđi) - generiše prekid tipa 5 ukoliko se D ne nalazi između vrednosti koje su specificirane pomoću S.

Odredišni operand D je registarski, dok je S memorijski. Instrukcija BOUND proverava da li označena vrednost u registru dužine 16, odnosno 32, leži unutar određenih granica. Granice se nalaze u dvema uzastopnim rečima, odnosno dvostrukim rečima, u memoriji. Vrednost u registru treba da bude veća ili jednaka od prve, a manja ili jednaka od druge memorijske vrednosti.

Primer.

Sledeća instrukcija vrši proveru da li je indeks niza (u registru EBX) izašao iz dozvoljenog intervala (specificiranog dvema dvostrukim rečima koje se nalaze u memoriji, počev od lokacije DMEMLOCS), i ako je indeks niza van opsega, generiše se prekid tipa 5.

BOUND EBX, DMEMLOCS

Da bi se lepo upoznali sa drugim dvema instrukcijama, neophodno je shvatiti mehanizam poziva funkcije, odnosno procedure, u višem programskom jeziku. Za primer će se koristiti programski jezik PASCAL.

Primer.

PASCAL procedura sadrži odeljak deklaracije procedure i telo procedure:

procedure A; šodeljak deklaracije procedureć

var

             a1, a2: integer;

begin štelo procedureć

a1:= a2+1;

end;

Primer.

Kod PASCAL procedure u odeljku deklaracije mogu biti deklarisane i druge procedure:

procedure A;

var

             a1, a2: integer;

procedure B;

             var

                         b1, b2: integer;

begin

             b2:= a1+2;

end;

procedure C;

             var

                         c1, c2: integer;

begin

             c1:= a2+3;

end;

begin

a1:= a2+1;

end;

Primećuje se da objekti (promenljive, procedure) deklarisane u odeljku deklaracija procedure A mogu biti korišćeni kako u telu procedure A, tako i u telu procedura B i C. Ali, objekti deklarisani u odeljku deklaracija procedure B mogu biti korišćeni samo unutar tela procedure B.

Napomena.

Situaciju dodatno komplikuje i postojanje rekurzivnih procedura u PASCAL-u. Jer, jasno je (o tome je bilo reči kada je opisivana uloga steka kod podprograma) da svaki poziv rekurzivne procedure mora imati svoj prostor za smeštaj promenljivih koje su deklarisane unutar procedure. Stoga, promenljive moraju biti alocirane pri svakom od poziva i dealocirane po završetku rada procedure. Uobičajeno mesto za smeštaj ovakvih promenljivih je stek.

PASCAL kompajleri obično generišu kod koji pri pozivu procedure izvodi sledeće akcije:

1) alocira memorijski prostor (nazvan stek-okvir) na steku, za promenljive koje su deklarisane u proceduri;

2) postavlja (E)BP da pokazuje na memorijsku lokaciju, tj. tačku početka (odnosno najnižu adresu) stek-okvira.

Primer.

Sledeći dijagrami prikazuju stek-okvire procedure A i procedure B datih u trećem primeru ovog poglavlja.

 

veće memorijske adrese Ż 

...

 

 

 

 

 

 

 

(E)BP ®

 

 

stek-okvir procedure B

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

stek-okvir procedure A

 

 

 

 

 

 

 

...

­rast steka

Sada se za pristup promenljivoj deklarisanoj u proceduri (tzv. lokalnoj promenljivoj procedure) koristi fiksna veličina: razmak tj. rastojanje adrese promenljive od početka stek-okvira. Ovakvo adresiranje naziva se stek-okvir relativno adresiranje.

Primer.

Uočimo drugi primer u ovom poglavlju. Ako je promenljiva a2 smeštena 8 bajtova od početka stek-okvira, a promenljiva a1 6 bajtova od početka stek-okvira, onada bi pri prevođenju tela procedure A, PASCAL kompajler generisao otprilike sledeći kod:

MOV AL, [EBP-8]

INC AL

MOV [EBP-6], AL

Pri implementaciji PASCAL procedura mora se voditi računa o tome da je svaka promenljiva kojoj se može pristupiti u nekoj proceduri smeštena bilo u stek-okviru date procedure, bilo u stek-okviru procedure u kojoj je data procedura umetnuta. Stoga, stek-okvir mora sadržati pokazivače na svaki od prethodno pobrojanih stek-okvira. Lista ovakvih pokazivača naziva se displej (eng. display - prikaz). Može se reći da displej neke procedure opisuje statičke veze koje postoje između te procedure i svih procedura u kojima je ona ugnježdena.

Primer.

Na sledećoj slici vidimo iste stek-okvire iz prethodnog primera na kojima su prikazani displeji i alocirane promjenjljive.

 

veće memorijske adrese Ż 

...

 

 

 

 

 

 

 

b2

 

 

 

b1

prostor za promenljive

 

·

 

 

·

displej

 

  (E)BP ®

 

 

 

 

 

 

 

 

 

 

 

 

a2

 

 

 

a1

prostor za promenljive

 

·

displej

 

 

 

 

 

 

 

 

 

 

...

­rast steka

 

Po izlasku iz date procedure, moraju se izvršiti sledeće akcije:

1) stek okvir mora biti dealociran;

2) registar (E)BP se mora postaviti tako da pokazuje na stek okvir koji je bio tekući u trenutku kada je data procedura bila pozvana.

Veza između pozivajuće i pozvane procedure naziva se dinamička veza (eng. dynamic link - dinamička veza). Jasno je da stek-okvir procedure koja podziva datu proceduru ne mora biti isti sa stek-okvirom procedure u kojoj je data procedura ugnježdena, tj. dinamička veza se ne mora poklapati sa statičkom vezom.

Primer.

Procedura B iz trećeg primera u ovm poglavlju je ugnježdena u proceduri A, ali može biti pozvana i iz procedure A i iz procedure C.

Dealokacija (oslobađanje, uništavanje) stek-okvira se postiže stavljanjem tekuće vrednosti registra (E)BP u registar (E)SP, tj. postavljanjem (E)SP-a na početak tekućeg stek-okvira.

Izmena (E)BP-a pri izlasku iz procedure tako da on pokazuje na prethodno aktivni stek-okvir neće biti moguća ukoliko se pre poziva date procedure u stek-okviru te procedure, a pri njegovom formiranju, ne sačuva dotadašnja vrednost (E)BP-a. Ta vrednost, tj. dinamička veza se obično stavlja u stek-okvir neposredno pre displeja.

Dakle, pre svakog povratka iz procedure, kompajler mora generisati kod za delokaciju stek-okvira i restaurisanje registra EBP.

Primer.

Slika prikazuje stek-okvir sa dinamičkim vezama za PASCAL kod opisan u trećem primeru ovog poglavlja, a uz pretpostavku da se u telu procedure A nalazi i poziv procedure B.

 

veće memorijske adrese Ż 

...

 

 

 

 

 

 

 

b2

 

 

 

b1

prostor za promenljive

 

·

 

 

·

displej

 

  (E)BP ®

·

dinamička veza

 

 

 

 

 

 

 

 

 

 

a2

 

 

 

a1

prostor za promenljive

·

displej

 

 

·

dinamička veza

 

 

 

 

 

 

...

­rast steka

Instrukcije ENTER i LEAVE obavljaju upravo te zadatke.

LEAVE (eng. leave - napusti) instrukcija nema argumenata. Izvršava operacije neophodne za korektan povratak iz procedure. Njen efekat bi se mogao predstaviti na sledeći način:

ESP ¬ EBP

POP EBP

ENTER D, S (eng. enter - uđi) ima dva operanda. Ova instrukcija izvršava operacije neophodne za korektan ulazak u proceduru. Drugi operand predstavlja nivo ugnježdavanja date procedure, koji procesoru saopštava kolika je veličina displeja. Najspoljašnjiji nivo je 1. Prvi operand je broj bajtova u memoriji potreban za promenljive deklarisane u proceduri. Formalni opis ove instrukcije je dat sledećim algoritmom:

;formiranje dinamicke veze

PUSH EBP

;formiranje displeja

privremena vrednost STEK_OKVIR_PTR ¬  ESP

if D > 0 then

            repeat D -1 put:

                        EBP ¬ EBP-2

                        PUSH rec na koji pokazuje EBP

            end repeat

            PUSH STEK_OKVIR_PTR

endif

ESP ¬ FRAME_PTR

;formiranje prostora za lokalne promenljive

ESP ¬ ESP-S

Dakle, ukoliko je drugi operand nula, to znači da instrukcija ne uključuje displej u stek-okvir. Ovo je korisno za jezike poput C - a, u kojima nema ugnježdenih procedura.

Primećuje se da, kada procesor 80386 emulira neki od predhodnika, instrukcije ENTER i LEAVE rade na osnovu 16-bitnih vrijednosti registara BP i SP.

Instrukcije sinhronizacije

Kao što je u poglavlju XI i istaknuto, sistem prekida obezbeđuje sinhronizaciju procesora 80386 sa spoljnim uređajima. Arhitektura procesora 80386 obezbeđuje još dva oblika sinhronizacije:

Instrukcije za rad sa brojevima u pokretnom zarezu

Prvi oblik uključuje korišćenje podređenog procesora (koprocesora) za implementaciju skupa instrukcija za rad sa brojevima u pokretnom zarezu. Tokom postojanja i razvoja procesora iz familije 80x86, izvršenje instrukcija u pokretnom zarezu je bilo dodeljeno podređenom procesoru. Konkurentni rad procesora i koprocesora će biti opisan u delu koji se bavi arhitekturom i načinom funkcionisanja samog koprocesora. Zasad će samo biti istaknuto da procesor 80386 interpretira instrukcije za rad sa brojevima u pokretnom zarrezu kao direktive za sinhronizovanje sa podređenim procesorom, za komunikaciju sa tim procesorom, i za upravljanje memorijskim pristupom za taj procesor.

Deljenje resursa

Drugi oblik sinhronizacije između dva procesora je deljenje zajedničkih resursa. Odranije je poznato da konkurentan rad nad istim resursom može da proizvede probleme tj. naruši integritet podataka. Takođe je poznato da je uvođenje semafora put za prevazilaženje problema nastalih usled konkurentnog rada. Ovde se semafor realizuje kao memorijska lokacija koja procesoru signalizira da li neko drugi trenutno koristi deljenu memoriju. Jasno je da pri radu sa semafora mora postojati nedjeljiva operacija, tj. između očitavanja vrijednosti da je slobodna i postavljanja na zauzeto ne smije ništa da se desi.

Primer.

Sledeća sekvenca operacija predstavlja primer nekorektnog rada sa lokacijom koja predstavlja semafor.

1 - I čita 0 (slobodno)

2 - II čita 0 (slobodno)

3 - I postavlja 1 (zauzima)

4 - II postavlja 1 (zauzima)

Uočava se da je postavljanje jedinice (koja signalizira zauzetost) od strane procesa I, prekinuto, i da je u tom prekidu od strane procesa II očitana neadekvatna vrednost semafora. Tako se dogodilo da i proces I i proces II imaju informaciju da je delejni resurs njima stavljen na raspolaganje.

Da bi se čitanje raspoloživosti i postavljanje zauzetosti nekog resursa obavili pomoću jedne instrukcije, koristi se XCHG instrukcija.

Primer.

Sledeća sekvenca instrukcija se koristi da dohvati vrednosti iz bajt-memorijske promjenljive SEMA, i da, ukoliko SEMA indicira da je resurs slobodan, postavi da je resurs zauzet.

            MOV AL,1

L1:

            XCHG AL,SEMA

            CMP AL,0

            JNE L1

Ako se na ovakav način realizuje čekanje sve dok kritični resurs ne bude dostupan i njegovo zauzimanje kada postane dostupan, tada se nedeljiva sekvenca operacija realizuje samo jednom XCHG instrukcijom.

Na nesreću, iako se u prethodnom primeru koraci provere dostupnosti i eventualnog signaliziranja zauzetosti izvršavaju jednom naredbom, hardver ih ne izvršava simultano, tako da između operacije čitanja i upisa postoji kratak vremenski period, tokom koga izvršavanje ove instrukcije može biti prekinuto.

Problem je rešen na hardverskom nivou sa izlaznim pinom (eng. pin - iglica) na procesoru 80386 koji se naziva lock pin (eng. lock - zaključavanje), ili pin zaključavanja. Taj pin zaključavanja šalje signal za vrijeme trajanja XCHG instrukcije. Na taj način se može dati ekskluzivan memorijski pristup na kom procesoru koji je poslao signal zaključivanja.

Pitanje je koliko se često treba slati signal zaključavanja? Ako bi uz svaku instrukciju imao signal zaključavanja, to bi degradiralo performanse sistema toliko mnogo da bi se sva prednost postojanja više od jednog procesora izgubila.

Zbog toga se dopušta programska kontrola nad pinom zaključavanja, eventualnim postavljanjem prefiksa instrukcije LOCK. Instrukcija koja ima prefiks LOCK će izazvati da pin zaključavanja bude aktiviran za vreme trajanja instrukcije.

U sljedećem poglavlju će biti opisani primeri korišćenja LOCK prefiksa pri manipulaciji bitovima.

Još treba napomenuti da LOCK prefiks nije neophodan kod XCHG instrukcije, zato što procesor 80386 automatski aktivira pin zaključavanja kod svih XCHG instrukcija koje uključuju memorijski operand.

Instrukcije za rad sa nizovima bitova

Ove instrukcije postoje tek kod procesora 80386 i njegovih sljedbenika. Instrukcije su dizajnirane za obezbeđenje kompletnih mogućnosti za manipulaciju nizovima pojedinačnih bitova.

Opet se postavlja pitanje: “[ta će nam sve to? ^emu bi (korisnom) takve instrukcije služile? Zar te instrukcije, odnosno njihovo uvođenje, nisu u suprotnosti sa pravcem razvoja familije procesora 80x86? Jer, 32-bitne mašine su dizajnirane za manipulisanje većim skupinama podataka, a ne manjim.”

Posmatranjem razvoja računara, uočavaju se dva glavna razloga koja određuju značaj razvoja instrukcija za manipulaciju sa bitovima:

1) Razvoj memorijskih uređaja je učinio mogućim da računar manipuliše sa audio i video zapisima. Za razliku od numeričkih i tekstovnih podataka, slika se teško može smisleno orgnizovati u blokove slogova koji sadrže više bitova. Sposobnost adresiranja individualnih bitova je, dakle, od vitalne važnosti za laku i brzu manipulaciju sa ovakvim podacima.

2) Uvećana snaga jezika visokog nivoa je napravila poželjnom bit manipulaciju koda generisanog od strane kompajlera. Najveći broj kompajlera je prisiljen da za svaki elemenat logičkog niza rezerviše ceo bajt. Direktno adresiranje bitova omogućava prevodiocu da spakuje logički niz (niz logičkih objekata) sa maksimalnom preciznošću.

Da bi se ovo moglo postići, potrebne su nam instrukcije za čitanje i upis individualnih bitova, za pretragu kroz niz bitova i za premeštanje bitovnog niza.

Nadalje se koristi sledeća konvencija za adresiranje bitova:

31

16

15

8

7

0

 

 

 

 

tj bit najmanje težine ima adresu 0, sljedeći bit adresu 1 itd. bit najveće težine u bajtu ima adresu 7, u reči 15, a u dvostrukoj reči 31.

^itanje i upis pojedinačnih bitova

Postoje samo 4 načina na koji se može manipulisati sa pojedinačnim bitom:

1) Postavljanje - vrednost postaje 1

2) Brisanje - vrednost postaje 0

3) Komplementiranje

4) Ostavljanje u nepromijenjenoj vrijednosti.

Svaka od ovih manipulacija sa bitom se obavlja tačno jednom od sledećih instrukcija:

BTS D, S (eng. bit set - postavi bit) - DS®CF, 1®DS, tj. bit odredišta D čija je adresa specificirana sa S se postavlja na 1, a stara vrednost tog bita smešta se u CF.

BTR D, S (eng. bit reset - obriši bit) - DS®CF, 0®DS, tj. bit odredišta D čija je adresa specificirana sa S se postavlja na 0, a stara vrednost tog bita smešta se u CF.

BTC D, S (eng. bit complement - komplementiraj bit) - DS®CF, 1-DS®DS, tj. komplementira se bit odredišta D čija je adresa specificirana sa S, a stara vrednost tog bita smešta se u CF.

BT D, S (eng. bit - bit) - DS®CF, tj. bit odredišta D čija je adresa specificirana sa S se smešta bit u CF

Svaka od ovih instrukcija ima dva operanda: prvi je reč ili dvostruka reč koja sadrži bit koji se čita i sa kojim se manipuliše. Drugi operand sadrži adresu bita unutar reči ili dvostruke reči. Adresa može biti neposredna vrednost, ili može biti sadržaj registra.

Primer.

Efekat dejstva instrukcije

BTC AX,2

(pri čemu je najniža četvorka AX-a tj. posljednja heksa cifra u AX-u 1111) se svodi na promjenu te četvorke u 1011, pri čemu će CF biti postavljen na 1.

Primećuje se da kada bit dođe u registar, bitovna adresa ne može preći adresu bita najveće težine u registru. Ovakva restrikcija ne bi smjela postojati u slučaju kada bitovi dolaze iz memorije. Međutim, nije tako.

Primer.

Promena bita na adresi 100 realizuje kao pomjeranje za 12 bajova (12*8=96) pa se promieni peti bit u trinaestom bajtu od početka - već je istaknuto da numeracija bitova počinje od 0.

Primer.

Ovo korišćenje bitovnog testiranja uključuje nizove semafora u rad sa semaforom. Segment programskog koda na asemblerskom jeziku obavlja isti rad sa semaforom kao i prethodni primjer koji je radio sa semaforom (s tim što se čita EAX-ta pozicija bita u lokaciji SEMA, koji sadrži niz semafora):

L1: ;neka se petlja postavi sve dok semafor postavi na 0

            LOCK BTS SEMA,EAX ;cita se bit u CF, a ovaj postavi na 1

JC L1 ;ako je bit vec bio 1, ostaje se u petlji

Pretraživanje kroz bitovni niz

^esto je od interesa tražiti specificiranu vrijednost bita kroz bitovni niz, jer se bitovni niz koristi za indikaciju alokacija resursa.

Primer.

Preko logičkog tj. bitovnog niza se može realizovati određivanje koji su sektori na disku slobodni: ako je sektor N slobodan, onda će N-ti bit u bitovnom nizu biti biti 1, inače će biti 0.

Tako, ako operativni sistem treba da alocira sektor, mora naći bit 1 u logičkom nizu.

Vrlo brzo se može naći dvostruka riječ koja sadrrži bar jedan bit postavljen na 1 - sa REPZ SCASD. Još samo treba da se brže odredi bit u nađenoj dvostrukoj reči - pri čemu se dvostruka reč može čitati odnapred ili odpozadi.

BSF D, S (eng. bit scan forward - skeniranje bitova unapred) - pozicija ne nula bita najmanje težine u S ®D.

BSR D, S (eng. bit scan reverse - skeniranje bitova unazad) pozicija ne nula bita najveće težine u S ®D.

Obe ove instrukcije zahtevaju da prvi operand bude registarski.

Primer.

Neka se bitovni niz zove MAPA_SEKT, a broj bitova u mapi je neposredna konstanta BR_SEKT. Da bi se uprostio problem, pretpostaviće se da MAPA_SEKT zauzima ceo broj dvostrukih riječi. Sljedeći segment programa određuje broj slobodnog sektora, vraće tu vrijednost u EAX i markira taj sektor kao zauzet.

            MOV EDI, MAPA_SEKT ;pokazi na bitovni niz sektora

            MOV ECX, BR_SEKT/32 ;unesi broj dvostrukih reci sektora

            SUB EAX, EAX ;obrazac za uporedjivanje je dvostruka rec ispunjena 0

            REPZ SCASD ;nadji ne nula dvostruku rec u nizu

            JZ greska ;ako su sve dvostruke reci 0, radi se o gresci

            BSF EAX,[EDI-1] ;odredi adresu prvog bita u nenula dvostrukoj reci

            SUB EDI, MAPA_SEKT+1 ;izracunaj broj preskocenih dvostrukih reci

            SHL EDI, 5 ;i konvertuj taj broj u broj preskocenih bitova

            ADD EDX, EDI ;dodaj broj preskocenih bitova na bitovnu adresu

            BTR MAPA_SEKT, EAX

greska:

Primer.

Neki primeri korišćenja prethodnih instrukcija:

BSF AX, BX ;postavlja AX na poziciju najnize jedinice u BX-u

BSF CX, M_W ;postavlja CX na poziciju najnize jedinice u reci M_W u memoriji

BSR EBX, EAX ;postavlja EBX na poziciju najvise jedinice u EAX-u

BSR EDX, M_DW ;postavlja EDX na poziciju najvise jedinice u dvostrukoj reci M_DW

Premeštanje bloka bitova

Razmotrimo za početak probleme koji odgovaraju bit- mapiranim vizuelnim slikama. Da bi se implementirale osobine kao što su proporcionalno širenje (tj. razmicanje) mora posojati mogućnost da npr. bit najmanje težine u dvostrukoj reči-izvoru prekopiramo u bit na poziciji 10 dvostruke reči - odredišta, pa sve tako do kraja.

Lako se uočava, za konkretan slučaj, da se svaka dvostruka reč u odredišnoj niski (stringu), sem prve i poslednje, sastoji od 10 bitova izvorne dvostruke reči i 22 bita sljedeće izvorne dvostruke riječi. Tako, podaci dolaze iz dve dvostruke reči (tj. dužina izvora je 64 bita).

Instrukcije pomeranja i rotacije koje su dosad opisane rade nad podacima od maksimalno 32-bita.

Procesor 80386 poseduje dve instrukcije specijalne namene, za 64-bitovno pomeranje:

SHLD D, H, S (eng. shift logical left double precision - pomeri logički ulevo dvostruko precizno) CF ¬ D ¬ H. Realizuje pomeranje odredišnog operanda za izvorom određen broj pozicija ulevo. Na mesta koja su “ispražnjena” prilikom pomeranja ulevo, smeštaju se niži (tj. donji) bitovi središnjeg operanda.

SHRD D, H, S (eng. shift logical right double precision - pomeri logički udesno dvostruko precizno) H ® D ® CF. Realizuje šiftovanje odredišnog operanda za izvorom određen broj pozicija udesno. Na mesta koja su “ispražnjena” prilikom pomeranja udesno, smeštaju se viši bitovi (tj. gornji bitovi ili bitovi veće težine) središnjeg operanda.

Ove dve instrukcije, dakle, imaju tri operanda. Prvi i poslednji su isti kao kod “normalnih” instrukcija pomjeranja: ukazuju na onaj registar (ili memorijsku lokaciju) nad kojim se vrši pomeranje i na to za koliko se mjesta pomjeranje izvršava. Razlika je u tome što SHLD i SHRD, za razliku od SHL i SHD koje ubacuju nule, na nova mesta ubacuju bitove iz srednjeg operanda. Pritom srednji operand izvršenjem ove instrukcije ne biva promenjen.

Primer.

Instrukcija

SHRD EAX, EBX, 10

pomera sadržaje EAX registra za deset mesta udesno, pri čemu se gornjih deset bitova registra EAX puni iz deset najnižih bitova registra EBX. Po izvršetku instrukcije će registar EBX ostati nepromenjen.

Potpuno analogno kao kod instrukcija pomeranja i rotacije, treći operand, tj. broj pozicija za koje se vrši pomeranje može biti dat bilo neposredno, bilo kao sadržaj registra CL.

Primer.

Da bi se ilustrovalo korišćenje instrukcija SHLD i SHRD, neka se posmatra rutina koja izvršava pomeranje blokova bitova. Neka se izvorni blok bitova sastoji od (E)DX dvostrukih reči, na koje pokazuje (E)SI. Radi jednostavnosti, pretpostavićemo da se izvor sastoji od celog broja dvostrukih reči, poravnatih tako da počinju od bita 0 izvora. Odredište počinje od CH-tog bita dvostruke reči na koju pokazuje (E)DI.

Premeštanje se prikazuje sledećom shemom:

 

0               31

0                31

0                   31

0                31

 

(E)SI®

 

 

 

 

 

 

Ż               Ż

Ż                 Ż

Ż                    Ż

Ż                    Ż

 

 

 

0

31

0                 31

0                31

0               31

0

31

 

(E)SI®

 

 

 

 

 

 

 

Kod kojim se realizuje premeštanje sastojaće se iz tri dela: deo za prenos u prvu dvostruku reč, deo za prenos srednjih dvostrukih reči i deo za prenos u sledeću dvostruku reč.

Kod je sledećeg oblika:

            MOV CL, 32

            SUB CL, CH ;racunamo 32-CH - za toliko se vrsi pomeranje

            MOV EAX, [EDI] ;dohvati prvu rec sa odredista

            ROL EAX, CL ;pomeri donjih CH bitova na vrh - kod u petlji ce ih ponovo vratiti na dno

 

L1:

            MOV EBX, [ESI] ;dohvati dvostruku rec sa izvora

            ADD SI, 4 ;uvecaj pokazivac na dvostruke reci sa izvora

            SHRD EAX, EBX, CL ;pomeri nanize CL bitova iz te i sledece reci

            STOSD ;smesti dobijeni rezultat

            MOV EAX, EBX ;sledeca izvorna rec postaje aktuelna

            DEC EDX ;umanji broj dvostrukih reci

            JNZ L1

 

            MOV CL, CH ;CL se koristi za oformljenje poslednje reci odredista

            SHR DWORD PTR [EDI], CL ;pomeri 32-CH bitova na dno - kako bi sledecom instrukcijom bili vraceni

            SHLD [EDI], EAX, CL ;pomeri bitove iz poslednje dvostruke reci izvora

Napomena.

U prethodnom primeru nije korišćena instrukcija LODS (tj. LODSD) zato što je dvostruka reč sa izvora trebala da se smesti u EBX, a ne u EAX. Ipak, umesto

MOV EBX, [ESI]

ADD SI, 4

moglo se napisati:

XCHG EAX, EBX

LODSD

XCHG EBX, EAX

Kao što je već istaknuto, instrukcije SHLD i SHRD su uključene kako bi se obezbedilo 64-bitovno pomeranje, i skoro uvek su argumenti, tj. operandi, dvostruke reči. Međutim, zbog potpune simetrije između reči i dvostrukih reči kod procesora 80386, mnemonici SHLD i SHRD prihvataju i 16-bitne operande. Nataj način se dobija egzotičnija forma 32-bitnog pomeranja. Kod ovih instrukcija operandi ne mogu biti dužine 8.

Primer.

Neki od načina korišćenja instrukcija SHLD i SHRD:

SHLD AX, BX, 3 ;gornja rec od AX BX SHL 3 ® AX

SHRD AX, BX, 3 ;donja rec od BX AX SHR 3 ® AX

SHLD M_W, DX, 9 ;gornja rec od M_W DX SHL 9 ® M_W

SHRD M_W, DX, 9 ;donja rec od DX M_W SHR 9 ® M_W

SHLD ECX, EDX, 23 ;gornja dvostruka rec od ECX EAX SHL 23 ® ECX

SHRD M_DW, EAX, 2 ;donja dvostruka rec od EAX M_DW SHR 2 ® M_DW

Sumarni pregled instrukcija

Primena prefiksa instrukcija

Postoji ukupno pet prefiksa instrukcija: REP, LOCK, prefiks veličine operanda, prefiks adresne dužine i prefiks označavanja segmenta. U ovom poglavlju će biti govora isljučivo o prefiksima REP i LOCK.

REP prefiks je valjan samo za string primitive.

LOCK prefiks je valjan samo za instrukcije koje čitaju i upisuju u istu memorijsku lokaciju. Sledeća tabela prikazuje valjane forme instrukcija za LOCK prefiks.

Valjane forme instrukcija za LOCK

ADD mem, reg

ADD mem, nep

DEC mem

ADC mem, reg

ADC mem, nep

INC mem

AND mem, reg

AND mem, nep

NEG mem

OR mem, reg

OR mem, nep

NOT mem

SBB mem, reg

SBB mem, nep

XCHG reg, mem

SUB mem, reg

SUB mem, nep

XCHG mem, reg

XOR mem, reg

XOR mem, nep

 

BT mem, reg

BT mem, nep

 

BTR mem, reg

BTR mem, nep

 

BTS mem, reg

BTS mem, nep

 

BTC mem, reg

BTC mem, nep

 

Ukoliko se neki od ova dva prefiksa koristi sa neodgovarajućom instrukcijom, tada dolazi do prekida tipa 6, tj. do invalidnog operacionog koda (eng. invalid opcode exception - izuzetak invalidnog opkoda).

Kako prefiksi REP i LOCK imaju disjunktne skupove instrukcija za koje su valjani, jasno je da se ta dva prefiksa ne mogu istovremeno primeniti.

Ukoliko se prekid prinudi da čeka, (jer prekidi se obično izvršavaju između instrukcija) sve dok se u potpunosti ne izvrši neka string primitiva sa prefiksom ponavljanja, to može da traje isuviše dugo. Stoga je procesor dizajniran tako da dopušta opsluživanje prekida poosle nekog broja ponavljanja repetirajuće string-primitive, a pre njenog kraja. Po opsluženju prekida će se ta repetirajuća instrukcija ponovo izvršiti.

Postavljanje flegova

U tabelama koje slede biće opisano postavljanje statusnih flegova: OF, CF, AF, SF, ZF, PF i nekih od kontrolnih flegova: DF, IF, TF.

Instrukcija

OF

CF

AF

SF

ZF

PF

ADD ADC SUB SBB

+

+

+

+

+

+

CMP NEG CMPS SCAS

+

+

+

+

+

+

INC DEC

+

-

+

+

+

+

MUL IMUL

+

+

?

?

?

?

DIV IDIV

?

?

?

?

?

?

DAA DAS

?

+

+

+

+

+

AAA AAS

?

+

+

?

?

?

AAM AAD

?

?

?

+

+

+

AND OR XOR TEST

0

0

?

+

+

+

SHL SHR (jedinično)

+

+

?

+

+

+

SHL SHR (promenljivo)

?

+

?

+

+

+

SAR

+

+

-

-

-

-

ROL ROR RCL RCR (jedinično)

+

+

-

-

-

-

ROL ROR RCL RCR (promenljivo)

?

+

-

-

-

-

POPF POPFD IRET IRETD

+

+

+

+

+

+

SAHF

-

+

+

+

+

+

CLC

-

0

-

-

-

-

STC

-

1

-

-

-

-

CMC

-

*

-

-

-

-

BT BTS BTR BTC

-

+

-

-

-

-

BSF BSR

-

-

-

-

+

-

SHLD SHRD

?

+

?

-

-

-

Legenda.

 

+

pogađa tj. utiče

1

postavlja (vrednost postaje 1)

 

-

ne pogađa tj. ne utiče;

0

briše (vrednost postaje 0)

 

?

nedefinisan

*

komplementira

Instrukcija

DF

IF

TF

 

POPF POPFD IRET IRETD

+

+

+

 

INT INTO

-

0

0

 

STD

1

-

-

 

CLD

0

-

-

 

STI

-

1

-

 

CLI

-

0

-

 

Napomena.

Instrukcije inkrementiranja i dekrementiranja ne utiču na CF (što se i vidi iz tabele u kojoj je opisano postavljanje statusnih flegova). Ta činjenica omogućava da se petljom (čiji opis sledi) izvrši aritmetička operacija nad dugim brojevima:

1. postavi ESI na bajt anajmanje težine u prvom operandu

2. postavi EDI na bajt anajmanje težine u drugom operandu

3. obriši fleg prenosa CF

4. izvrši ADC između bajta na koji pokazuje EDI i bajta na koji pokazuje ESI

5. inkrementiraj ESI tako da pokazuje na sledeći bajt prvog operanda

6. inkrementiraj EDI tako da pokazuje na sledeći bajt drugog operanda

7. sve dok ima još bajtova, vraćaj se na korak 4

Primećuje se da, ukoliko bi INC instrukcija u koracima 5. i 6. bila zamenjena sa instrukcijom sabiranja, ta instrukcija bi delovala na CF, pa sabiranje u koraku 4 ne bi nužno dalo korektan rezultat.

PSEUDOINSTRUKCIJE, PSEUDOOPERACIJE

Pseudoinstrukcije i pseudooperacije figurišu u asemblerskim programima, ali nisu prave instrukcije procesora, što se lako može uočiti uporednim pregledom asemblerskog koda i odgovarajućeg objektnog koda. Kako neke od pseudoinstrukcija faktički ukazuju asembleru i linkeru kako da se izvrši kreiranje izvršnog koda, to se pseudoinstrukcije ponekad nazivaju i direktivama.

Pseudoinstrukcija SEGMENT

Asembler MASM dopušta da program saopšti linkeru na koji način će biti alociran memorijski prostor u finalnom izvršnom programu.

To se postiže pseudoinstrukcijom SEGMENT. Ova pseudoinstrukcija omogućava kreiranje segmentiranog programa.

<ime segmenta> SEGMENT <tip poravnanja>][<tip kombinovanja>][ <ime klase>] (eng segment - isečak) - saopštava asembleru da otpočinje novi segment.

Parametar za određivanje tipa poravnanja može biti PARA, PAGE, WORD ili BYTE i određuje na kakvu će vrstu granice u memoriji linker smestiti početak segmenta.

Tipovi poravnanja omogućavaju da se prevaziđu ograničenja zasnovana na segmentiranoj memoriji.

 Tip poravnanja

Efekat

Adresa

PARA

PARA segment mora počinjati na granici pargrafa, tj. adresa početka segmenta mora biti daljiva sa 16D (ovo je podrazumevano poravnanje).

xxxx0H

PAGE

PAGE segment mora počinjati na granici strane, tj. adresa početka segmenta mora biti daljiva sa 256D.

xxx00H

WORD

WORD segment počinje na granici reči, tj. na parnim adresama.

xxxxYH

BYTE

BYTE segment može početi bilo gde.

xxxxxH

Pseudoinstrukcija SEGMENT može biti praćena sa još dve opcione vrednosti, koje određuju vrstu kombinovanja segmenata i ime klase.

Jedan segment može biti kombinovan sa drugim segmentima u istom modulu i/ili sa segmentima koji su definisani u drugim modulima. Kada se iskombinuju, ti segmenti će obrazovati jedan fizički segment koji se smešta u memoriju i na koji ukazuju segmentni registri krajnjeg izvršnog programa. Tip kombinovanja (onda kada postoji) može biti: PUBLIC, STACK, COMMON, MEMORY, AT.

Sledeća tabela sumarno prikazuje tipove kombinovanja:

Način kombinovanja

Efekat

ne postoji

Segmenti se ne kombinuju (ovo je podrazumevano kombinovanje).

PUBLIC

Svi PUBLIC segmenti sa istim imenom se pri linkovanju spajaju u jedan fizički segment (nadodajući se jedan na drugi).

STACK

Svi STACK segmenti sa istim imenom tretiraju se kao da su PUBLIC. Linker zahteva da postoji bar jedan STACK segment. Pokazivač steka (E)SP se inicijalizuje na dužinu segmenta. Segmentni registar SS se automatski postavlja.

COMMON

Svi COMMON segmenti sa istim imenom počinju od iste fizičke adrese i na taj način zauzimaju zajednički prostor. Dužina COMMON segmenta biće jednaka daužini najvećeg među COMMON segmentima.

MEMORY

MEMORY segment se smešta u memoriju u adresama višim od ostalih segmenata. Ako nekoliko segmenata ima tip kombinovanja MEMORY i zajedno su linkovani, tada prvi na koji se pri linkovanju naišlo se smatra takvim, dok se sa ostalim radi kao sa COMMON segmentima.

AT <izraz>

Segment je smešten na poziciju čija je apsolutna segmentna adresa zadata izrazom

Sledeća slika predstavlja ilustraciju prethodno prikazanih tipova kombinovanja:

Pre kombinovanja od strsna linkera

 

Posle kombinovanja od strane linkera

Prvatni

segmenti

PUBLIC

STACK

COMMON

MEMORY

Parametar ime klase sastoji se od imena uokvirenog apsotrofima (npr. ‘TIMER’). Kada se iz individualnog modula konstruiše izvšni program, linker će zajedno grupisati segmente sa istom vrednošću parametra ime klase, tako da će ti segmenti zauzeti lokacije u kontinuitetu. Segmenti će, unutar dela memorije koji je dodeljen klasi, biti smešteni onim redom kako na njih nailazi linker tokom povezivanja.

Tako, svim programskim segmentima se može dati klasno ime ‘CODE’, dok se klasno ime ‘DATA’ može dati svim segmentima podataka, a klasno ime ‘STACK’ svim stek-segmentima u raznovrsnim modulima, u zavisnosti da li tip kombinacije omogućava da to ima smisla.

Primer.

Sledeći segment ima klasno ime OURDATA:

DATA SEGMENT ‘OURDATA’

Napomena.

Pseudoinstrukcija SEGMENT može uključiti ma koju kombinaciju tipova poravnanja, tipova kombinovanja i parametara imena klase. Uobičajeno je da redosled bude kao u sledećem kodu:

MY_SEGMENT SEGMENT PARA COMMON ‘VIDEO’

MY_SEG SEGMENT AT 3CB0H ‘DISPLAY’

CODE SEGMENT BYTE ‘EXAMPLE’

Pseudoinstrukcija GROUP

Ova pseudoinstrukcija dopušta programeru da instruiše linker kako bi ovaj sakupio listu segmenata koji će se naći u jednom fizičkom segmentu. Pri tome asembler ne proverava da li je suma veličina segmenata u grupi prevazišla limit koji predstavlja veličina fizičkog segmenta.

<ime grupe> GROUP <ime segmenta><ime segmenta>} (eng group - grupa) - saopštava asembleru da koji se sve segmenti sadrže u grupi.

Primer.

Neka jedan od modula sadrži sledeći kod:

SMALL_MEMEORY GROUP CODESEG1, CODESEG2

CODESEG1 SEGMENT

      ASSUME CS:SMALL_MEMEORY

         .

         .

         .

CODESEG1 ENDS

CODESEG2 SEGMENT

      ASSUME CS:SMALL_MEMEORY

         .

         .

         .

CODESEG2 ENDS

END

Neka se, istovremeno, u drugom modulu nalazi sledeći kod:

SMALL_MEMEORY GROUP OTHER_MODULE_SEG

OTHER_MODULE_SEG SEGMENT

      ASSUME CS:SMALL_MEMEORY

         .

         .

         .

OTHER_MODULE_SEG ENDS

END

Na ovaj način su sva tri segmenta skupljena u isti fizički prostor, a pod imenom SMALL_MEMORY. Kad je jednom na ovaj način definisana grupa, njeno ime može biti korišćeno kao bilo koje drugo ime segmenta.

Pseudooperatori

Operatori koji vraćaju vrednost

Operatori SEG, OFFSET i TYPE

Memorijski objekti (promenljive i labele) imaju tri atributa: segment, offset i tip. Operatori iz ove grupe za odgovarajući memorijski objekat vraću vrednost njegovog atributra

SEG <memoriski objekat> (eng. segment - isečak) - vraća ceo 16-bitni broj koji predstavlja segmentnu adresu memorijskog objekta.

Primer.

Instrukcija

MOV BX, SEG RUN_ERR

će pri asembliranju biti prevedena u instrukciju ekvivalentnu sa

MOV BX, n

gde je n broj tj. fikirana vrednost - segmentna adresa promenljive RUN_ERR.

OFFSET <memoriski objekat> (eng. offset - pomeraj) - vraća ceo broj koji predstavlja broj bajtova između memorijskog objekta i početka segmenta u kom je definisan taj objekat.

TYPE <memoriski objekat> (eng. type - tip) - vraća broj bajtova koje zauzima podatak na koji se u instrukciji referiše.

Primer.

Neka asemblerski kod sadrži sledeće pseudoinstrukcije i instrukcije:

NEW_CENT DW 2000D

MOV AX, TYPE NEW_CENT

Poslednja (i jedina) instrukcija će pri asembliranju biti prevedana u instrukciju ekvivalentnu instrukciji

MOV AX, 2

Napomena.

Jasno se uočava neophodnost da asembler, tokom svog rada, odredi segmentnu adresu, offset i tip memoriskog objekta koji figuriše u asemblerskom programu. Dakle, te veličine su konstante sa stanovišta asemblera i to pre nego što asembller pristupi generisanju koda.

Operatori LENGTH i SIZE

Ovi operatori dopuštaju programeru da izbegne računanje broja bajtova koje zauzima dugačka ili složena struktura podataka. Preciznije rečeno, to računanje se prepušta asembleru.

LENGTH <memoriski objekat> (eng. length - dužina) - vraća broj podobjekata koje obuhvata komplekan objekat na koji se u instrukciji referiše.

Korišćenjem ovih operatora se smanjuje obim izračunavanja tokom rada programa, čime je smanjena mogućnost greške. Na ovaj način takođe se smanjuje i zavisnost instrukcija programa od konkretnih konstanti.

Primer.

Ako je:

SA DB 80H DUP(0)

DA DW 100H DUP(1924D)

Pri asembliranju instrukcija:

MOV AX, LENGTH SA

MOV BX, LENGTH DA

biće dobijen objekt kod koji sadrži instrukcije ekvivalentne sa:

MOV AX, 80H

MOV BX, 100H

Ukoliko je, iz nekih razloga, potrebno imatis veći niz SA, tada se pseudooperacija DB može promeniti, a da to uopšte ne utiče na izmene u kodu za instrukciju MOV AX, LENGTH SA.

Primer.

Sledeći fragment programa realizuje kopiranje niska ASTRING u nisku BSTRING.

MOV SI, OFFSET ASTRING

MOV DI OFFSET BSTRING

MOV CX LENGTH ASTRING

CLD

REP MOVSB

SIZE <memoriski objekat> (eng. size - veličina) - vraća proizvod operatora LENGTH i TYPE, tj. broj bajtova koje zauzima komplekan objekat.

Primer.

Instrukcije

MOV AX, SIZE SA

MOV BX, SIZE DA

će biti asemblirane u objekt kod ekvivalentan sa instrukcijama

MOV AX, 80H

MOV BX, 200H

Ipak, korišćenje ovih pseudooperatora ne sme biti univerzalno.

Primer.

Ako je:

TEST_VALUES DB 2,4,6,8,0AH, 0CH, 0EH

MOV AX, LENGTH TEST_VALUES

MOV BX, TYPE TEST_VALUES

MOV CX, SIZE TEST_VALUES

poslednje tri instrukcije će biti asemblirane kao

MOV AX, 1

MOV BX, 1

MOV CX, 1

jer ime TEST_VALUES u ovom slučaju referiše samo na prvi definišući bajt.

Aritmetički operatori

Neka treba izračunati vrednost izraza u kom figurišu isključivo konstantne vrednosti (nijedan od operanada u izrazu nije promenljiv).

Primer.

Neka treba izračunati vrednost izraza (40*32*15)/6, jer on npr. predstavlja indeks traženog člana niza. Asebler dopušta da se ovakav izraz javi kao operand instrukcije i na taj način programer biva pošteđen izračunavanja njegove vrednosti. Stoga je sasvim korektna sledeća instrukcija:

MOV CX, (40D*32D*15D)/6D

Ta instrukcija će biti asemblirana u ekvivalent

MOX CX, 0B6H

tj. u instrukciju

MOV CX, 3200D

U aritmetičke operatore spadaju:

HIGH <operand> (eng. high - visok) - vraća gornji bajt reči operanda.

LOW <operand> (eng. low - nizak) - vraća donji bajt reči operanda.

<operand 1> * <operand 2> - računa proizvod operanada.

<operand 1> / <operand 2> - računa celobrojni količnik operanada.

<operand 1> MOD <operand 2> - računa ostatak pri deljenju prvog operanda sa drugim.

<operand 1> SHL <operand 2> - računa prvi operand šiftovan ulevo za onoliko bitova kolika je vrednost drugog operanda.

<operand 1> SHR <operand 2> - računa prvi operand šiftovan udesno za onoliko bitova kolika je vrednost drugog operanda.

<operand 1> + <operand 2> - računa zbir operanada.

<operand 1> - <operand 2> - računa razliku operanada.

+ <operand> - potvrđuje znak operanada.

- <operand> - menja znak operanada.

Primer.

Ilustruje korišćenje aritmetičkih operatora kod asemblerskih instrukcija:

MOV AL, LOW(0ABC1H)

CMP DX, (132*15)/3 MOD 4

CMP AH, 14H SHR 6

MOV AL, RECORD_START+2

Primer.

Instrukcije

MOV AX, 100H MOD 17D

MOV BX, 0EFH SHL 2

će pri asembliranju biti prevedene u isti kod kao instrukcije

MOV AX, 1

MOV BX, 0BCH

Relacioni operatori

Binarna relacija je neki podskup direktnog proizvoda dva skupa. Dakle, za svaki par elemenata se može utvrditi da li su oni u relaciji (odgovor je tada true) ili nisu (odgovor je false). Kod relacionih operatora u asemblerskom jeziku, logička konstanta true je predstavljena binarnim brojem koji se sastoji isključivo od jedinica, dok je logička knstanta false predstavljena nulom.

Relacioni operatori su:

<operand 1> EQ <operand 2> (eng. equal - jednako) - određuje da li su operandi međusobno jednaki.

<operand 1> NE <operand 2> (eng. not equal - različito) - određuje da li su operandi međusobno različiti.

<operand 1> LT <operand 2> (eng. less than - manji od) - određuje da li je prvi operand manji od drugog.

<operand 1> LE <operand 2> (eng. less than or equal- manji ili jednak sa) - određuje da li je prvi operand manji ili jednak sa drugim.

<operand 1> GT <operand 2> (eng. greater than - veći od) - određuje da li je prvi operand veći od drugog.

<operand 1> GE <operand 2> (eng. greater than or equal- veći ili jednak sa) - određuje da li je prvi operand veći ili jednak sa drugim.

Primer.

Instrukcije

MOV AL, 16 LT 17

MOV DL, 5EH GT 6EH

su ekvivalentne sa:

MOV AL, 0FFH

MOV DL, 0

Logički operatori

Asembler MASM dopušta da izrazi sadrže operatore NOT, AND, OR i XOR. Značenje ovih operatora je isto kao značenje odgovarajućih bitovnih logičkih instrukcija.

Dakle,

<operand 1> AND <operand 2> (eng. and - i) - izračunava se bitovna konjukcija operanada.

<operand 1> OR <operand 2> (eng. or - ili) - izračunava se bitovna disjunkcija operanada.

<operand 1> XOR <operand 2> (eng. exclusive or - ekskluzivno ili) - izračunava se bitovna ekskluzivna disjunkcija operanada.

NOT <operand> (eng. not - ne) - izračunava se bitovna negacija operanda.

Primer.

Instrukcije:

MOV DL, 3EH OR 0FEH

MOV BH, NOT 15H

MOV CL, 22H AND OABH

su ekvivalentne sa:

MOV DL, 0FEH

MOV BH, 0EAH

MOV CL, 22H

Napomena.

U instrukcijama i izrazima je moguće kombinovati raznovrsne operatore:

CO_ORD_ADR DW OFFSET MY_LOC+(22H*2)

Operatori koji postavljaju ili prevazilaze vrednosti

U ovu grupu pseudooperatora spadaju PTR, SHORT i THIS. Svaki od ovih operatora dopušta da postojeća definicija podataka bude na neki način prevaziđena.

Pored ovih operatora, u istoj grupi se nalazi još i segmentni prefiks.

<tip> PTR <operand> (eng. pointer - pokazivač) - dopušta da se komponente operanda tretiraju u skladu sa tipom - kao reči, bajtovi, dvostruke reči.

Primer.

Dvosmislenost kao kod instrukcije:

INC [BX]

može biti prevaziđena na sledeći način:

INC WORD PTR [BX]

Primer.

Instrukcija u asemblerskom kodu:

MY_WORD DW 4142H

     .

     .

     .

MOV AX, BYTE PTR MY_WORD

će biti asemblirana u ekvivalent od

MOV AX, 41H

Primer.

Korićenje operatora PTR kod skokova:

NEAR_LOOP:

   ADD AX, BX

   MOV DX, AX

         .

         .

         .

JMP NEAR_LOOP

         .

         .

         .

   FAR_LOOP EQU FAR PTR NEAR_LOOP

   JMP FAR_LOOP

THIS <tip> (eng. this - ovo) - dopušta da dva podatka definisana pseudooperaci­jama tako da zauzimaju uzastopne bajtove budu tumačeni u skladu sa tipom.

Operator THIS mora biti praćen tipom, tj. jednom od reči BYTE, WORD, DWORD, FWORD, QWORD, TBYTE, NEAR, FAR, PROC.

Primer.

Ilustruje kako se može dopustiti pristup sadržaju uzastopnih lokacija FIRST_BYTE i SECOND_BYTE i kako se one mogu tretirati kao jedna reč:

AB_WORD EQU THIS WORD

FIRST_BYTE DB 41H

SECOND_BYTE DB 42H

Primer.

Ilustruje kako se mogu oformiti alternativne labele za iste adrese, od kojih je jedna NEAR, a druga FAR:

FAR_LOOP EQU THIS FAR

NEAR_LOOP:

   ADD AX, 2

SHORT <odredište> (eng. short - kratak) - zahteva da odredište skoka bude enkodirano u kratkoj formi.

Jasno je da operator SHORT mora biti praćen valjanim imenom labele. Neophodno je i da ta labela bude u istom segmentu gde se nalazi i instrukcija u kojoj figuriše ovaj operator.

Primer.

Instrukcija

JMP SHORT NEXT_BLOCK_LABEL

je dopuštena samo ako je labela NEXT_BLOCK_LABEL u istom segmentu u kom je i instrukcija JMP.

<segmentni registar>: - segmentni prefiks omogućuje prevazilaženje segmenata, pa se podacima koji se nalaze u jedno segmentu može pristupiti i iz drugih segmenata.

Primer.

Instrukcija

MOV AL, ES:A_BYTE

će biti asemblirana tako da se sadržaj AL napuni iz lokacije čija je segmentna adresa u u registru ES, a koja ima isti ofset od početka segmenta na koji ukazuje ES kao što je ofset lokacije A_BYTE u segmentu u kom je ona definisana.

Operatori za definiciju podataka

U ovu grupu spadaju: LABEL, DB, DW, DD, DQ, DT, EQU, =

<ime> LABEL <tip> (eng. label - naziv) - definiše labelu.

Primer.

Ilustruje kako se može dopustiti pristup sadržaju uzastopnih lokacija FIRST_BYTE i SECOND_BYTE i kako se one mogu tretirati kao jedna reč:

AB_WORD LABEL WORD

FIRST_BYTE DB 41H

SECOND_BYTE DB 42H

Primer.

Ilustruje kako se niz reči po potrebi može posmatrati i kao niz bajtova:

ARRAYB LABEL BYTE

ARRAYW DW 100 DUP(?)

      .

      .

      .

ADD AL, ARRAYB[99]

ADD AX, ARRAYW[49]

Pretposlednja instrukcija dodaje 100-ti bajt niza na AL, a  poslednja dodaje 50 tu reč niza na AX.

Primer.

Ilustruje kako se mogu oformiti alternativne labele za iste adrese, od kojih je jedna NEAR, a druga FAR.

FAR_LOOP LABEL FAR

NEAR_LOOP:

   ADD AX, 2

DB <izraz> (eng. define byte - definiši bajt) - rezerviše bajt u memoriji i inicijalizuje vrednost tog bajta na izraz.

DW <izraz> (eng. define word - definiši reč) - rezerviše reč u memoriji i inicijalizuje vrednost te reči na izraz.

DD <izraz> (eng. define double word - definiši dvostruku reč) - rezerviše dvostruku reč u memoriji i inicijalizuje vrednost te dvostruke reči na izraz.

DQ <izraz> (eng. define quoter word - definiši četvorostruku reč) - rezerviše četvorostruku reč u memoriji i inicijalizuje vrednost te četvorostruke reči na izraz.

Primer.

Ilustruje kako se na desnoj strani može javiti bilo kakav izraz. Sledeći kod je sasvim korektan

TEST:

   MOV AX, BX

        .

        .

        .

OFF_TEST DW TEST

Njime je u memorijsku lokaciju OFF_TEST smešten ofset labele TEST. Još treba istaći i da redosled pojave labele TEST i lokacije OFF_TEST ne utiče na korektnost koda.

Dakle, potpuno je ispravan i sledeći kod:

OFF_TEST DW TEST

        .

        .

        .

TEST:

   MOV AX, BX

<ime> EQU <izraz> (eng. equal - jednako) - definiše simboličku konstantu (koja se ne može redefinisati) sa nazivom ime i njenu vrednost postavlja na izraz.

Primer.

Ilustruje kako se pseuudoinstrukcija EQU može koristiti za definisanje svojih mnemonika. Pri asembliranju koda:

PREMESTI EQU MOV

ADRESA EQU DS:[BP]

INICIJALIZACIJA EQU AX,DX

PREMESTI INICIJALIZACIJA

PREMESTI AX, ADRESA

dobiće se isto što bi se dobilo asembliranjem instrukcija:

MOV AX,DS

MOV AX,DS:[BP]

<ime> = <izraz> - definiše simboličku konstantu (koja se može redefinisati) sa nazivom ime i njenu vrednost postavlja na izraz.

Primer.

Ilustruje korišćenje pseudooperatora EQU i =:

CR=0DH ;carriage return

      .

      .

      .

CR=0H ;current record

CR=CR+1 ;uvecava vrednost current record

      .

      .

      .

CR EQU 0H ;illegal redefinition

CR EQU CR+1 ;illegal redefinition

Tabela prioriteta operatora

Kao uvek pri evaluaciji izraza, prvo se izračunavaju operatori sa najvećim prioritetom. Zagradama se može promeniti prioritet izvršenja operacija. Prioritet operatora u izrazima je prikazan tabelom koja sledi. Operator SHORT ima najmanji prioritet, a operatoori u istom redu tabele imaju jednak prioritet.

LENGTH SIZE

Operator prevazilaženja segmenta

PTR OFFSET SEG TYPE THIS

HIGH LOW

* / MOD SHL SHR

+ - (binarni i unarni)

EQ NE LT LE GT GE

NOT

AND

OR XOR

SHORT

Pseudoinstrukcije EXTRN, PUBLIC

EXTRN <ime> (eng. extern - spoljašnji) - saopštava asembleru da objekat sa datim imenom nije definisan u izvornom kodu koji se upravo asemblira, već u nekom drugom modulu.

Stoga asembler nije u mogućnosti da za takvo simboličko ime generiše offset tj. adresu, već u objekt kodu stavlja oznaku koja ukazuje linkeru da tu treba da uspostavi vezu.

PUBLIC <ime> (eng. public - javan) - saopštava asembleru da objekat sa datim imenom definisan u izvornom kodu može da se koristi i u drugim modulima.

Pseudoinstrukcije .RADIX, DUP, NAME, END

Asembler dopušta da se brojevi u programu specificiraju kao binarni, dekadni ili heksadekadni. Programer može eksplicitno (korišćenjem sufiksa B, D, H) specificirati da li da asembler nisku cifara tumai kao binarni, dekadni ili heksa broj.

Postavlja se pitanje: Ako niska nema sufiks, kako asembler određuje da li će vršiti konverziju u binarni, dekadni ili heksadekadni broj?

.RADIX <izraz> (eng. radix - osnova) - naređuje da se prilikom asembliranja niske bez sufiksa konvertuju u brojeve čija je osnova data kao parametar ove pseudoinstrukcije.

Dakle, parametar pseudoinstrukcije .RADIX je izraz čija je vrednost neki od brojeva 2, 10, 16. Operandi u izrazu moraju biti konstante čija je vrednost poznata asembleru u trenutku kada on asemblira direktivu .RADIX.

[<izraz1>] DUP(<izraz2>) - naređuje da se prilikom asembliranja u memoriju onoliko puta koliko iznosi vrednost izraza ispred pseudoinstrukcije DUP smesti vrednost izraza u zagradama. Ako izraz ispred direktive DUP ne postoji, podrazumeva se da je njegova vrednost 1.

Pseudoinstrukcija NAME služi za davanje imena asemblerskom programu.

NAME <ime> (eng. name - ime) - postavlja naziv asemblerskog programa.

Ako u asemblerskom programu nema direktive NAME, tada se naziv određuje kao prvih šest slova imena datoteke u kojoj se nalazi program.

Pseudoinstrukcija END služi za ukazivanje na kraj asemblerskog koda. Njom se specificira i tzv. ulazna tačka programa tj. simbolička adresa od koje će početi izvršavanje programa.

END [<ime>] (eng. end - kraj) - završava asemblerski kod i određuje ulaznu tačku programa.

Pseudoinstrukcija ASSUME

Za MASM je (zbog mehanizama specificiranja adresa u obliku segent:offset) od ogromnog značaja da ima informaciju koji će se segmentni registar koristiti kako pri adresiranju instrukcija, tako pri adresiranju podataka.

ASSUME <segmentni registar>:<ime><segmentni registar>:<ime>} (eng. assume - preuzmi) - informiše asembler o asocijaciji između segmenata i segmentnih registara.

Parametar ime koje figuriše u ovoj pseudoinstrukciji može biti: ime segmenta prethodno definisano pomoću direktive SEGMENT; ime grupe prethodno definisano pomoću direktive GROUP; reč NOTHING; izraz kom prethodi pseudooperator SEG; izraz koji evaluiranjem daje ime segmenta ili ime grupe

Asocijacija se može kontrolisati bilo novim ASSUME pseudoinstrukcijama, bilo operatorom prevazilaženja segmenta.

Primer.

Sledeći program ilustruje korišćenje pseudooperacije ASSUME:

DATA SEGMENT

   DATA_BYTE DB 414

DATA ENDS

 

EXTRA SEGMENT

   SCREEN_DISPLAY DB 2000H DUP(?)

EXTRA ENDS

 

CODE SEGMENT

ASSUME CS:CODE, DS:DATA, ES:EXTRA

   MOV AX, DATA

   MOV DS, AX

   MOV ES, AX

   MOV AL, DATA_BYTE

   MOV SCREEN_DISPLAY, AL

ASSUME DS:DATA, ES:DATA

      .

      .

      .

NEXT_LETTER:

   INC DATA_BYTE

            .

            .

            .

   MOV AX, EXTRA

   MOV DS, AX

   JMP NEXT_LETTER

      .

      .

      .

CODE ENDS

END

U ovom je primeru, zbog ASSUME pseudoinstrukcije, asembleru bilo poznato da SCREEN_DISPLAY u instrukciji

MOV SCREEN_DISPLAY, AL

referiše na lokaciju u segmentu na čiju adresu ukazuje ES, pa će asembler generisati prevazilaženje segmenta tako da će biti korišćen ES, a ne DS.

Isti efekat se mogao postići operatorom prevazilaženja segmenta, tako da bi bila korektna i sledeća instrukcija :

MOV ES:SCREEN_DISPLAY, AL

Naravno, ako bi se tako radilo, tada za svaku od instrukcija u kojoj ima prevazilaženja segmenta, mora eksplicitno da se koristi operator prevazilaženja segmenta.

Pri korišćenju ASSUME pseudoinstrukcije jednom uspostavljeno pridruživanje važi sve dok ga ne zameni neko drugo.

Ponekad nije moguće znati šta će biti u nekom segmentnom registru kada se izvrši određena instrukcija, što može dovesti do komplikacija. Za takve komplikacije je u MASM-u obezbeđena specijalna forma ASSUME pseudoinstrukcije, oblika ASSUME NOTHING.

Primer.

U programu iz prethodnog primera, prvi put kada se izvrši instrukcija INC sve će biti u redu (jer DS pokazuje na segment u kome se nalazi DATA_BYTE): Međutim, sledeće instrukcije postavljaju DS tako da pokazuje na EXTRA segment, pa će se po izvršenju JMP instrukcije instrukcija INC izvršavati sa nekorektno postavljenim DS-om.

Ako se napiše:

   ASUME DS: NOTHING

NEXT_LETTER:

   INC DATA_BYTE

problem je rešen. Pseudoinstrukcija

ASSUME DS:NOTHING

saopštava asembleru da od te tačke nadalje ne treba pretpostavljati da DS referiše na bilo koji od imenovanih segmenata. Po nailasku na instrukciju

INC DATA_BYTE

MASM traži da vidi koji imenovani segmešta programeru da preciznije kontroliše tok asembliranja.nt sadrži DATA_BYTE. Odgovor je DATA, pa MASM potom saznaje da li postoji trenutna pretpostavka o registru koji se može koristiti za adresiranje DATA segmenta. U ovom slučaju postoji, jer iako je ASSUME DS:NOTHING, istovremeno je i ASSUME ES:DATA. Kako INC instrukcija koristi registar DS kao podrazumevani, to će ovde MASM automatski generisati prevazilaženje segmenata, pa će se

instrukcija inkrementacije asemblirati kao

INC ES:DATA_BYTE

Pseudoinstrukcije ORG, EVEN, INCLUDE i pseudooperator $

Pseudoinstrukcija ORG dopušta programeru da preciznije kontroliše tok asembliranja. Naime, prilikom asembliranja se stalno ažurira vrednost promenljive brojač lokacija, koja sadrži na offset memorijskog objekta u odnosu na početak asembliranog segmenta (način rada asemblera i linkera biće opisan u posebnom poglavlju).

ORG <izraz> (eng. origin - poreklo, koren) - naređuje da se prilikom asembliranja brojač lokacija postavi na evaluiranu vrednost izraza.

Primer.

Pseudoinstrukcija

ORG 200H

postavlja vrednost brojača lokacija na ofset 200H (=512D) u odnosu na početak segmenta koji sadrži ovu pseudoinstrukciju.

Asembler MASM dopušta da programer pristupi (tj. da sazna) tekuću vrednost brojača lokacija. Ta vrednost je sa stanovišta asemblera konstantna, i može figurisati u izrazima.

$ - vraća tekuću vrednost brojača lokacije.

Primer.

Pseudoinstrukcija

ORG $+2

uvećava vrednost brojača lokacija za 2.

Primer.

U sledećem segmentu koda

MY_CODE SEGMENT

   START_BROJAC = $

      .

      .

      .

   MOV BX, AX

   ADD CX, [BX]

      .

      .

      .

DUZ_KOD=$-START_BROJAC+1

MY_CODE ENDS

se simbolička konstanta DUZ_KOD postavlja na broj bajtova koji zauzima asemblirani segment MY_CODE.

Već je istaknuto da se u okviru izraza koji se javlja u pseudoinstrukciji ORG smeju naći samo konstantne vrednosti. Međutim, to je potreban uslov za korektnost izraza. Dovoljan uslov zahteva da veličine koje figurišu u izrazu budu poznate već u prvoj fazi asembliranja, čim asembler naiđe na pseudoinstrukciju. Uslov korektnosti je pooštren zato što već u prvom prolasku asembler mora oformiti i čuvati relativne ofsete onim redom kako na njih nailazi, tj. određene reference moraju biti poznate asembleru već u prvoj fazi asembliranja.

Primer.

Sledeći segment programa je nekorektan:

ORG OFFSET LATER + 15

   MOV AL, 5

      .

      .

      .

LATER:

   MOV AX, BX

pa će se prilikom asembliranja pojaviti poruka oblika: Must be declared in PASS 1.

S druge strane, sledeći programski segment je sasvim kotrektan:

MOV AL, 5

      .

      .

      .

LATER:

   MOV AX, BX

ORG OFFSET LATER + 15

Napomena.

Kod pseudoinstrukcija .RADIX i DUP izrazi koji figurišu u njima takođe moraju biti poznati u prvoj fazi asembliranja (preciznije iskazano, moraju biti poznati kada asembler prilikom asembliranja naiđe na njih).

Pseudoinstrukcija EVEN takođe omogućuje da programer u okviru asemblerskog koda utiče na vrednost brojača lokacija prilikom asembliranja.

EVEN (eng. even - paran) - naređuje da se prilikom asembliranja brojač lokacija postavi na sledeću parnu adresu.

Kod procesora 8086 nije bilo svejedno da li reč otpočinje na parnoj ili neparnoj adresi, pa se reč koja počinje od neparne adrese morala uzimati u dva koraka, bajt po bajt.

Pseudoinstrukcija INCLUDE je dizajnirana radi eliminisanja potrebe za ponavljanjem sekvenci instrukcija koje su zajedničke za više asemblerskih datoteka, kao šro su datoteka sa definicijama makroa, ili skup rezultata merenja izražen kao segment podataka.

INCLUDE <ime> (eng. include - uključi) - naređuje da se prilikom asembliranja, od mesta pojave pseudoinstrukcije, u izvorni kod uključi sadržaj tekstualne datoteke čije je ime parametar pseudoinstrukcije.

Primer.

Pseudoinstrukcija

INCLUDE ISKAZI.ABC

prouzrokuje da asembler sadržaj datoteke ISKAZI.ABC prekopira u izvorni program na mesto gde se nalazi pseudoinstrukcija (direktiva) INCLUDE.

Pseudoinstrukcije za kontrolisanje izlaza pri asembliranju

U ovu grupu pesudoinstrukcija spadaju: PAGE, TITLE, SUBTTL, .LIST, .XLIST, %OUT. One nisu neophodne pri pravljenju manjih programa, ali su nezaobilazne kod velikih projekata, u kojima učestvuje više programera.

PAGE [<izraz>,<izraz>] đ PAGE + (eng. page - strana) - podešava visinu i širinu stranice u asemblerskom listingu, ili ubacuje znak za kraj strane u tekuću stranu asemblerskog listinga, ili prelazi na sledeće poglavlje u listingu.

Prvi parametar je izraz čija je vrednost između 10 i 255 i on predstavlja visinu stranice, dok se vrednost drugog parametra, koji predstavlja širinu stranice, kreće u opsegu 60-132. Podrazumevane vrednosti visine i širine stranice su 64 i 80. Dakle, ukoliko se vrednosti visine i širine stranice ne specificiraju korišćenjem pseudoinstrukcije PAGE, stranica listinga će sadržati 64 kolone sa maksimalno 80 znakova u koloni.

Do uvećavanja rednog broja strane i prelaska na sledeću stranu listinga može doći bilo zato što se napunila tekuća strana, ili zato što je pri asembliranju asembler naišao na pseudoinstrukciju PAGE koju nisu pratili argumenti. Dakle, korišćenjem pseudoinstruk­cije PAGE bez argumenata prelazi se na sledeću stranu.

Ukoliko asembler naiđe na PAGE+ prelazi se na sledeću stranu, uvećava se redni broj poglavlja, a redni broj stranice se postavlja na 1.

TITLE <niska> (eng. title - naslov) - postavlja naslov u asemblerskom listingu.

Niska koja prestavlja naslov može sadržati najviše 60 znakova. Ovako specificirani naslov će se pojavljivati u prvoj liniji na svakoj strani listinga. Ako naslov nije specificiran pomoću direktive TITLE, tada će se u prvoj liniji listinga naći naziv dat korišćenjem direktive NAME. Ukoliko se u izvornom kodu ne koristi ni pseudoinstrukcija NAME ni TITLE, tada se sadržaj prve linije na svakoj strani dobija od naziva datoteke u kojoj se nalazi kod.

SUBTTL <niska> (eng. subtitle - podnaslov) - postavlja podnaslov u asemblerskom listingu.

Niska koja prestavlja podnaslov može sadržati najviše 60 znakova. Podnaslov će se pojavljivati u liniji ispod naslova u zaglavlju svake od strana listinga.

Napomena.

Prestanak štampanja podnaslova može da sepostigne korišćenjem pseudoinstrukcije

 SUBTTL

bez argumenata (tj. tada se podrazumeva da je argument prazna niska).

Sledeće dve pseudoinstrukcije omogućavaju, odnosno onemogućavaju formiranje listinga pri asembliranju.

.LIST (eng. include listing - uključi listing) - naređuje da se prilikom asembliranja, od mesta pojave pseudoinstrukcije, generiše asemblerski listing.

.XLIST (eng. exclude listing - isključi listing) - naređuje da se prilikom asembliranja, od mesta pojave pseudoinstrukcije, ne generiše asemblerski listing.

Dakle, naređenje specificirano jednom od ovih direktiva traje sve dok asembler opet ne naiđe na jednu od ove dve pseudoinstrukcije, ili dok se ne završi proces asembliranja. Ako nema ni jedne ni druge pseudoinsrtukcije u izvornom kodu, asemblerski listing će biti generisan.

Sledeća pseudoinstrukcija dopušta programeru da se tokom asembliranja, u tačkama koje on izabere, prikažu željene poruke.

%OUT <niska> (eng. out - napolje) - naređuje asembleru da, kada naiđe na ovu pseudoinstrukciju, na izlaz pošalje nisku.

Primer.

Kada asembler u izvornom programu naiđe na pseudoinstrukciju:

%OUT pred asembliranjem procedure CALC

tada će se na ekranu pojaviti poruka:

pred asembliranjem procedure CALC

Pojednostavljene direktive

Kao što im samo ime kaže, ove pseudoinstrukcije omogućavaju pojednostavljeno kreiranje asemblerskog koda.

.MODEL <model memorije>[[,<jezik>],<tip steka>] - definiše oblik modula i olakšava zajednički rad asemblerskih procedura u modulu i programa napisanih u nekom od viših programskih jezika.

Parametar model memorije definiše segmentnu strukturu modula.On može uzeti neku od vrednosti: TINY, SMALL, MEDIUM, COMPACT, LARGE, HUGE.

Parametar jezik definiše kave konvencije imenovanja, pozivanja i povratka pretpostavlja korišćenje direktive PROC. Jezik može biti: C, Pascal, FORTRAN, BASIC.

Parametar tip steka određuje da li će asembler pri generisanju koda pretpostaviti da je SS=DS, tj. da li je stek deo segmenta podataka. Ako je vrednost ovog parametra nearStack, tada se pretpostavlja da je stek deo segmenta podataka, pa je SS=DS i SP pokazuje na vrh zone podataka.Ako je vrednost ovog parametra farStack, tada asembler pretpostavlja da je segment steka i fizički odvojen od segmenta podataka.

.CODE [<ime>] (eng. code - kod) - definiše početak kodnog segmenta.

Ako se ime ne navede, za ime segmenta će se uzeti osnovno ime datoteke sa izvornim kodom.

.STACK [<veličina>] (eng. stack - stek, stog) - definiše početak segmenta steka.

.DATA (eng. data - podatak) - definiše početak segmenta bliskih (tj. near) inicijalizovanih podataka.

.FARDATA (eng. far - dalek, udaljen) - definiše početak segmenta udalljenih (tj. far) inicijalizovanih podataka.

Nova pseudoinstrukcija SEGMENT završava prethodni segmenat. Direktiva END završva poslednji segment u izvornoj datoteci.

.STARTUP (eng. start up - otpočinjanje, startovanje) - postavlja vrednosti registara DS, SS i SP tako da je DS=SS i da je tip nearStack.

Primer.

Ukazuje na način korišćenja pojednostavljenih direktiva:

EXTRN max, act:FAR ;konstante i far obelezje su bilo gde

.MODEL small,C

 

.STACK 100H

 

.DATA

EXTRN nvar:BYTE ;near promenljiva u bliskim podacima

 

.FARDATA

EXTRN fvar:WORD ;far promenljiva u udaljenim podacima

 

.CODE

.STARTUP

EXTRN task:PROC ;task je obelezje u bliskom kodu (na bliskost ukazuje proc ili near)

ASSUME ES: SEG fvar ;utvrdi adresibilnost segmenta

   ;neka ES ukazuje na udaljeni segment podataka

   MOV AX, SEG fvar

   MOV ES, AX

      .

      .

      .

   MOV AH, nvar ;napuni spoljasnju near promenljivu

   MOV BX, fvar ;napuni spoljasnju far promenljivu

   CALL task ;pozovi proceduru

   JMP act ;skoci na far obelezje

END

Strukture

Ove pseudoinstrukcije omogućavaju kreiranje i rad sa strukturama, odnosno podacima koje se sastoje od raznorodnih elemenata. Elementi jedne strukture nazivaju se polja strukture.

STRUC (eng. structure - struktura) - definiše strukturne promenljive. Ova pseudo­instrukcija obično ima sledeći oblik:

<ime strukture> STRUC

      .

      .

      .

<ime strukture> ENDS

Strukturna promenljiva je kolekcija bajtova u kojoj se specifičnoj grupi bajtova može pristupiti simbolički. Grupe bajtova mogu imati različitu veličinu, ali svaki član familije će imati isto grupisanje i simbolička imena za grupu še biti ista.

Primer.

Ilustruje korišćenje pseudoinstrukcije STRUC:

REPORT STRUC

   HEADER DB 30H DUP(‘ ‘)

   DATE DB 6D DUP(0)

   CONTENT DB 2000H DUP(‘ ‘)

REPORT ENDS

Iako asembler MASM to ne zahteva, uobičajeno je da se familija strukturnih promenljivih definiše na samom početku izvornog asemblerskog programa.Taj redosled je ovde uobičajen, a kod viših programskih jezika je zahtevan.

Po definisanju strukture, modu se pojaviti strukturne promenljive.

Primer.

Na ovaj način se oformljuju memorijski objekti sa datom strukturom

REPORT STRUC

   HEADER DB 30H DUP(‘ ‘)

   DATE DB 6D DUP(0)

   CONTENT DB 2000H DUP(‘ ‘)

REPORT ENDS

 

DATA SEGMENT

      .

      .

      .

   SALES REPORT <>

   MARKETING REPORT <>

      .

      .

      .

Napomena.

Simboli <> kod struktura SALES i MARKETING u prethodnom primeru ukazuju da se ne prevazilazi inicijalizacija data u definiciji familije, tj. definiciji strukture.

Primer.

Ilustruje prevazilaženje inicijalizacije koja je data u definiciji familije:

ADRESS STRUC

PERSON DB ‘THE OCCUPIER ’

   STREET DB ‘IF UNDELIVERED PLEASE RETURN ‘

   CITY DB ‘TO SENDER ’

   ZIPCODE DB ‘AB12 3DE ‘

   COUNTRY DB ‘UK

ADRESS ENDS

 

DATA SEGMENT

      .

      .

      .

   HOME1 ADRESS <‘Mr. J.Bloggs ‘, ‘14 Railway Cuttings ‘, ‘London ‘, ‘NW10 2AG ‘, ‘GB’>

      .

      .

      .

HOME2 ADRESS < , ‘27 Black Street ‘, ‘Brighton‘, ‘BL5  3TW ‘, >

      .

      .

      .

DATA ENDS

Uočava se da su vrednosti za polja PERSON i COUNTRY u strukturi HOME2 u stvari vrednosti određene u definiciji familije.

Pristup pojedinim poljima strukturne promenljive se, slično kao u višim programskim jezicima, realizuje primenom punktualnog operatora.

<strukturna promenljiva>.<ime polja> - vraća zadato polje u datoj strukturi.

Primer.

Ilustruje primenu operatora za pristup poljima u strukturi:

STUDENT STRUC

   NAME 30D DB DUP(‘ ‘)

   STREET 30D DB DUP(‘ ‘)

   CITY 20D DB DUP(‘ ‘)

   AGE DB 18

STUDENT ENDS

 

DATA SEGMENT

      .

      .

      .

   DOBAR STUDENT < , , , 20>

      .

      .

      .

LOS STUDENT < , , , 28>

      .

      .

      .

DATA ENDS

 

CODE SEGMENT

      .

      .

      .

   MOV AL, DOBAR.AGE

      .

      .

      .

   MOV BX, OFFSET LOS

   MOV AL, [BX].AGE

      .

      .

      .

CODE ENDS

END

Napomena.

Pristup iz prethodnog primera se ne može primeniti za polja strukturi koja nisu jednočlana. Tako, ako se posmatra struktura i promenljive iz prehodnog primera, tada je

MOV DX, OFFSET DOBAR

korektno, dok je

MOV DX, OFFSET [BX].NAME

nekorektno.

Međutim, ovaj problem može biti razrešen. Pristup ofsetu pojedinog polja u okviru zadate strukture na koju ukazuje registar BX, se može realizovati korišćenjem instrukcije LEA:

LEA DX, [BX],.NAME

Napomena.

Strukture se ne mogu ugnežđavati, tj. izmedju

<ime strukture> STRUC

      .

      .

      .

<ime strukture> ENDS

se ne sme pojaviti druga pseudoinstrukcija STRUC.

Slogovi

Dok je za najveći broj svrha za koje se koristi asemblerski jezik pogodno da se rukuje podacima grupisanim u bajtove, ponekad je neophodno rukovati podacima kao grupama bitova. Za rad sa podacima na ovakav način može se koristiti pseudoinstrukcija RECORD. Koristeći ovu pseudoinstrukciju, u asembleru se mogu deklarisati slogovne promenljive. Te promenljive su slične ostalim, s tim što se kod slogovnih specifičnoj grupi susednih bitova može simbolički pristupiti.

Ukupan broj bitova koji zauzimaju sve različite grupe ne sme da bude veći od 32 (odnosno, kod predhodnika procesora 80386, od 16).

<ime sloga> RECORD <polje>:<širina>š ,<polje>:<širina>ć (eng. record - slog) - definiše slogovne promenljive, tj. omogućava kreiranje familije promenjivih kod kojih se pojedinim grupama susednih bitova može simbolički pristupiti.

Ukupan broj bitova koji zauzimaju sve različite grupe ne sme da bude veći od 32 (odnosno, kod predhodnika procesora 80386, od 16).

Primer.

Neka se familija slog promenljivih koristi za pomoć u programiranju kolor prikaza na PC-u. Kada se (u jednom od modova) prikazuje tekst u koloru, boja teksta i boja pozadine za svaku poziciju karaktera na ekranu je određena postavljanjem bitova u okviru relevantnog bajta atribita: bitovi 0,1,2,3 određuju boju pozadine; bitovi 4, 5, 6 određuju boju teksta; dok bit 7 određuje da li će tekst blinkovati.

Deklarisanje familije slogovnih promenljivih koje bi se koristile u ovoj situaciji, realizuje se na sledeći način:

COLOR_SETTING RECORD BLINK:1, FOREGROUND:3, BACKGROUND:4

Ovim je deklarisano ime familije, te imena i veličine pojedinih bitovnih polja koja se nalaze u okviru promenljivih iz zadate familije slogovnih promenljivih.

Da bi se mogle koristiti slog promenljive iz prethodno definisane familije, asembleru se mora saopštiti ime promenljive i ime familije slogovnih promenljivih. Ukoliko je to neophodno, može se specificirati i inicijalna vrednost za promenljivu.

Primer.

Pseudoinstrukcija:

MENU COLOR_SETTING <0, 2, 3>

će inicijalizovati memorijsku promenljivu MENU dužine 8 na vrednost 00100011B.

Konvencija je da se deklaracije familija slog promenljivih, tj. RECORD pseudoinstrukcije, obično nalaze na samom početku asemblerskog programa.

Primer.

Obrazac deklarisanja slog promenjljive je, stoga, sledeći:

COLOR_SETTING RECORD BLINK:1, FOREGROUND:3, BACKGROUND:4

      .

      .

      .

DATA SEGMENT

      .

      .

      .

   MENU COLOR_SETTING <0, 2, 3>

      .

      .

      .

DATA ENDS

 

CODE SEGMENT

      .

      .

      .

CODE ENDS

END

U slogu koji se deklariše, prvo deklarisano polje biće smešteno u najznačajnije cifre, tj. na pozicije najveće težine; sledeće deklarisano polje smestiće se u sledeća desna polja, tj. u sledeća polja manje težine. Nadalje se smeštanje nastavlja na isti način, sve do poslednjeg deklarisanog polja.

Ako je zbir dužina bitovnih polja takav da se slogovna promenljva može smestiti u bajt, tada će asembler oformiti slogove koji odgovaraju bajtovima. U suprotnom, oformljeni slogovi će odgovarati rečima, odnosno dvostrukim rečima. Ukoliko je zbir dužina bitovnih polja manji od 8, odnosno 16, tj. 32, tada će polja biti desno poravnata - poslednji bit poslednjeg polja će biti smešten u bitu najmanje težine bajta, odnosno reči, tj. dvostruke reči.

Primer.

Neka asemblerski program sadrži sledeći kod:

TIME RECORD HOURS:6, MINUTES:6

      .

      .

      .

DATA SEGMENT

      .

      .

      .

   START_TIME TIME <10, 02>

      .

      .

      .

U ovom slučaju je zbir širina polja promenljive START_TIME 12 bitova, pa će asembler rezervisati reč u memoriji i polja će biti desno poravnata. Neiskorišćeni bajtovi će imati nedefinisanu vrednost. Stoga će reč čija je simbolička adresa START_TIME biti postavljena na ????001010000010B.

Napomena.

Nemoguće je definisati sledeću familiju slogovnih promenljivih:

TIME RECORD HOURS:12, MINUTES:12, SECONDS:12

Zato što zbir dužina bitovnih polja prevazilazi 32.

Ukoliko se pri deklarisanju slogovne promenljive izostavi neka vrednost u inicijalizaciji, onda sadržaj odgovarajućeg bitovnog polja neće biti inicijalizovan.

Primer.

Neka asemblerski program sadrži sledeći kod:

DATE RECORD MONTH:4, DAY:5, YEAR:7

      .

      .

      .

DATA SEGMENT

      .

      .

      .

   START_DATE DATE <10, , 91>

      .

      .

      .

U ovom slučaju se START_DATE inicijalizuje tako da polje MONTH dobije vrednost 10101, polje YEAR 1001011, dok će vrednost za polje DAY ostati neinicijalizovana.

Slično bi deklaracija

START_DATE DATE < , 1, 91>

ostaviti polje MONTH neinicijalizovanim, dok će

START_DATE DATE <10, 1, >

Ostaviti polje YEAR neinicijalizovanim. Deklaracija oblika:

START_DATE DATE < , , >

ostavlja neinicijalizovanim sva tri polja.

Isto kao što se pseudoinstrukcija DUP može koristiti zajedno sa pseudooperatorima DB, DW, DD, DQ, DT za deklaraciju više od jedne promenljive, tako se pseudoinstrukcija RECORD može koristiti za deklaraciju više od jedne promeljive iz familije slogovnih promnljivih.

Primer.

Deklaracija

MY_DATES DATE 24H DUP(<>)

Prouzrokuje da asembler rezerviše 24 reči u memoriji, od kojih na prvu referiše simbolička adresa MY_DATES. Svaka od ovih reči se može tretirati kao promenljiva tipa DATE.

Pseudoinstrukcija RECORD i skupovi

U ovom odeljku se opisuju operatori koje obezbeđuje asembler za manipulisanje sa slogovnim promenljivima. To opisivanje se realizuje u kontekstu korišćenja slogovnih promenljivih za implementaciju skupova.

Primer.

Neka su PASCAL promenljive deklarisane na sledeći način:

type

   colours = (brown, yellow, green, red, orange);

   pallete = set of colours;

var

   davinci, rubens, renoir: pallete;

i neka su neke od vrednosti koje može uzeti promenljiva davinci :

[red, green], [orange], [brown, yellow, red], [brown..red], [brown..green, orange]

Obično se koristi jedan bit za predstavljanje prisustva (taj bit se tada postavi na 1) odnosno odsustva (bit se postavi na 0) svakog mogućeg elementa u skupu. Za prethodno popisane skupove bi se koristila sledeća reprezentacija:

[red, green]

00110

[orange]

00001

[brown, yellow, red]

11010

[brown..red]

11110

[brown..green, orange]

11101

Familija slogovnih promenljivih koje predstavljaju skupove bi u ovom slučaju bila definisana sledećom pseudoinstrukcijom:

PALLETE RECORD BROWN:1, YELLOW:1, GREEN:1, RED:1, ORANGE:1

Dakle, na ovaj način bi bila implementirana deklaracija tipa pallete definisanog u prethodnom PASCAL programu. Od strane asemblera će za svaku paletu biti uzet jedan bajt, pri čemu su od interesa samo bitovi na pet mesta najmanje težine.

Tako će efekat deklaracije

DAVINCI PALLETE <1, 1, 0, 1, 0>

biti da se u bajt na koji referiše DAVINCI pri inicijalizaciji smešta ???11010B. Ako je još istovremeno i

RUBENS PALLETE <0, 1, 0, 1, 1>

RENOIR PALLETE <1, 1, 0, 0, 1>

Tada se paskalovska naredba dodele

rubens:= davinci;

implementira sekvencom asemblerskih instrukcija

MOV AL, DAVINCI

MOV RUBENS, AL

Postoje tri operatora koji se koriste za izolaciju pojednih polja u slogu: brojač pomeraja, WIDTH i MASK.

<polje> - brojač pomeraja postaje efektivan navođenjem naziva polja u slogu. On faktički vraća broj bitovnih pozicija za koje odgovarajuće polje treba pomeriti udesno da bi to polje bilo desno poravnato.

Primer.

Ako je u asemblerskom programu familija slogovnih promenljivih definisana pseudoinstrukcijom:

PALLETE RECORD BROWN:1, YELLOW:1, GREEN:1, RED:1, ORANGE:1

tada se instrukcija

MOV CL, YELLOW

asemblira kao da što se asemblira instrukcija

MOV CL, 3

jer polje YELLOW mora biti pomereno za dva mesta udesno da bi bilo desno poravnato.

WIDTH <polje> (eng. width - širina) - vraća širinu polja u slogu, tj. broj bitovnih mesta koje zauzima polje.

Primer.

Ako je u asemblerskom programu familija slogovnih promenljivih definisana pseudoinstrukcijom:

PALLETE RECORD BROWN:1, YELLOW:1, GREEN:1, RED:1, ORANGE:1

tada se instrukcija

MOV CL, WIDTH YELLOW

asemblira kao da što se asemblira instrukcija

MOV CL, 1

MASK <polje> (eng. mask - maska) - vraća bitovnu masku za pozicije koje zauzima polje.

Primer.

Ako je u asemblerskom programu familija slogovnih promenljivih definisana pseudoinstrukcijom:

PALLETE RECORD BROWN:1, YELLOW:1, GREEN:1, RED:1, ORANGE:1

tada se instrukcija

MOV CL, MASK YELLOW

asemblira kao da što se asemblira instrukcija

MOV CL, 00001000B

Primer.

Implementacija PASCAL instrukcije

davinci:= [yellow, red]

bi lako mogla biti realizovana sledećim kodom (uz korišćenje slogovnih promenljivih formiranih u prethodnim primerima):

MOV AL, 1

MOV CL, YELLOW

SHL AL, CL

MOV DAVINCI, AL

MOV AL, 1

MOV CL, RED

SHL AL, CL

OR AL, DAVINCI

MOV DAVINCI, AL

Zadatak.Opisati efekat izvršenja sledećeg asemblerskog koda.

DATE RECORD MONTH:4, DAY:5, YEAR:7

      .

      .

      .

DATA SEGMENT

      .

      .

      .

   RODJEN DATE <1, 27, 76>

      .

      .

      .

DATA ENDS

 

CODE SEGMENT

      .

      .

      .

   MOV AX, RODJEN

   MOV BX, 0

   MOV CL, DAY

   MOV DL, YEAR

   ADD DL, WIDTH MONTH

   SHR AX, CL

   AND AX, 0FFFEH

   SHL AX, CL

   MOV RODJEN, AX

   MOV BX, NOT MASK MONTH

      .

      .

      .

CODE ENDS

Još treba razmotriti kako se slogovne promenljive koriste za implementaciju nekih operacija i relacija nad skupovima.

Primer.

Neka su deklarisane slogovne promenljive kao u prethodnim primerima. Tada, paskalovska naredba dodele

renoir:= davinci + rubens;

može da se implementira sekvencom asemblerskih instrukcija

MOV AL, DAVINCI

OR AL, RUBENS

MOV RENOIR, AL

Primer.

Neka su deklarisane slogovne promenljive kao u prethodnim primerima. Tada, paskalovska naredba dodele

renoir:= davinci * rubens;

može da se implementira sekvencom asemblerskih instrukcija

MOV AL, DAVINCI

AND AL, RUBENS

MOV RENOIR, AL

Primer.

Neka su deklarisane slogovne promenljive kao u prethodnim primerima i neka treba proveriti da li je vrednost skupovne promenljive davinci podskup od rubens, tj. treba evaluirati izraz

davinci <= rubens

To se (uz korišćenje stava a<=b Ű a*b=a) može postići sledećom sekvencom asemblerskih instrukcija:

MOV AL, DAVINCI

AND AL, RUBENS

XOR AL, DAVINCI

Na ovaj način će u registru AL ostati 0 ukoliko inkluzija važi, a ako davinci nije podskup od rubens broj u AL će biti razlicit og 0.

Makroi

Prvo slovo u nazivu programa MASM ukazuje da se radi o makroasembleru, tj. da taj program dopušta korišćenje makroa.

Makroi su sekvence asemblrskih instrukcija koje imaju jednoznacno određeno ime. Ako programer uoči da se neke slične sekvence instrukcija javljaju više puta u kodu, on može oformiti makroe, i u kodu samo pozivati te makroe. Makroasembler na počeku asembliranja startuje tzv. makro predprocesor, koji iz izvornog koda "izvuče" sve definicije makroa i njihov kod. Potom se, makroi razviju - svi pozivi nekog makroa u izvornom kodu se zamene sa kodom koji je dat u definiciji makroa.

U definiciji makroa mogu se specificirati formalni parametri. To znači da će pri razvoju makroa svaki od tih formalnih parametara biti zamenjen sa tekstom odgovarajućeg stvarnog parametra.

MACRO - definiše asemblerski makro. Ova pseudo­instrukcija se obično javlja u paru sa pseudoinstrukcijom ENDM i ima sledeći oblik:

<ime makroa> MACRO [<parametar>š,<parametar>ć]

      .

      .

      .

ENDM

Primer.

Od sledećeg segmenta koda (koji uređuje dva broja smeštena u bajtu)

   MOV AL, PRVI

   CMP AL, DRUGI

   JNB GOTOVO

   XCHG AL, DRUGI

   MOV PRVI, AL

GOTOVO:

se lako može napraviti makro:

UREDI MACRO PRVI, DRUGI

   MOV AL, PRVI

   CMP AL, DRUGI

   JNB GOTOVO

   XCHG AL, DRUGI

   MOV PRVI, AL

GOTOVO:

ENDM

Međutim, asembler bi javio grešku pri svkom pokušaju asembliranja koda koji sadrži više od jednog poziva ovog makroa. Do greške dolazi zato što se labela GOTOVO koja se javlja u definiciji makroa razvijanjem javlja na bar dva mesta u kodu, što bi značilo da dve različite memorijske lokacije imaju istu simboličku adresu.

Da bi se prevazišli problemi ove vrste, u makroasemblerski jezik je uvedena pseudoinstrukcija koja proglašava da će data labela prilikom razvoja makroa dobiti jedinstveno ime. To je pseudoinstrukcija LOCAL.

LOCAL <ime> (eng. local - lokalno) - saopštava asembleru da je svako od imena u listi lokalno za makro i da im se pri svakom razvoju makroa daje ime koje ih jednoznačno identifikuje.

Primer.

Dakle, makro iz prethodnog primera će biti sledeći:

UREDI MACRO PRVI, DRUGI

LOCAL GOTOVO

   MOV AL, PRVI

   CMP AL, DRUGI

   JNB GOTOVO

   XCHG AL, DRUGI

   MOV PRVI, AL

GOTOVO:

ENDM

Primer.

Ilustruje pozivanje makroa napravljenog u prethodnom primeru:

UREDI MACRO PRVI, DRUGI

LOCAL GOTOVO

   MOV AL, PRVI

   CMP AL, DRUGI

   JNB GOTOVO

   XCHG AL, DRUGI

   MOV PRVI, AL

GOTOVO:

ENDM

 

DATA SEGMENT

   TOTAL DB ?

   SUM DB ?

   MILES DB ?

DATA ENDS

 

STK SEGMENT STACK

   DB 100H DUP(?)

STK ENDS

 

CODE SEGMENT

   ASSUME CS:CODE, DS:DATA, SS:STK

START:

   MOV AX, DATA

   MOV DS, AX

   ;procitaj bajtove sa ulaza

   CALL READCHAR

   MOV TOTAL, AL

   CALL READCHAR

   MOV SUM, AL

   CALL READCHAR

   MOV MILES, AL

   ;izvrsi uredjivanje

   UREDI TOTAL, SUM

   UREDI SUM, MILES

   UREDI TOTAL, SUM

   ;prikazi rezultate

   MOV DL, TOTAL

   CALL PRINTCHAR

   MOV DL, SUM

   CALL PRINTCHAR

   MOV DL, MILES

   CALL PRINTCHAR

   ;kraj programa

   MOV AX, 4c00h

   INT 21H

;procedura za ucitavanje znaka sa tastature

READCHAR:

   MOV AH, 1

   INT 21H

   RET

;procedura za prikaz znaka na ekran

PRINTCHAR:

   MOV AH, 2

   INT 21H

   RET

CODE ENDS

END START

Budući da makroi i podprogrami obavljaju donekle istu funkciju, logično se postavlja pitanje: kada koristiti jedne, a kada koristiti druge?

Naravno, jasno je da i jedan i drugi koncept značajno poboljšavaju programerski kod i olakšavaju proces programiranja.

Ne postoje jasna i brza pravila koja bi dala odgovor na prethodno postavljeno pitanje. Normalno bi billo koristiti podprograme onda kada se ponavljaju grupe instrukcija koje su potpuno iste u svim svojim pojavama. S druge strane, ima smisla koristiti makroe u slučajevima kada su mnemonici instrukcija isti, ali se labele, promenljive ili izrazi menjaju od jedne do druge pojave.

Primer.

Za segment asemblerskog programa:

   ADD AX, BX

   MUL DX

   CMP AX, 3

   JNZ TEST1

      .

      .

      .

ADD AX, BX

   MUL DX

   CMP AX, 3

   JNZ TEST2

      .

      .

      .

ADD AX, BX

   MUL DX

   CMP AX, 3

   JNZ TEST3

      .

      .

      .

je mnogo pogodnije koristiti makroe:

TEST MACRO LABELA

   ADD AX, BX

   MUL DX

   CMP AX, 3

   JNZ LABELA

ENDM

      .

      .

      .

TEST TEST1

      .

      .

      .

TEST TEST2

      .

      .

      .

TEST TEST3

      .

      .

      .

nego da se radi preko procedura:

SABMNOPOR:

   ADD AX, BX

   MUL DX

   CMP AX, 3

pa da se skok, u zavisnosti od postavljenih flegova, izvršava po izlasku iz procedure.

Napomena.

Kako su makroi zasnovani na zameni stringova, to mesto njihovog pojavljivanja nije bitno. Ipak obično su definicije makroa date bilo na početku asemblerskog programa, bilo u posebnim datotekama koje pomoću pseudoinstrukcije INCLUDE bivaju uključene u izvorni kod.

Već je prethodni primer ukazao da parametri u definiciji makroa mogu predstavljati ne samo promenljive, već i labele. Parametri takođe mogu predstavljati registre, instrukcije, opkodove instrukcija, niske, ili numeričke vrednosti.

Primer.

U definiciji makroa iz jednog od prethodnih primera:

UREDI MACRO PRVI, DRUGI

LOCAL GOTOVO

   MOV AL, PRVI

   CMP AL, DRUGI

   JNB GOTOVO

   XCHG AL, DRUGI

   MOV PRVI, AL

GOTOVO:

ENDM

registar AL se koristi za privremeno smeštanje vrednosti tokom zamene.. Dakle, ako bi se u pozivu makroa registar AL javljao kao parametar, gornji makro ne bi korektno radio.

Stoga, mogao bi se napraviti novi makro:

NOVOUREDI MACRO PRIVRREG, PRVI, DRUGI

LOCAL GOTOVO

   MOV PRIVRREG, PRVI

   CMP PRIVRREG, DRUGI

   JNB GOTOVO

   XCHG PRIVRREG, DRUGI

   MOV PRVI, PRIVRREG

GOTOVO:

ENDM

Makroi FORDO i ENDFOR

Asembler sadrži sa neke, već ugrađene, makroe, koje programer može pozivati a da ih prethodno ne definiše. Ti predefinisani makroi omogućavaju da programer radi onako kako bi radio u nekom od viših programskih jezika.

Koristeći makroe FORDO i ENDFOR, može se oformiti programska struktura ekvivalentna sa for petljom u nekom od viših programskih jezika.

FORDO <donja granica>,<gornja granica>,<labela početak>,<labela kraj>,<registar brojač> - omogućava, za­jedno sa makroom ENDFOR, lako kreiranje brojačke petlje.

Ovaj makro ima sledeći izgled:

FORDO MACRO DONJI, GORNJI, START, STOP, REG

   MOV REG, GORNJI

   SUB REG, DONJI

   JB STOP

   INC REG

START:

   CMP REG, 0

   JE STOP

   DEC REG

ENDM

ENDFOR <donja granica>,<gornja granica> - omogućava, za­jedno sa makroom FORDO, lako kreiranje brojačke petlje.

Definicija ovog makroa je:

ENDFOR MACRO START, STOP

   JMP START

STOP:

ENDM

Primer.

Odavde je jasno da će programski sistem oblika:

FORDO 1, 12H, BEG, END, SI

MOV AH, 1

INT 21H

ENDFOR BEG, END

pri asembliranju formirati sledeći listing:

            FORDO 1, 12H, BEG, END, SI

1                      MOV SI, 12H

1                      SUB SI, 1

1                      JB END

1                      INC SI

1          BEG:    CMP SI, 0

1                      JE END

1                      DEC SI

                        MOV AH, 1

                        INT 21H

            ENDFOR BEG, END

1                      JMP BEG

1          END:

Napomena.

Uočava se da, ukoliko je prvi parametar makroa veći od drugog parametra, tada nema prolazaka kroz telo petlje. Takvo ponašanje karakteriše i  više programske jezike.

Primer.

Ovim primerom se realizuje štampanje velikih i malih slova abecede na ekran.

FORDO ‘A’, ‘Z’, BEGPRINT, ENDPRINT, CL

   MOV DL, ‘Z’

   SUB DL, CL

   ;stampaj veliko slovo

   CALL PRINTCHAR

   ;konvertuj u malo slovo

   ADD DL, 20H

   ;stampaj malo slovo

   CALL PRINTCHAR

   ;vrati u veliko slovo

   SUB DL, 20H

ENDFOR BEGPRINT, ENDPRINT

Parametri u definiciji makroa mogu biti instrukcije, ali ne mogu biti sami nazivi makroa.

Primer.

Makro koji sledi ilustruje prethodno tvrđenje:

RADIPUNO MACRO BROJ, BROJAC_REG, INSTRUKCIJA, OPERAND

   FORDO 1, BROJ, POCRADIPUNO, KRAJRADIPUNO, BROJAC_REG

   INSTRUKCIJA OPERAND

   ENDFOR POCRADIPUNO, KRAJRADIPUNO

ENDM

Poziv ovog makroa može imati oblik:

RADIPUNO 27D, AH, INC, BX

će pri asembliranju biti raširen u 27 instrukcija INC BX.

Kako se razvijanje makroa zasniva na zameni niski (stringova), to redosled definisanja nije od nikakvog značaja. Ali, program će biti čitljiviji ako se prvo definišu makroi - gradivni elementi, potom složeniji makroi (oni koji koriste makroe - gradivne elemente), da bi tek posle njih bile instrukcije programa.

Zadatak. Koristeći makroe FORDO i ENDFOR, napisati asemblerski program koji radi sledeće:

a) Izračunava sumu kvadrata prvih 30D prirodnih brojeva:

b) Za dati dan u nedelji u koji “pada” prvi tog meseca, i za dati broj dana u mesecu, štampati kalendar u obliku

Po

U

Sr

C

Pe

Su

N

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

 

 

 

 

Zadatak. Napisati makro ekvivalente za  while i repeat petlju u PASCAL-u. Potom, koristeći prethodno napravljene makroe, napisati programe za:

a) Proveru da li je unesena sekvenca zagrada korektna.

b) Određivanje i štampanje svih trocifrenih brojeva  čija je vrednost jednaka zbiru kubova njegovih cifara.

Korišćenje makroa za definisanje nizova

Ponekad je poželjno da se koriste makroi za definisanje nizova podataka.

Primer.

Neka je potrebno definisati niz dvostrukih reči  koje sadrže stepene broja 2, i kojima se može indidvidualno pristupiti preko simboličkih imena DVANA1 (sadrži 2), DVANA2 (sadrži 4), DVANA3 (sadrži 8) itd, sve do DVANA10 (sadrži 1024).

Za realizaciju takvog cilja, programeru su na raspolaganju i sledeći pseudooperatori:

<izraz>&<ime > - spaja na izraz vrednost zadatog imena u trenutku izvršenja pseudoinstrukcije.

%<izraz > - primorava makroasembler da evaluira izraz, pa vraća evaluiranu vrednost zadatog izraza.

Primer.

Da bi se postiglo definisanje drugog stepena broja 2, makro bi trebao da sadrži sledeće instrukcije:

   BROJ_LABELA=2

   VREDNOST=4

   DVANA&BROJ_LABELA DD VREDNOST

Pored toga, poželjno je da postoji i predefinisani makro, takav da omogućava da se neka sekvenca asemblerskih instrukcija ponovi zadati broj puta.

REPT - (eng. repeat - ponovi) određuje da se kod između poziva ove pseudoinstrukcije i prvog ENDM ponavlja potreban broj puta. Dakle, pseudo­instrukcija REPT se obično javlja u paru sa pseudoinstrukcijom ENDM i ima sledeći oblik:

REPT <broj ponavljanja>

      .

      .

      .

ENDM

Primer.

Da bi se postiglo definisanje prvih deset stepeni broja 2 onako kako je zahtevano u prvom primeru ovog poglavlja, potrebna su dva makroa:

Razvojem prvog od njih, definiše se jedan podatak, tj. jedan stepen dvojke:

DVA_NA MACRO BROJ_LABELA, VREDNOST

   DVANA&BROJ_LABELA DD VREDNOST

ENDM

Sada se ovaj makro treba pozvati 10 puta, svaki put sa nešto drugačijim parametrima. Jedan od načina za ciklično pozivanje je korišćenje makroa FORDO i ENDFOR. Drugi način, u kom se koristi makro REPT, je:

NIZ_DV_NA MACRO

   REPT 10D

      IZLOZILAC = IZLOZILAC + 1

      STEPEN = STEPEN * 2

      DVA_NA %IZLOZILAC, %STEPEN

   ENDM

ENDM

U ovom slučaju pseudoinstrukcije REPT i ENDM usmeravaju asembler da deset puta ponavlja instrukcije unutar petlje. Na taj način sekvenca pseudoinstrukcija

   IZLOZILAC = 0

   STEPEN = 1

   NIZ_DVA_NA

biva tokom asembliranja raširena u:

   IZLOZILAC = 0

   STEPEN = 1

   DVANA1 DD 2

   DVANA2 DD 4

   DVANA3 DD 8

   DVANA4 DD 16

   DVANA5 DD 32

   DVANA6 DD 64

   DVANA7 DD 128

   DVANA8 DD 256

   DVANA9 DD 512

   DVANA10 DD 1024

^esto se dešava da niz podataka ne sadrži vrednosti koje se lako mogu odrediti formulom. U tom slučaju, prethodno opisani pristup pada u vodu.

Primer.

Neka je potrebno definisati niz bajtova  koji sadrže uzastopne proste brojeve, i kojima se može indidvidualno pristupiti preko simboličkih imena PROSTI1, PROSTI 2, PROSTI 3  itd, sve do PROSTI 10.

Asembler MASM sadrži još jedan predefinisani makro, koji olakšava programiranje u ovakvim slučajevima:

IRP - (eng. iterative repeat - iterativno ponavljanje) određuje da se kod između pseudoinstrukcije i prvog ENDM ponavlja onoliko puta, koliko je veličina drugog (nizovnog) argumenta, pri čemu u svakoj iterraciji prvi argumenat biva zamenjen sa odgovarajućom komponentom drugog argumenta. Pseudo­instrukcija IRP se najčešće javlja u paru sa pseudoinstrukcijom ENDM. Ona ima sledeći oblik:

IRP <ime>,<niz>

      .

      .

      .

ENDM

Primer.

Da bi se postiglo definisanje prvih deset prostih brojeva na način zahtevan u prethodnom primeru, potrebna su dva makroa:

Prvi makro se koristi za definisanje jednog podatka:

PROST MACRO BROJ_LABELA, PROST

   PROSTI&BROJ_LABELA DB PROST

ENDM

Sada se ovaj makro treba pozvati 10 puta, svaki put sa nešto drugačijim parametrima. Ne postoji formula koja bi za redni broj elementa na jednostavan i lak način određivala vrednost tog elementa.

NIZ_PROSTIH MACRO

   IRP PRIM, <2, 3, 5, 7, 11, 13, 17, 19, 23, 29>

      BROJ = BROJ + 1

      PROST %BROJ, PRIM

   ENDM

ENDM

Na ovaj način sekvenca pseudoinstrukcija

   BROJ = 0

   NIZ_PROSTIH

biva tokom asembliranja raširena u:

   BROJ = 0

   PROSTI1 DB 2

   PROSTI2 DB 3

   PROSTI3 DB 5

   PROSTI4 DB 7

   PROSTI5 DB 11

   PROSTI6 DB 13

   PROSTI7 DB 17

   PROSTI8 DB 19

   PROSTI9 DB 23

   PROSTI10 DB 29

Primer.

Jednim pozivom sledećeg makroa sadržaji registara AX, BX, CX, DX, SI, DI će biti gurnuti na stek:

PUSH_REGIS MACRO

   IRP REGIS, <AX, BX, CX, DX, SI, DI>

      PUSH REGIS

   ENDM

ENDM

Kada se ovaj makro raširi, dobija se asemblerski kod:

   PUSH AX

   PUSH BX

   PUSH CX

   PUSH DX

   PUSH SI

   PUSH DI

Pseudoinstrukcija IRPC je varijacija pseudoinstrukcije IRP. Kod te pseudoinstrukcije drugi parametar nije niz, već niska (string).

IRPC - (eng. iterative repeat of characters - iterativno ponavljanje znakova) određuje da se kod između pseudoinstrukcije i prvog ENDM ponavlja onoliko puta, koliko iznosi dužina drugog argumenta, pri čemu u svakoj iterraciji prvi argumenat biva zamenjen sa odgovarajućim znakom drugog argumenta. Pseudo­instrukcija IRPC se skoro uvek javlja u paru sa pseudoinstrukcijom ENDM. Ona ima sledeći oblik:

IRPC <ime>,<niska>

      .

      .

      .

ENDM

Primer.

Sledeći kod :

DATA SEGMENT

   .

   .

   .

   IRPC CODE, CXPRMNYZTUABVDIJKEFGHOQSW

      DW ‘&CODE&’

   ENDM

   .

   .

   .

DATA ENDS

će pri asembliranju biti raširen u:

DATA SEGMENT

   .

   .

   .

   DW ‘C’

   DW ‘X’

   .

   .

   .

   DW ‘S’

   DW ‘W’

   .

   .

   .

DATA ENDS

Ovo, na primer, može predstavljati tajni kod po kome se slovo A kodira slovom C, slovo B slovom X, slovo C slovom P, itd.

Zadatak. Koristeći pseudoinstrukcije REPT, IRP ili IRPC, napisati deo asemblerskog program za inicijalizaciju sledećih promenljivih:

a) Kvadrate prvih deset celih brojeva u neoznačenoj 8-bitnoj formi, nazvane KVAD1, KVAD2, KVAD3 itd.

b) Broj dana u svakom mesecu, počev od januara, sa oznakama MES1, MES2, itd.

c) 26 promenljivih, nazvanih A, B, C, ..., Y, Z inicijalizovanih na istu vrednost.

d) Prvih deset stepeni broja 3, označene sa TRINA1, TRINA2, itd. u neoznačenoj 64-bitovnoj formi.

Zadatak. Napisati i testirati makro SPACES, koji ima jedan parametar: nenegativan ceo broj. Pri razvijanju makroa treba da se dobiju instrukcije za štampanje tog broja blankova.

Zadatak. Ispitati makro FORDO. Da li je moguće napisati ekvivalentan makro bez korišćenja parametara START i STOP? Ako da, kako? Ako ne, zašto?

Funkcionisanje programerskih alata

U ovom poglavlju će biti opisan način rada asemblera i linkera.

Način rada asemblera MASM

Asembler MASM je, kao što je nešto ranije istaknuto dvoprolazan - asembliranje se odvija u dve faze.

Za rad sa lokacijama koje odgovaraju simbolima u pvoj fazi asembliranja, makroasembler MASM koristi promenljivu nazvanu brojač lokacija. Brojač lokacija se postavlja na nulu na početku asembliranja ma kog segmenta. Kako se prolazi kroz svaku od instrukcija u segmentu, tako se brojač lokacija uvećava za broj bajtova koje zauzima konkretna instrukcija. Brojač lokacija se koristi za konstruisanje tabele simbola, koja čuva relativne ofsete podataka i instrukcija u okviru jednog segmenta. Podaci iz tabele simbola se koriste u drugom prolasku radi generisanja adresa operanada.

Sam postupak kojim se realizuje prvi prolazak asemblera, mogao bi se opisati sledećim pseudo-PASCAL kodom:

brojac_lokacija:= 0;

pročitaj novu instrukciju sa izvora;

while pročitana instrukcija nije END pseudoinstrukcija do

begin

   if promenljiva ili labela je već u tabela_simbola then

   begin

      odstampaj poruku o grešci

   else

      u tabelu simbola unesi simbol, trenutnu vrednost promenljive brojac_lokacija

      i informacije o tipu simbola

   end;

   case pročitana instrukcija koristi of

      DB, DW, DD, DQ,...::

       begin

          odredi dužinu prostora koji treba rezervisati;

          uvećaj brojač lokacija za tu veličinu;

       end;

      SEGMENT:

       begin

          brojac_lokacija:= 0;

          unesi ime segmenta u tabelu simbola;

       end;

   end;

   if pročitana instrukcija je korektna then

   begin

      odredi duzinu instrukcije na osnovu podataka iz unutrašnje tabele;

      uvećaj brojač lokacija za dužinu instrukcije;

   end

   else

      odštampaj poruku o grešci;

end;

Generisanje mašinskog (tj. objekt) koda u se realizuje drugom prolazu, a na osnovu internih tabela koje za svaku formu instrrukcije sadrže odgovarajuće podatke. To generisanje nije uvek jednostavno, jer asembler dopušta da instrukcije i pseudoinstrukcije sadrže aritmetičke izraze. U drugom prolazu će, pre generisanja koda, biti evaluirani svi izrazi koji se javljaju u asemblerskom programu.

U drugom prolazu se razrešava i problem tzv. prosleđenih referenci (eng. forward reference - prosleđena referenca). Kada asembler naiđe na instrukciju koja sadrži prosleđenu referencu, tada će (ako mu programer direktivom FAR nije naglasio suprotno) pretpostaviti da se radi o bliskom skoku, pa će u prvom prolazu biti rezervisan prostor samo za ofset odredišta (za toliku vrednost še se uvećati brojač lokacija). Razrešavanje problema prosleđenih referenci može dovesti do toga da informacije iz prvog i drugog prolaska budu nekonzistentne, pa se javlja tzv. greška u fazama (eng. phase error - fazna greška).

Način rada linkera LINK

Način korišćenja linkera i njegova svrha su već ranije opisani. Ovde će se detalljnije razmotriti realokacija i upravljanje memorijom, koji dopuštaju programeru da kontroliše format izvršnog programa koji se konstruiše iz individualnih modula.

Linker ima tri osnovna zadatka:

1) Pronalazk modula koji će se linkovati.

2) Uklapanje između referenci na spoljašnje ime (eng. external reference - spoljašnja referenca) i modula koji sadrži definiciju koja odgovara tom imenu.

3) Konstruisanje izvršnog koda kombinovanjem svih objektnih modula u jedan program.

Da bi dopustio linkeru da reši zadatak povezivanja između deklaracija i definicija, asembler neće dodeljivati vrednosti svim adresama koje se koriste u asemblerskom programu. Naravno, programe može, korišćenjem prethodno opisanih pseudoinstrukcija, narediti asembleru da konkretna simbolička adresa dobije određenu vrednost.

Dakle, po asembliranju modula neke vrednosti segmenta i ofseta mogu biti označene kao relokabilne, tj. može biti omogućeno linkeru da odredi aktuelnu adresu.

Primer.

Sledeći dijagram ukazuje na rad linkera u povezivanju dva modula:

 

BROJEVI U POKRETNOM ZAREZU, MATEMATI^KI PROCESOR

Procesor 80386 nema ugrađene mogućnosti za rad sa brojevima u pokretnom zarezu (eng. floating point - plutajuća tačka). Jedan od puteva za obezbeđenje takvog rada je pisanje biblioteke podprograma koje implementiraju različite aritmetičke operacije. Međutim, aritmetika u pokretnom zarezu će biti bitno ubrzana  korišćenjem specijalizovanog hardvera. Takav hardver je INTEL-ov čip 80387.

Matematički procesor (ili koprocesor) 80387 izvršava operacije u pokretnom zarezu mnogo brže nego odgovarajuće rutine procesora 80386. Asemblerski programeri mogu uključiti instrukcije procesora 80387 u programe pisane za procesor 80386, baš kao da su to instrukcije procesora 80386. Kada procesor 80386 “naiđe” na instrukciju koprocesora, ta instrukcija biva prosleđena na izvršenje koprocesoru 80387. Na asemblerskom nivou, sve instrukcije procesora 80387 počinju slovom f (eng .fast - brz).

[ta se dešava kada procesor 80386 “naiđe” na instrukciju za procesor 80387, a koprocesora 80387 nema u računaru? U tom slučaju procesor predaje kontrolu programu za rukovanje sa izuzecima, koji je kreiran od strrane operativnog sistema. INTEL je obezbedio rutinu za obradu izuzetaka pod nazivom E80387 koja softverski emulira rad procesora 80387. Korišćenjem ovakve rutine, program radi kao da je prisutan procesor 80387, samo dosta sporije.

Procesori 8087 i 80287 su neposredni prethodnici procesora 80387. Razlike između procesora 80387 i njegovih prethodnika su nastale ne samo usled razvoja tehnologije, već i zbog toga što je u vreme nastanka procesora 80387 organizacija IEEE usvojila i propisala standard za računanje sa brojevima u pokretnom zarezu. Dizajneri koprocesora 80387 su u potpunosti ispoštovali taj standard.

Formati brojeva u pokretnom zarezu

U zapisu broja u pokretnom zarezu razlikuju se: znak broja, eksponent (ili izložilac) i mantisa.

Ovakav zapis broja ne mora biti jednoznačan, pa se stoga obično nameće pravilo da mantisa ima oblik X.XXXX...X, pri čemu je X oznaka za cifru brojnog sistema. Mantisa ovakvog oblika naziva se normalizovana mantisa, a broj sa normalizovanom mantisom je broj u normalizovanom obliku, ili normalizovan broj. Ostali načini zapisa tog istog broja se nazivaju nenormalizovani.

Kod procesora 80387 broj se takođe sastoji od znaka, eksponenta i mantise, pri čemu je osnova brojnog sistema 2.

Ovaj procesor radi sa brojevima u pokretnom zarezu, koji mogu biti zapamćeni u nekom od sledećih formata: jednostruka preciznost (eng. single precision), dvostruka preciznost (eng. double precision) i raširena preciznost (eng. extended precision).

Sledeći dijagram ukazuje sa kojim sve formatima brojeva radi procesor 80387 i koje bitovne pozicije zauzimaju znak broja, eksponent i mantisa. 

 

1

8

23

 

jednostruka preciznost

Z

E

M

(4 bajta)

 

1

11

52

 

dvostruka preciznost

Z

E

M

(8 bajtova)

 

1

15

64

 

raširena preciznost

Z

E

M

(10 bajtova)

Zapis pojedinih elemenata koji obrazuju broj u pokretnom zarezu (eksponenta i mantise) je isti kao zapis brojeva u fiksnom zarezu: krajnje levo se nalazi mesto naveće težine, a udesno se značaj, tj. težina mesta smanjuje. Istu intuiciju sledi i razmeštaj bitovnih polja u koje se zapisuju mantisa, eksponent i znak broja u pokretnom zarezu: najznačajniji delovi (tj. oni delovi čija eventualna izmena najviše utiče na vrednost broja) smeštaju se krajnje levo, nešto manje značajni delovi se smeštaju desno od njih, a krajnje desno se  smeštaju namanje značajni delovi zapisa broja.

Polje za znak

Na prethodnom dijagramu je polje za znak označeno sa slovom Z. Ako je broj pozitivan, u polju za znak će biti nula. Ako je broj negativan, u polju za znak će biti smeštena jedinica. Zbog toga kod procesora 80387 postoje dve nule, +0 i -0, alli je to “skriveno” od programera.

Primer.

Iako se bitovni zapisi broja +0 i -0 razlikuju, instrukcija poređenja kod procesora 80387 postavlja bitove u ćelijama svojih registara kao da su ta dva broja isti.

Polje za mantisu

Već je istaknuto da je mantisa normalizovana, i da je oblika 1.XX..XX, pri čemu je XΚ0, 1ć (zapisuje se normalizovani broj, pa ispred decimalne tačke mora biti nenula cifra - dakle 1).

Da bi postigli najveću tačnost (preciznost), potrebno je da se u ograničenom prostoru predviđenom za mantisu smesti što je moguće više cifara. Pametnim izborom normalizovane mantise izbegnuto je smeštanje vodećih nula, a ispostavlja se da se ne mora smeštati ni celobrojni deo mantise. Bit koji predstavlja ceo deo mantise mora biti 1. Taj bit se ne pamti u okviru mantise i zato se zove implicitni bit.

Zbog više razloga (jedan je brzina izvršavanja operacije, drugi je to što je prostor dovoljno veliki za postizanje tačnosti) trik sa implicitnim bitom se ne primenjuje kod mantisa brojeva u raširenoj tačnosti.

Polje za eksponent

Osnova brojnog sistema kod eksponenta je, naravno, 2. Sadržaj polja se tumači kao neoznačeni broj. Kako eksponent može biti i negativan, to se eksponent pamti tako što se na njegovu stvarnu vrednost doda pozitivna konstanta bias (eng. bias - kosina , predrasuda). Veličina konstane bias zavisi od formata datog broja u pokretnom zarezu. Veličina bias-a se određuje tako da u polju za izložilac uvek bude pozitivna vrednost - pa ona direktno zavisi od širine bitovnog polja u koje se smešta eksponent. Za broj u jednostrukoj tačnosti veličina bias-a iznosi 28-1-1 = 27-1 = 127, za broj u dvostrukoj tačnosti  211-1-1 = 210-1 = 1023, a za broj u raširenoj tačnosti veličina je 215-1-1 = 214-1 = 16383.

Primer.

Ako broja u jednostrukoj tačnosti ima eksponent čija je vrednost 5, tada se u polju za ekponsnt nalaze bitovi 10000100B =132D.

Ako je vrednost eksponenta broja u jednostrukoj tačnosti -5, tada se u polju za ekponsnt nalaze bitovi 1111010B =122D.

Kod procesora 80387 je korišćenje najmanjeg i najvećeg eksponenta rezervisano za rukovanje greškama.

Vrednost broja u pokretnom zarezu

Vrednost broja u jednostrukoj tačnosti, čiji je zapis ze1e2...e7e8m1m2... m22m23 data je sledećim izrazom:

Vrednost broja u dvostrukoj tačnosti, čiji je zapis ze1e2...e10e11m1m2... m51m52 data je sledećim izrazom:

Vrednost broja u dvoostrukoj tačnosti, čiji je zapis ze1e2...e14e15m1m2... m63m64 data je sledećim izrazom:

Primer.

^etiri bajta

1

1011đ1111đ01011đ1111đ0

110đ0000đ0000đ0000đ0000đ0000

 

će, ako se tumače kao broj u pokretnom zarezu, sa jednostrukom preciznošću, imati Z=1, E=126, M=11000000000000000000000, pa je odgovarajuća vrednost broja u pokretnom zarezu

Veličine brojeva u pokretnom zarezu opisane su sledećom tabelom:

Format broja

Značajne cifre

Najmanji stepen broja 10

Najveći stepen broja 10

Jednostruka preciznost

6

-37

38

Dvostruka preciznost

15

-307

308

Raširena preciznost

19

-4931

4932

 

Iz prethodne tabele direktno sledi da jednostruka preciznost garantuje samo 6 cifara. Stoga, jednostruku tačnost treba koristiti samo kada prostor predstavlja izuzetno snažan limitirajući faktor.

Budući da procesor 80387 interno operiše sa brojevima u raširenoj tačnosti, svi brojevi sa kojima se radi će prvo biti konvertovani u raširenu prreciznost. Prema tome, rad sa brojevima u jednostrukoj tačnosti neće biti mnogo brži od rada sa brojevima u dvostrukoj tačnosti. Uočava se da je kod formmata dvostruke tačnosti uvećana veličina prostora za eksponent (uvećani su i tačnost i opseg), što kod nekih računara nije bio slučaj. Povećanjem veličine izlložioca postignuto je da broj u formatu dvostruke tačnosti može, bez gubitka preciznosti i bez greške, prihvatiti proizvod dva broja u jednostrukoj tačnosti.

Svrha postojanja brojeva u raširenoj tačnosti je čuvanje privremenih rezultata, kako bi se omoguućilo dobijanje korektnog krajnjeg rezultata u dvostrukoj tačnosti.

Primer.

Izračunavanjem funkcije , gde su x i y u dvostrukoj tačnosti, trebalo bi da se dobije z u dvostrukoj tačnosti. Međutim, tu dvostruku tačnost je teško garantovati bez korišćenja formata raširene tačnosti za smeštaj privremenih rezultata.

Neka je . Tu je z završni rezultat, a  privremeni rezultat.

Ukoliko se  razdvoji na ceo i razlomljeni deo, tj. , tada je .

Kako je  to je  značajni deo normalizovane reprezentacije  broja z, a i je eksponenet. Budući da krajnji rezultat z treba biti u dvostrukoj tačnosti, to i zahteva 11 bitova, dok f zahteva 53 bita. Dakle, međurezultat i+f zahteva 64 bita.

Još se postavlja pitanje: zašto je dužina broja u raširenoj tačnosti 80 bitova (deset bajtova) a ne neki stepen dvojke?

Jedan razlog za takvu realizaciju je što bi izbor stepena dvojke zahtevao više aritmetičkog hardvera, illi bi se sa postojećim hardverom postizale slabije performanse. Drudi razlog je to što, kako je u prethodnom primeru pokazano, deset bajtova predstavlja dovoljan prostor za čuvanje privremenih rezultata tako da krajnji rezultat (čak i u dvostrukoj tačnosti) ne izgubi preciznost.

Intervali brojeva u pokretnom zarezu, za sva tri formata, opisani su sledećom tabelom”

 

najmanji negativan

najveći negativan

najmanji pozitivan

najveći pozitivan

 

 

 

 

 

jednostruka tačnost

1

1 ...10

11     ...     1

1

0 ...01

00... 0

0

0 ...01

00... 0

0

1 ...10

11   ...     1

 

-3.37 1038

-1.17 10-38

1.17 10-38

3.37 1038

 

 

 

 

 

dvostruka tačnost

1

1 ...10

11     ...     1

1

0 ...01

00... 0

0

0 ...01

00... 0

0

1 ...10

11   ...     1

 

-1.67 10308

-2.23 10-308

2.23 10-308

1.67 10308

 

 

 

 

 

raširena tačnost

1

1 ...10

11     ...     1

1

0 ...01

00... 0

0

0 ...01

00... 0

0

1 ...10

11   ...     1

 

-1.2 104932

-3.37 10-4932

3.37 10-4932

1.2 104932

Pri tome se broj 0, bez obzira da li se radi o  -0 ili o +0,  u svakom od ovih formata predstavlja tako što polje za eksponent i polje za mantisu sadrže isključivo nule.

Vrednosti za izuzetke

Numerički izuzeci (eng. exception - izuzetak) koji se mogu dogoditi pri radu sa procesorom 80387, grubo rangirani po učestanosti, su:

Netačan rezultat (eng. inexact result) - ovakvo stanje nastaje kada rezultat operacije sa brojevima u pokretnom zarezu ne može biti precizno smešten u željenom odredišnom formatu. Mnogi korisnici aritmetike u pokretnom zarezu neće smatrati da je netačan rezultat greška i očekivaće da automatski bude primenjena neka vrsta rezanja ili zaolruživanja.

Numeričko podkoračenje (eng. numerical underflow) - ono nastupa kada je nenula rezultat toliko mali po modulu da se mora predstaviti kao nula. Korišćenje raširene tačnosti za smeštaj broja utiče na ređe javljenje ovog izuzetka.

Numeričko prekoračenje (eng. numerical overflow) - nastaje kada je rezultat suviše veliki po modulu, tako da isti ne može biti predstavljen.

Deljenje sa nulom (eng. divide by zero) - nastupa kada je vrši operacija deljenja, pri čemu je delilac nula.

Nenormalizovani operand (eng. denormalized operand) - nastupa kada se vrši operacija sa nenormalizovanim operandom.

Invalidna operacija (eng. invalid operation) -- ova kategorija izuzetaka uključuje sve preostale izuzetke (npr. deljenje nule nulom, kvadratni koren negativnog broja, pokušaji koriš]enja nepostojećih i praznih registara procesora 80387, itd.).

Najčešće se koristi jedan od sledeća dva metoda za rad sa greškama:

Suspendovanje, hvatanje u zamku (eng. trapping - hvatanje u zamku): prekida se izvršavanje operacija ukoliko je uslov zadovoljen.

Prosleđivanje specijalnih vrednosti grešaka, odnosno vrednosti izuzetaka.

Razlozi protiv korišćenja drugog metoda:

1.    Vrednost greške mora biti različita od uobičajenih vrednosti.

2.    Kad god program sadrži uslovan skok baziran na poređenju, mora se razmotriti mogućnost da je jedan od operanada pri poređenju baš vrednost koja indicira grešku. Realizacija takvih razmatranja dodatno komplikuje kod.

3.    Postupak dibagirnja programa se usložnjava i otežava sa udaljavanjem izvora greške od mesta prekida rada.

Razlozi koji, u konkretnom radu sa procesorom 80387, ohrabruju korišćenje drugog metoda:

1.    Procesor 80387 dopušta vrednosti grešaka, tj. vrednosti izuzetaka, ukoliko je eksponent 0...0 ili 1...1.

2.    Poređenje brojeva u pokretnom zarezu je mnogo ređe od poređenja brojeva u fiksnom zarezu.

3.    Može se dogoditi da, dođe do greške u izračunavanju međurezultata, a da vrednost krajneg rezultata ipak bude korektna.

Formati celih brojeva

Tu spadaju: celobrojna reč (eng. word integer), kratak ceo broj (eng. short integer), dugi ceo broj (eng. long integer) i pakovani dekadni broj (eng. packed decimal).

Sledeći dijagram prikazuje sve celobrojne formate koje podržava procesor 80387:

 

16

 

celobrojna reč

 

(2 bajta)

 

32

 

kratki ceo brojt

 

(4 bajta)

 

64

 

dugi ceo broj

 

(8 bajtova)

 

1

7

72

 

pakovani dekadni broj

Z

0...0

D17

D16

...

D1

D0

(10 bajtova)

 

Ovi celi brojevi se, sem poslednjeg formata, čuvaju u potpunom komplementu.

Postavlja se pitanje: čemu služe ovi formati, kad se zna da je procesor 80387 prvenstveno dizajniran za rad sa brojevima u pokretnom zarezu?

Ovi formati se najčešće koriste za konverzije između celih brojeva i brojeva u pokretnom zarezu. Te konverzije se moraju vršiti pri izraačnavanjima u kojima su pomešane obe vrste brojeva.

Arhitektura procesora 80387

Procesor 80387 dopunjava rad procesora 80386. I ovaj procesor mnog brže operiše sa podacima koji se nalaze u registrima, nego sa brojevima koji su u memoriji.

Numerički registri

Procesor 80387 sadrži registre, nazvane numerički registri, koji su korisni za računanje u pokretnom zarezu. Oni služe za smeštaj argumenata i međurezultata i sadrže isključivo brojeve u raširenoj tačnosti.

Ti registri su prikazani na sledećoj shemi:

 

80

R0:

 

R1:

 

R2:

 

R3:

 

R4:

 

R5:

 

R6:

 

R7:

 

Iako svaki od ovih registara ima svoju oznaku, instrukcije procesora 80387 su dizajnirane tako da olakšavaju (pomalo neuobičajen) stek-orjentisan pristup numeričkim registrima. Naime, broj numeričkog registra specificiran u instrukciji procesora 80387 se uvek sabira sa sadržajem trobitnog polja ST (eng. stack top - vrh steka) koje se nalazi u okviru statusnog registra procesora 80387. Tako dobijena suma, po modulu 8, određuje koji će se numerički registar zbilja koristiti. Na ovaj način se skup memoriskih registara vidi kao stek, kao što i ilustruje naredni dijagram:

R0:

 

ST(5)

R1:

 

ST(6)

3

R2:

 

ST(7)

ST

R3:

vrh steka

ST(0)

R4:

prvi ispod vrha steka

ST(1)

R5:

 

ST(2)

R6:

 

ST(3)

R7:

 

ST(4)

Dizajneri procesora 80387 su smatrali da većina programera želi korišćenje numeričkih registara u stek maniru, i zbog toga najveći broj instukcija procesora 80387 tokom svog izvršenja modifikuje i bitovno polje ST.

Zbog ovakvog načina pristupa registrima, nadalje će skup numeričkih registrara često biti nazivan registarski stek.

Kontrolni registar

Kontrolni registar je 16-bitni registar. On sadrži polja čije vrednosti modifikuju celokupno ponašanje procesora 80387.

 

 

 

12

11

10

9

8

 

 

5

4

3

2

1

0

 

 

 

IC

R

C

P

C

 

 

PM

UM

OM

ZM

DM

IM

Pet bitova najmanje težine služe za maskiranje izuzetaka. Izuzeci koji mogu nastupiti tokom rada procesora 80387 su opisani u prethodnom poglavlju.

IM - maska invalidne operacije (eng. invalid operation mask).

DM - maska nenormalizovanog operatora (eng. denormalized operator mask).

ZM - maska deljenja sa nulom (eng. zero mask).

OM - maska numeričkog prekoračenja (eng. overflow mask).

UM - maska numeričkog podkoračenja (eng. underflow mask).

PM - maska netačnog rezultata (eng. precision mask).

Ako je bit maske nula, tada će događanje odgovarajućeg  izuzetka dovesti do suspenzije rada programa i do izvršenja odgovarajućeg prekida. Ukoliko je bit maske postavljen, tada se odgovarajući izuzetak maskiran i nastavlja se rad.

PC - dvobitno polje kontrole preciznosti (eng. precision control) koje ukazuje na koju će tačnost biti zaokruženi rezultati. Za PC=11 zaokruživanje će se vršiti na raširenu tačanost, i to je podrazumevano ponašanje. Ako je PC=10, rezulatat će biti zaokružen na dvostruku precianost. Ukoliko je PC=00, vrši se zaokruživanje na jednostruku preciznoat.

Ovo polje postoji iz dva razloga. Prvi razlog je omogućavanje nesmetanog izvršavanja programa pisanih za pretke ovog procesora.Takvi programi mogu sadržavati trikove koji su bazirani na nižoj preciznosti. Drugi razlog je prilagođavanje onim jezicima visokog nivoa koji za me”urezultate zahtevaju upravo takvu preciznost.

RC - dvobitno polje kontrole zaokruživanja (eng. rounding control) koje ukazuje na koji način će se zaokruženi rezultati. Za PC=00 zaokruživanje će se vršiti prema najbližem, i to je podrazumevano ponašanje. Ako je PC=01, rezulatat će biti zaokružen naniže (prema -Ą), a za PC=10, rezulatat će biti zaokružen naviše (prema +Ą). Ukoliko je PC=11, vrši se zaokruživanje prema nuli.

IC - kontrola beskonačnosti (eng. infinity control) koje je ostalo zbog kompatibilnosti sa prethodnicima. Ovo jednobitno oplje određije da li je beskonačnost afina ili projektivna. Kod procesora 80387 u ovom polju mora biti 1, što označava afinu beskonačnost.

Statusni registar

Statusni registar je registar dužine 16. On sadrži polja koja odslikavaju uslove u kojima 80387 obično ne menja svoje ponašanje.

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

B

C3

 

ST

 

C2

C1

C0

ES

SF

PE

UE

OE

ZE

DE

IE

 

Pet bitova najmanje težine služe za indiciranje izuzetaka.

IE - izuzetak invalidne operacije (eng. invalid operation exception).

DE - izuzetak nenormalizovanog operatora (eng. denormalized operator exception).

ZE - izuzetak deljenja sa nulom (eng. zero exception).

OE - izuzetak numeričkog prekoračenja (eng. overflow exception).

UE - izuzetak numeričkog podkoračenja (eng. underflow exception).

PE - izuzetak netačnog rezultata (eng. precision exception).

SF - greška steka (eng. stack fault) - ukazuje da li je do generisanja izuzetka došlo zbog nekorektnog rada sa procesorskim stekom.

Dakle, na bitovnim pozicijama 0-6 se nalaze flegovi izuzetaka. Kada dođe do izuzetka (bilo maskirranog ili nemaskiranog) tada se odgovarajući fleg u ovom registru postavi na 1.

ES - fleg zbirne greške (eng. error sumary flag) - postavlja se u slučaju ma koje greške.

C0, C1, C2, C3 - sadrže uslovne kodove (eng. condition - uslov) zasnovane na poređenju ili deljenju sa ostatkom. Sama interpretacija uslovnog koda zavisi od instrukcije koja se konkretno izvršava i biće razmatrana pri razmatranju tih instrukcija.

B - fleg zauzetosti (eng. busy - zauzet) postavljen je kad god procesor 387 izvršava instrukciju signaliziranja ili prekida. Ovaj fleg je 0 kad god je procesor 80387 slobodan.

Tag registar

Ovaj 16-bitni registar se koristi interno kod procesora 80387 za sumarni prikaz sadržaja numeričkih registara, a u cilju optimizacije performansi i radi detekcije izuzetaka.

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

 

 

Ta

g7

Ta

g6

Ta

g5

Ta

g4

Ta

g3

Ta

g2

Ta

g1

Ta

g0

Tag registar sadrži osam dvobitnih polja. Svako polje odgovara jednom od numeričkih registara. Ako je sadržaj polja 00, to znači da je sadržaj odgovarajućeg registra validan. Ako je sadržaj dvobitnog polja 01, u odgovarajućem registru je nula. Ukoliko bitovno polje sadrži 10, sadržaj registra je invalidan, a ako bitovno polje sadrži 11, registar je prazan.

Registri sa tagom “prazan” su ili neinicijalizovani, ili skinuti sa steka numeričkih registara. Procesor 80387 koristi tag “prazan” za otkrivanje prekoračenja i podkoračenja steka.

Pokazivač instrukcije i pokazivač operanda

Ovi registri obezeđuju memorijske adrese za posllednju korišćenu 387 instrukciju i za memorijski operator, ukoliko taj operator postoji. Ove informacije su od značaja programima za rukovanje izuzecima (eng. exception handler - rukovalac izuzecima).

SKUP INSTRUKCIJA PROCESORA 80387

Svi opkodovi za procesor 80387 počinju sa istih pet bitova, koji upozoravaju procesor 80386 da te instrukcije on ne izvršava. Stoga, svi mnemonci opkodova procesora 80387 počinju sa slovom F (eng. fast - brz). Pri radu su dopušteni svi uobičajeni adresni modovi procesora 80386.

Primer.

Različiti načini adresiranja kod instrukcija za 80387:

FADD IME

FADD W[EBX]

FADD IME[EBX][ESI]

Asembler je u mogućnosti da implictno detektuje veličinu (tj. tačnost) memorijskog operanda jer ima informaciju o korišćenju neke od pseudoinstrukcija DD, DQ, DT.

Najveći broj instrukcija ima formate koji referišu na registarski stek. Takav format je ST(i), što ožnačava i-ti element ispod vrha registarskog steka. Registru na vrhu steka se može pristupiti sa ST(0) ili kraće ST.

Instrukcije prenosa podataka

Ovim instrukcijama se realizuje premeštanje iz memorije u numeričke registre, iz numeričkih registara u memoriju i između numeričkih registara.

Guranje na registarski stek

FLD S (eng. fast load - brzo ucitaj)

FILD S (eng fast integer load - brzo ucitaj ceo broj)

FBLD S (eng fast BCD load - brzo ucitaj BCD broj)

Skidanje sa registarskog steka

FSTP D (eng. fast store and pop - brzo smesti i skini)

FISTP D (eng. fast integer store and pop - brzo smesti i skini ceo broj)

FBSTP D (eng. fast BCD store and pop - brzo smesti i skini BCD broj)

Prenos između vrha registarskog steka i numeričkog registra

FST D (eng. fast store - brzo smesti)

FIST D (eng. fast integer store - brzo smesti ceo broj)

FXCH D (eng. fast exchange - brzo razmeni)

Guranje konstanti na registarski stek

FLDZ (eng. fast load zero - brzo ucitaj nulu)

FLD1 (eng. fast load one - brzo ucitaj jedinicu)

FLDPI (eng. fast load pi - brzo ucitaj p)

FLDLG2 (eng. fast load log102 - brzo ucitaj jedinicu log102)

FLDLN2 (eng. fast load ln2- brzo ucitaj jedinicu ln2)

FLDL2T (eng. fast load log210 - brzo ucitaj jedinicu log210)

FLDL2E (eng. fast load log2e - brzo ucitaj jedinicu log2e)

Aritmetičke instrukcije

^etiri osnovne binarne aritmetičkle operacije su sabiranje, oduzimanje, množenje i delljenje.

Kod aritmetičkih instrukcija za 80387, jedan od operandad mora biti vrh registarskog steka. Instrukcije se javljaju u jednoj od sledećih formi:

Fxxx - instrukcija se odnosi na vrh registarskog steka i elemenat nepostedno ispod vrha.

Fxxx <mem> - instrukcija se odnosi na vrh registarskog steka i memorijsku lokaciju.

FIxxx <mem> - instrukcija se odnosi na vrh registarskog steka i memorijsku lokaciju, pri čemu se radi sa celim brojevima.

Fxxx ST, ST(i) - instrukcija se odnosi na vrh registarskog steka i i-ti element ispod vrha steka.

Fxxx ST(i), ST - instrukcija se odnosi na i-ti element ispod vrha steka i vrh registarskog steka.

FxxxP ST(i), ST - instrukcija se odnosi na i-ti element ispod vrha steka i vrh registarskog steka, i potom se skida elemenat sa steka.

Niska xxx može uzeti vrednosti: ADD, SUB, MUL, DIV, SUBR (eng. subtract reversed - obratno oduzimanje), DIVR (eng divide reversed - obratno deljenje)

Instrukcije poređenja

Ovim instrukcijama se, na osnovu vrednosti operanda, postavljaju neki od bitova statusnog registra.

FCOM (eng. fast compare - brzo uporedi)

FUCOM (eng. fast unordered compare - brzo neuređeno uporedi)

FICOM (eng. fast integer compare - brzo uporedi cele brojeve)

FCOMP (eng. fast compare and pop - brzo uporedi i skini)

FUCOMP (eng. fast unordered compare and pop - brzo neuređeno uporedi i skini)

FICOMP (eng. fast integer compare and pop - brzo uporedi cele brojeve i skini)

FCOMPP (eng. fast compare and pop twice - brzo uporedi i dvaput skini)

FUCOMPP (eng. fast unordered compare and pop twice  - brzo neuređeno uporedi i dvaput skini)

FTST (eng. fast test - brzo testiraj, uporedi sa nulom)

Pri poređenju se bitovi statusnog registra postavljaju na sledeći način:

C3

C0

uslov

0

0

ST(0)>x

0

1

ST(0)<x

1

0

ST(0)=x

1

1

neuređeno

Napomena.

Instrukcija FSTSW AX, uvedena kod procesora 80287 omogućuje da se statusna reč koprocesora smesti u registar AX, a potom se lako mogu testirati postavljanja bitova.

Ako bi se, izvršenjem instrukcije LAHF sadržaj AH prebacio u registar flegova, tada bi bitu C0 odgovarao CF, a bitu C3 odgovara ZF.