You are on page 1of 19

12.

Generisanje koda
Faza generisanja koda je praktino poslednja faza u procesu prevoenja jezika. Obino se
nadovezuje na generisanje meukoda i koristi informacije sauvane u Tabeli simbola, Sl. 12.1.
Kod nekih kompilatora se nakon generisanja koda vri njegova optimizacija mada se veoma esto
optimizacija koda vri i na nivou meukoda, o emu e biti rei u narednom poglavlju.
Osnovni zadatak generatora koda je da generie ispravan kod pri emu je bitno da taj kod bude i
to je mogue efikasniji.

Izvorni kod Analizator meukod Optimizator meukod Generator Ciljni


koda
kod

Tabela simbola

Slika 12.1 Pozicija generatora koda u procesu prevoenja


Generator koda moe da bude realizovan na tako da generie direktno mainski kod sa apsolutnim
adresama, mainski kod sa relativnim adresama ili asemblerski kod koji zatim prolazi kroz proces
asembliranja.
Kada se generie mainski kod sa apsolutnim adresama on se direktno smeta u memoriske
lokacije i neposredno posle toga izvrava. Ovo je pristup koji se obino primenjuje kod manjih
kompilatora koji se realizuju kao studentski projekti.
U sluaju kada se generie kod sa relativnim adresama delovi programa, kao to su potprogrami
mogu da se prevode nezavisno pa da se naknadno povezuju pomou linkera i ubacuju u memoriju
pomou loadrea.
Kada generator koda generie asemblerski jezik sam generator se lake realizuje, koriste se
simbolike naredbe asemblerskog jezika kao i raspoloive makro naredbe ali se tada na fazu
generisanja koda nadovezuje faza asembliranja koda. U ovom poglavlju baviemo se tim
pristupom realizaciji kompilatora.
12.1 Ciljni jezik
Proces generisanja jezika direktno zavisi od ciljnog jezika i nemogue je u optem sluaju
sagledati sve probleme koji mogu da nastanu U ovom odeljku bie opisan jedan jednostavan
asembleski jezik koji e se koristiti u opisu generatora.
Uzeemo kao primer procesor u kome se za adresiranje rei koristi po jedan bajt, a same rei su
duine 4 bajta. Na raspolaganju nam je n registarau samom procesoru: R 1,R2, ... Rn-1. Asemblerski
jezik ovog procesora ima dvoadresne naredbe oblika
KO surce, destination
Gde je KO kod operacije naredbe, a surce, destination odreuju podatak nad kojim e se
operacija izvriti. Osnovne naredbe ovog jezika su:
MOV (source se alje u destination)
ADD (source se dodaje na destination)
SUB (source se oduzima od destination)
Kasnije e mo kako se bude ukazivala potreba uvoditi i druge naredbe.

Naini adresiranja

Polja soure i destination nisu dovoljna da specificiraju ceo podatak ili adresu podatka ve samo
kodiraju nain adresiranja koji je primenjen odnosno da li se u rei koja sledi iza naredbe nalazi
podatak ili adresa. U Tabeli 12.1 su navedeni naini adresiranja koji se koriste kod ovog
asemblerskog jezika kao i dodatna cena koju nain adresiranja pridodaje ceni naredbe u kojoj je
primenjen.
Tabela 12.1 Pregled zastupljenih naina adresiranja

Nain adresiranja Format simbolikog Adresa Dodatna cena


Zapisa naredbe

Apsolutno adr. M M 1

registarsko R R 0

indeksiranje c(R) c+(R) 1

Indirekno registarsko *R (R) 0

Indirekno sa indeksiranjem *c(R) (c+(R)) 1

Neposredno #c 1

Apsolutno adresiranje
U ovom sluaju memorijska lokacija ije je simboliko ime navedeno u naredbi je izvorite ili
destinacija. Na primer, u naredbi:
MOV R0,M
Sadraj registra R0 se prosleuje u memorijsku lokaciju M: (R0)M.
U ovom sluaju adresa memorijske lokacije sledi neposredno iza same naredbe, pa je zato uzeto
da samo adresiranje poveava cenu za jedan.
Registarsko adresiranje
Kod registarskog adresiranja navedeni registar je izvorite ili odredite podatka na koji se odnosi
naredba. U prethodnom primeru MOV naredbe sadraj registra R0 se prebacuje u mamorijsku
lokaciju M.
Kako se registri nalaze u procesoru i adresiranju se implicitno, nije potrebno da se zauzima
memorijski prostor za pamenje njihovih adresa, ovaj nain adresiranja ne poveava cenu
naredbe u kojoj se koristi.
Indeksiranje
U ovom sluaju adresa izvorita ili odredita se formira tako to se sadraju registra koji je
naveden u zapisu naredbe dodaje vrednost konstante koja je navedena u naredbi. U ovom sluaju
vrednost konstante u binarnom odliku sledi iza same naredbe ovo adresiranje poveava cenu
naredbe za 1.
Primer:
MOV 4,(R0), M
Efekat je da se sadraj registra R0 poveava za 4, ime se formira adresa memorijske lokacije iji
se sadraj alje u memorijsku lokaciju M: (4+(R))M.
Indirektno registarsko adresiranje
Indirektno adresiranje je oznaeno sa *, i sastoji se u tome da se sadraj navedenog registra
koristi kao adresa lokacije u kojoj ili iz koje se preuzima sadraj nad kojim se izvrava navedena
operacija.
Na primer, u naredbi:MOV *R0,M efekat je ((R0))M. Sardaj memorijske lokacije ija je
adresa jednaka sadraju registra R0 se prosleije u memorijsku lokaciju M. Ovo adresiranje kao i
registarsko ne poveava cenu naredbe zato to ne zahteva dodatan memorijski prostor za
pamenje podataka o adresi.
Indirekno indeksirano adresiranje
Kada se indirektno adresiranje kombinuje sa indeksiranjem najpre se indeksiranjem formira
adresa memorijske lokacije iji se sadraj koristi kao adresa lokacije iji se sadraj koristi u
operaciji.
Na primer u naredbi *4(R0), M efekat je ((c+(R0)))M.
U ovom sluaju, kao i kod indeksiranja, konstanta koja se koristi u indeksiranju se memorie
odmah iza same naredbe tako da ovo adresiranje poveava cenu naredbe za 1.
Neposredno adresiranje
U sluaju neposrednog adresiranja podatak nad kojim se izvrava naredba je konstanta koja se
daje uz samu naredbu. Ova konstanta se memorie neposredno iza naredbe tako da takav nain
adresiranja poveava cenu naredbe za 1.
Primer:
Naredba MOV #5, R0 ima efekat 5R0, vrednost konstante 5 se upisuje u registar R0.
Cena naredbi
U mnogim sluajevima prilikom generisanja koda postoji vie mogunosti. Nekada se isti efekat
moe postii izborom razliitih instrukcija. Generator koda zbog toga prilikom generisanja koda
koristi i neku procenu cene generisanog koda koju formira na osnovu cene pojedinanih naredbi
koje mu stoje na raspolaganju. Cena naredbe u sutini zavisi od memorijskog prostora koji
zauzima sama naredba kao i do naina adresiranja koji je u njoj primenjen, o emu je bilo ve
rei. Kao to smo videli, korienje procesorskih registara ne poveava cenu naredbe dok
korienje memorijskih lokacija je poveava. Sa druge strane korienje registara procesora utie
i na efikasnost samog koda zato to se operacije mnogo bre izvravaju ututar samog procesora,
odnosno nad sadrajima koji se nalaze u registrima u odnosu na sluaj kada se sadraj preuzima
iz memorije. Zbog svega toga zadatak samog generatora koda je i efikasno korienje registara
procesora.
Razmotriemo ukupnu cenu nekih naredbi iz jezika koji koristimo kao primer:
Naredba MOV R0,R1 kojom se sadraj registra R0 kopira u registar R!, imae ukupnu
cenu 1, zato to sama naredba zauzima jednu memorijsku lokaciju i ne zahteva dodatni
memorijski prostor za pamenje adresa.
Naredba MOV R0, M , kojom se sadraj registra R0 prebacuje u memorijsku lokaciju M,
ima ukupnu cenu 2, zato to sama naredba zauzima jednu memorijsku lokaciju, a
neposredno iza nje sledi adresa memorijske lokacije koja se koristi kao odredite
sadraja.
Naredba #5,R0, kojom se u registar R0 upisuje vrednost konstante 5, ima ukupnu cenu 2,
zato to sama naredba zauzima jednu memorijsku lokaciju, a neposredno iza nje se
memorie konstanta 5.
Naredba MOV 4(R0), *12(R1) iji je efekat (4+R0)(12+(R1)). Odnosno, sadraj
memorijske lokacije ija je adresa odreena zbirok indeksa 4 i sadrajem registra R0 se
upisuje u memorijsku lokaciju ija je adresa odreena sadrajem memorijske lokacije ija
je adresa zbir konstante 12 i sadraja registra R1. Ova naredba ima ukupnu cenu 3, zato
to se jedna memorijska lokacija koristi za samu naredbu i po jedna za memorisanje
konstanti 4 i 12.
Na primeru jednostavne troadresne naredbe a := b + c pokazaemo ta sve moe i treba da bude
uzeto u razmatranje u okviru generatora koda. Ova naredba moe da bude realizovana na mnogo
razliitih naina od kojih su neki:
1. MOV b,R=
ADD c, R=
MOV RO, a ukupna cena 6, zato to svaka od naredbi ima cenu 2.
2. MOV b,a
ADD c,a ukupna cena 6, zato to svaka naredba ima cenu 3.
Ako se adrese 1, b i c nalaze u registrima R1, R2 i R3 sekvenca naredbi bi bila:
3. MOV *R1, *R0
ADD *R, R0 ukupna cena 2, zato to je cena svake naredbe 1.
Ako pretpostavimo da se vrednosti a i b nalaze u registrima R0 i R1 i da nam vrednost b ne treba
posle operacije onda je mogua i sledea sekvenca naredbi:
4. ADD R2, R1
MOV R1, a sa ukupnom cenom 3, gde je cena prve naredbe 1, a druge 2.
Iz ovog trivijalnog primera se vidi da generator koda ima dosta komplikovan zadatak ako se kao
cilj postavi genrisanje optimalnog koda. Zbog toga se obino ovom problemu pristupa tako to se
kao primarni cilj generatora postavlja generisanje funkcionalno ispravnog koda, a optimizacija
koda se vri naknadno.
12.2 Realizacija generatora koda
Pre nego definiemo sam generator koda uveemo ogranienje da se rezultat izvravanja
neke operacije zadrava u registru sve dok je potreban. Iz registra emo ga prebacivati u
memorijsku lokaciju samo u sluaju kad je taj registar potreban za neku drugu operaciju kao i
neposredno pre poziva potprograma, pre naredbe skoka kao i pre naredbe sa labelom.
Algoritam generatora koda
Generator koda preuzima naredbe iz ulazne sekvence koja predstavlja troadresni meukod. U
okviru ovih sekvenci se obino identifikuju delovi (blokovi) koji sami za sebe predstavljaju
celine, tako da se moe uitavati blok po blok. Takoe za svaki od raspoloivih registara
koristimo Descriptor registra koji ukazuje na to vrednost koje promenljive je memorisana u
registru. Takoe za svaku od promenljivih imamo Deskriptor adrese koji ukazuje na to gde je
memorisana vrednost te promenljive.

Za svaku troadresnu naredbu oblika x := y op z izvravaju se sledei koraci:


1. Korak: Odreivanje lokacije L u kojoj e biti zapamen rezultat
U ove svrhe koristi se funkcija getreg, je data neposredno iza ovog algoritma. Nastoji se da
odredite bude neki od registara u procesoru, ali isto tako to moe da bude i neka od
memorijskih lokacija.
2. Korak: Odreivanje podatka nad kojim se izvrava operacija
Odreuje se gde se nalazi podatak y nad kojim se izvrava operacija. On moe da bude u
memoriji ili u nekom od registara procesora. Ukoliko se nalazi na oba mesta prednost se daje
registrima. Ako podatak ve nije u L, generie se naredba MOV y, L, kojom se podatak y
prebacuje u lokaciju L. (sa y je oznaena adresa lokacije u kojoj se nalazi podatak y).
3. Korak: Generisanje naredbe
Generie se naredba oblika OP z, L, gde je sa z oznaena lokacija u kojoj se nalazi podatak
simboliki oznaen sa z. Descriptor adrese za x se koriguje tako da pokazuje na lokaciju L.
Ako je L registar treba korigovati njegov deskriptor tako da pokazuje da on sadri podatak x,
i izbrisati x iz sadraja svih drugih deskriptora registara.
4. Korak: Oslobaanje registara
Ako se podaci y i z ne koriste neposredno iza razmatrane naredbe, nisu ivi po izlasku iz
bloka onda, ako se nalaze u registrima treba osloboditi registre ili naznaiti da se posle
bloka ti sadraji ne koriste.
Uoimo da za svaki od registara procesora imamo deskriptor registra koji pamti koji se podatak
nalazi u registru, dok za svaki podatak koji je u memoriji pamtimo adresu memorijske lokacije u
kojoj je memorisan.
Funkcija getreg
Funkciju getreg koristimo da odredimo lokaciju gde e biti smeten rezultat generisane naredbe.
Ako je cilj generisanje optimalnog koda ovaj zadatak moe da bude jako sloen. Ovde e biti
razmatrano jedno jednostavno reenje koje daje prednost registrima procesora u odnosu na
memorijske lokacije ako ta mogunost postoji.
1. Ako descriptor nekog registra pokazuje da je y u tom registru i ako se y vie ne koristi
posle naredbe x := y op z, onda se taj registar vraa kao L. Kako e posle izvrenja
naredbe u ovom registu biti rezultat operacije, a ne vie y treba korigovati descriptor
adrese za y da y vie nije u tom registru.
2. Ako prva solucija nije mogua za L uzimamo prazan registar ako takav postoji.
3. Ako ni druga solucija nije mogua i ako se x koristi dalje u istom bloku, ili je op operator
koji zahteva upotrebu registara, onda biramo neki od zauzetih registara R. Vrednost koja
je trenutno zapisana u registru prebacujemo u memoriju (generiemo naredbu MOV R,M)
ako ta vrednost ve nije zapamena u memoriji, korigujemo descriptor adrese za M i
vraamo R kao L. Ako je u registru R zapisana vrednost veeg broja promenljivih (to
moe da bude posledica copy naredbi) treba generisati odgovarajuu MOV naredbu za
svaku od tih promenljivih.
4. Ako se x ne koristi dalje u bloku ili ne moe da se nae odgovarajui prazan registar
onda se za L uzima memorijska lokacija u kojoj je zapamena vrednost za x.

Primer. 12.1 Razmotrimo kao primer naredbu dodeljivanja d := (a - b) + (a - c) + (a c) na


osnovu koje je generisan sledei meukod:
t1 := a b
t2 := a c
t3 := t1 t2
d := t3 + t2
Genarator koda opisan gore datom procedurom generisae sekvencu asemblerskih naredbi
prikazanu u Tabeli 12.2.
Table 12. 2 Generisani kod za blok naredbi iz Primera 12.1

Naredba meukoda Generisani kod Deskriptor registra Deskriptor adrese


Registri su prazni
t1 := a - b MOV a, R= R0 sadri t1 t1 je u R0
SUB b,R0
t2 := a - c MOV a,R1 R0 sadri t1 t1 je u R0
SUB c,R1 R1 sadri t2 t2 je u R1
t3 := t1 t2 ADD R1,R0 R0 sadri t3 t3 je u R0
R1 sadri t2 t2 je u R1
d := t3 + t2 ADD R1,R0 R0 sadri d d u R0
MOV R0, d d u memoriji

Generisanje koda za neke specijalne naredbe


Sloenije naredbe troadresnog koda, kao to su naredbe u kojima se javljaju indeksirane
promenljive i pointeri, se transformiu u asemblerski kod na slian nain kao i naredbe sa
binarnim operatorom.
Kod koji se generie za sluaj naredbi dodeljivanja u kojima se javljaju promenljive sa indeksima
prikazan je u Tabeli 12.3.
Tabela 12.3 Generisani kod za naredbe sa indeksima

Naredba Indeks i je u registru Indeks i je u memoriji Indeks i je u steku


meukoda Ri Mi
Gen. kod Cena Gen. kod Cena Gen. kod Cena
a := b[i] MOV b(Ri),R 2 MOV Mi, R 4 MOV Si(A),R 4
MOV b(R),R
MOV b(R),R
a[i] := b MOV b, a(Ri) 3 MOV Mi, R 5 MOV Si(A),R 5
MOV b, a(R) MOV b, a(R)

U Tabeli 12.3 su razmatrani sluajevi naredbi: a := b[i] i a[i] := b, a uzeta su obzir tri sluaja: kada
je indeks zapamen u registru procesora, u memorijskoj lokaciji ili se uva na steku.
Kod koji se generie u sluaju naredbi u kojima se koriste pokazivai prikazan je u Tabeli 12.4. I
ovde su uzeta u obzir dva oblika meunaredbi: a := *p i *p := a. Takoe su razmatrane sluajevi
kada se vrednost pokazivaa nalazi u registru procesora, u memorijskoj lokaciji ili na steku.
Tabela 12.4 Generisani kod za naredbe sa pokazivaima

Naredba Pokaziva p je u Pokaziva p je u Pokaziva p je u steku


meukoda registru Rp memoriji Mp
Gen. kod Cena Gen. kod Cena Gen. kod Cena
a := *p MOV *Rp,a 2 MOV Mp, R 3 MOV Sp(A),R 3
MOV *Mp, a MOV *R,a
*p := a MOV a, *Rp 2 MOV Mp, R 4 MOV a,R 4
MOV a, *Rp MOV R, *Sp(A)

Uslovne naredbe
Uslovne naredbe troadresnog koda oblika if x relop y go to z mogu da budu transformisane u
asemblerski u principu na dva naina.
Jedan nain je da se najpre x oduzme od y i da se rezultat zapamti u registru R, nakon ega se
generie naredba skoka na z ako je vrednost registra R negativna.
Drugi nain se primenjuje kod asemblerskih jezika koji koriste skup bitova (conditional code)
kojima se registruje kakva je vrednost koja je upisana u registar bilo da je ona dobijena kao
rezultat izvravanja neke operacije ili prilikom upisa vrednosti u registar. Ovi jezici obino sadre
naredbe skoka koje se vezuju za te bitove i omoguavaju prenos upravljanja na neku naredbu ako
je neki od uslova ispunje. U ovom sluaju naredba meukoda oblika if x < y go to z e biti
preslikana u sledeu sekvencu naredbi:
CMP x, y
CJ< z
Najpre se poredi vrednost podataka x i y, nakon ega se postavljaju vrednosti bitova kojima se
registruje sadraj rezultata. Druga naredba je skok na labelu z ako je u bitu kojim se registruje
uslov< upisana vrednost 1.
12.3 Organizacija memorije
Ako zamislimo da operativni sitem dodeljuje neki deo memorije kompilatoru za smetaj
programa koji se prevodi onda kompilator obino pravi raspodelu memorije tako da jedan
segment koristi za smetaj koda programa, u drugi smeta statike podatke, jedan deo memorije
se organizuje u vidu steka i slui za smetaj aktivacionih slogova potprograma (o emu e biti
rei kasnije) a deo memorije (Heap) se koristi za smetaj dinamikih podataka, Slika 12.2:
Kod programa

Statiki podaci

Stek

Heap-Dinamiki podaci

Slika 12. Organizacija memorije

Veliina generisanog koda je poznata u toku prevoenja programa, a takoe moe da se izrauna i
memorijski proctor potreban za smetaj statikih podataka. Ove informacije kompilator moe da
iskoristi i da kod i podatke smesti u memorijske lokacije odreene apsolutnim ili relativnim
adresama.
Kod nekih jezika, kao ro je na primer FORTRAN, svi podaci se smetaju statiki. Meutim
postoje jezici kod kojih se koriste dinamiki podaci za koje se vri alokacija memorije u toku
izvravanja programa. Ovim podavima namenjen je dinamiki deo memorije. Takoe kod
programskih jezika kod kojih su dozvoljeni rekurzivni pozivi potprograma za smetaj
aktivacionih slogova potprograma koristi se stek.
Veliina steka i dinamikog dela memorije moe da se menja u toku izvravanja programa.
Prilikom implementacije nekih jezika (Pascal, C) dozvoljava se da se ovi delovi menjaju jedan na
raun drugog.
Obino se u posebnom registru procesora uva adresa vrha steka, to je takozvani pokaziva vrha
steka.
Alokacioni slogovi
Za svaki poziv potprograma kompilator obino generie jedan aktivacioni slog u kome uva sve
informacije potrebne tom pozivu potprograma. U optem sluaju aktivacioni slog ima strukturu
prikazanu na Slici 12.3. Meutim, struktura aktivacionog sloga nije ista kod svih jezika niti kod
svih kompilatora za jedan jezik. Ona se obino prilagoava potrebama kompilatora.
Namena polja u aktivacionom slogu je sledea:
1. Na vrhu sloga, smeta se vrednost koju potprogram vraa glavnom programu. Ova
vrednost se zbog efikasnosti vraa u neki od registra procesora.
2. Polje namenjeno stvarnim parametrima se koristi od strane glavnog programa da prenese
parametre potprogramu koji odgovaraju konkretnom pozivu potprograma.
3. Opciono polje sa upravljakim linkovima se koristi da se obezbedi veza sa aktivacionim
slogom modula iz kojeg je pozvan potprogram.
4. Opciono polje sa linkovima za pristup podacima postoji kod jezika koji dozvoljavaju da
se koriste nelokalni podaci, podaci iz aktivacionih slogova drugih potprograma. Ovo
polje kod Fortrana nije potrebno zato to se svi nelokalni podaci uvaju na jednom mestu.
5. Deo aktivacionog sloga namenjen uvanju statusa procesora slui da se u njemu
memoriu vrednosti registara pocesora koje su zateene u trenutku poziva potprograma.
Ovde se obino smeta vrednost Brojaa neredbi i registara procesora opte namene.
6. Polje namenjenu lokalnim podacima slui za smetaj podataka koji pripadaju samo
potprogram, definisani su u potprogramu.
7. Polje namenjeno privremenim podacima slui za memorisanje podataka koje generie
kompilator kao pomone lokacije u koje smeta meurezultate.
Veliina svih polja u aktivacionom slogu moe da se odredi u fazi prevoenja programa. Izuzetak
su samo jezici kod kojih je dozvoljeno da se dimenzije polja definiu u fazi izvravanja tako to
se ti podaci uitavaju.

Vrednost koja se vraa glavnom programu

Stvarni parametri

Opconaalni upravljaki linkovi

Linkovi za pristup podacima

Podaci o statusu procesora

Lokalni podaci

Privremene promenljive

Slika 12.4 Struktura aktivacionog sloga

12.4 Strategije za alokaciju memorije


Na osnovu toga kako i kada se generiu i memoriu aktivacioni slogovi zastupljene su tri
strategije alokacije memorije kod realizacije kompilatora:
Statika alokacija svih objekata u vreme kompilacije.
Alokacija pomou steka
Dinamika alokacija pomou Heap-a
Kod statike alokacije aktivacioni slog se generie u fazi kompiliranja i smeta u statiki deo
memorije. Kod alokacije memorije pomou steka aktivacioni slogovi se generiu u fazi
izvravanja i smetaju na stek, dok se kod dinamike alokacije smetaju u dinamiki deo
memorije. Jednostavniji sluaj ovih alokacija je kada se svi podaci o strukturi sloga znaju u fazi
kompiliranja, a sloeniji kada se struktura kompletira u fazi izvravanja.
Statika alokacija
U toku kompiliranja programa generie se po jedan aktivacioni slog za svaku od procedura tako
da se isti aktivacioni slog koristi kod svakog poziva potprograma. Ovaj aktivacioni slog se smeta
u statiki deo memorije. U ovom sluaju nema mogunosti za rekurzivne pozive procedura zato
to bi svaki naredni poziv procedure prebrisao sadraj aktivacionog sloga koji odgovara
prethodnom pozivu koji jo nije zavren. Takoe nije dozvoljen rad sa dinamikim podacima za
koje se alocira memorija u fazi izvravanja. Ova tehnika se primenjuje kod realizacije
kompilatora za programski jezik FORTRAN.

Primer 12.3
Uzmimo kao primer kod program CONSUME i potprograma PRODUCE, napisanih u
programskom jeziku FORTRAN

PROGRAM CONSUME
CHARACTER * 50 BAF
INTEGER NEXT
CHARACTER C, PRODUCE
DATA NEXT /1/, BUF / /
6 C = PRODUCE ( )
BUF(NEXT:NEXT) = C
NEXT = NEXT + 1
IF (C .NE. ) GO TO 6
WRITE (*, (A)) BUF
END

CHACTER FUNCTION PRODUCE ( )


CHARACTER * 80 BUFFER
INTEGER NEXT
SAVE BUFFER, NEXT
DATA NEXT /81/
IF (NEXT .GT. 80 ) THEN
READ (*, (A)) BUFFER
NEXT = 1
END IF
PRODUCE = BUFFER(NEXT:NEXT)
NEXT = NEXT + 1
END

Kako su veliina memorijskog prostora potrebnog za smetaj koda programa i potprograma, kao i
aktivacionih slogova za ova dva modula poznati u fazi kompiliranja programa raspodela
memorije u ovom sluaju e biti kako je to prikazano na Slici 12.5.
Kod za CONSUME

Kod za PRODUCE

Aktivacioni slog za CONSUME

CHARACTER * 50 BUF
INTEGER NEXT
CHARACTER C

Aktivacioni slog za PRODUCE

CHARACTER * 80 BUFFER
INTEGER NEXT

Slika 12.4 Statika alokacija memorije

Alokacija memorije pomou steka


Ako programski jezik dozvoljava rekurzivne pozive potprograma onda nije mogue koristiti
statiku alokaciju memorije. Naime u ovom sluaju u jednom trenutku moe da postoji vie
aktiviranih instanci potprograma i za svaki takav poziv potreban je poseban aktivacioni slog.
Jedna od tehnika koju je u ovom sluaju mogue koristiti je alokacija memorije pomou steka, u
okviru koje se prilikom svakog poziva potprograma kreira novi aktivacioni slog i smeta na stek.
Kada se izvravanje odreene istance potprograma zavi odgovaraji aktivacioni slog se skida sa
steka. U jednom trenutku u steku moe da se nalazi vie istanci aktivacionog sloga jednog
potprograma, kao i vie tazliitih aktivacionih slogova.
U vreme kompiliranja programa zna se samo veliina aktivacionog sloga ali ne i dubina rekurzije
(koliko e aktivacionih slogova jednog potprograma u nekom trenutku biti u steku).
Primer 12.3
Uzmimo kao primer rekurzivnu proceduru quiksort kojom se ureuje vektor brojeva, iji je kod
dat u nastavku:
procedure quiksort (m,n: integer);
var i: integer;
begin
if (n>m) then
begin
i := partition (m,n);
quiksort(m, i-1);
quiksort(i+1, n);
end
end;
begin
a[0] := -9999;
a[10] := 9999;
readarray;
quiksort(1,9);
end.
Uoimo da se u datoj proceduri poziva potprogram partition kao i sam potprogram quiksort
rekurzivno i to dvostrukom rekurzijom. U glavnom programu pre poziva potprograma quiksort
poziva se i potprogram readaray. Redosled poziva potprograma najbolje se moe prikazati
aktivacionim stablom koje je za dati primer prikazano na Slici 12.5.

Slika 12.5 Aktivaciono stablo za program iz Primera 12.5.

Svaki vor u aktivacionom stablu sa Slike 12.5 prestavlja jedan poziv potprograma. Pozivi
potprograma koji se izvre iz jedne instance potprograma predstavljeni su vorovima do kojih
vode potezi iz vora koji odgovara toj istanci. Pri tome redosled poziva odgovara redosledu
vorova poslatrano sleva u desno.
Na Slici 12.6 je prikazan redosled ubacivanja aktivacionih slogova u stek koji odgovara delu
aktivacionog stabla prikazanog na Slici 12.5
AKTIVACIONO STABLO Aktivacioni slogovi u steku Komentar

S Aktivacioni slpg glavnog


S programa
A : array

S
A : array
r
readarray
i : integer

Aktivacioni slog potprograma


S r je bio ubaen u stek, a
A : array izbaen iz steka kada se ovaj
potprogram zavrio.
p(1,9) q(1,9) Nakon toga u stek je ubaen
aktivacioni slog potprograma
i : integer q(1,9), a posle toga
aktivacioni slog poziva
p(1,9).

Kada je zavren potprogram


S p(1,9) njegov slog se izbacuje
A : array iz steka. Nakon toga sledi
poziv q(1,3) tako da se u stek
ubacuje jo jedna istanca
q(1,9) aktivacionag sloga
potprograma q.
i : integer
q(1,3)
i : integer
S Potprogram q(1,3) poziva
potprogram p(1,3), tako da se
A : array u stek ubacuje nova istanca
aktivacionog sloga
potprograma p, itd.
q(1,9)
i : integer

q(1,3)
i : integer
p(1,3)
p(1,3)
i : integer

Slika 12.6 Dinamika ubacivana aktivacionih slogova u stek za program iz Primera 12.3.

Dinamika alokacija
Aktivacioni slogovi se smetaju u dinamiku memoriju i ne izbacuju se kao kod stek alokacije,
Slika 12.7. Delu aktivacionog stabla prikazanog na slici odgovara struktura slogva data na istoj
slici.

Slika 12.7 Dinamika alokacija memorije

Vektori u aktivacionom slogu


Aktivacioni slog sadri sve podatke potrebne u okviru jednog poziva potprograma. Meutim, ako
se potprogramu koriste vektori i matrice moe da se desi da aktivacioni slog bude prevelik i da
ograniava dubinu rekurzije. Zbog toga se obino u aktivacionom slogu uvaju samo pokazivai
na poetne lokacije vektora i matrica, dok se same strukture dislociraju iz sloga, Slika 12.8.
AKTIVACIONI SLOG

Slika 12. 8 Vektori dislocirani iz aktivacionog sloga


5. Realizacija alokacije memorije
Da bi se realizovala odreena strategija alokacije memorije kompilator treba da generie
odgovarajuu sekvencu naredbi mainskog ili asemblerskog koda. Ovde emo dati po jedan
primer statike alokacije i alokacije pomou steka.

Realizacija statike alokacije

U sluaju statike alokacije u taki poziva potprograma kompilator treba da zapamti adresu
povratka iz potprograma i skok na sekvencu naredbi potprograma. U te svrhe generie sledeu
sekvencu:
MOV #here + 20, pp.aktivacioni_slog
GOTO pp.kod
Praktino, naredbom MOV #here + 20, pp.aktivacioni_slog, u prvu lokaciju aktivacionog sloga
pozvanog potprograma smeta se adresa povratka u glavni program. U ovom primeru ta adresa je
#here + 20, gde je #here adresa tekue naredbe, vrednost brojaa naredbi (PC registra). Iza ove
naredbe generie se naredba GOTO pp.kod kojom se upravljanje prenosi na prvu naredbu
potprograma. .
U samom potprogramu generie se naredba za povratak u glavni program:
GO TO * pp.aktivacioni_slog
Za primer programa predstavljenog kodom na Slici 12.9, koji se satoji od glavnog programa i
poprograma, struktura aktivacionih slogova data je na istoj slici. Na Slici 12.10 prikazan je kod
koji e biti generisan od strne kompilatora za strategiju statike alokacije.
AKTIVACIONI SLOG ZA P

Slika 12.9 Primer programa C i potprograma P


/* Kod programa c */
100: ACTION1
120 : MOV #140, 364 /* 140 je adresa povratka*/
132: GO TO 200 /* Skok na poptprogram */
140 : ACTION2
160: HALT
/* Kod poptprograma p */
200: ACTION3
220: GO TO *364 /* Povratak u program c */
300: /* 300-363 aktivacioni slog za c */
304: /* adresa povratka */
/* Lokalni podaci za c */
364: /* 364-451 aktivacioni slog za p *
368: /* adresa povratka *
/* Lokalni podaci za p */

Slika 12.10 Generisani kod za statiku alokaciju


Realizacija alokacije pomou steka
U sluaju alokacije pomou steka zadatak kompilatora je neto sloeniji:
1. Najpre se vri inicijalizacija steka. U te svrhe kompilator generie sledeu sekvencu
naredbi:
/* Inicijalizacija steka */
MOV #stackstart, SP
Kod prve procedure
HALT
2. U taki poziva potprograma generie se sekvenca naredbi kojom se najpre menja
vrednost stek pointera koji ukazuje na poetnu lokaciju steka. Kako je pre poziva
potprograma stek pointer ukazivao na poetak aktivacionog sloga glavnog programa,
treba ga korigovati za duzinu tog aktivacionog sloga tako da pokazuje na prvu lokaciju
aktivacionog sloga pozvanog potprogram. Iza toga pamti se adresa povratka i upravljanje
prenosi na pozvani potprogram. Adresa povratka se pamti u steku, odnosno na poetak
aktivacionognog sloga potprograma, lokaciji na koju ukazuje stek pointer.
/* Dodavanje ak. sloga u stek */
ADD #glpr.recordsize, SP
MOV # here +16, *SP
GOTO pp.kod
3. U potprograma se kao poslednja naredba generie naredba za povratak u glavni program,
pri emu se generie skok na naredbu ija je adresa zapamena u prvom slogu
aktivacionog sloga na koji ukazuje stek pointer.
/* povratak u gl. program */
GO TO *0 ( SP )
4. Po povratku u glavni program treba izvriti korekciju stek pointera tako da ukazuje na
poetak aktivacionog sloga glavnog programa, to odgovara izbacivanju aktivacionog
sloga potprograma iz steka:
/* izbacivanje sloga iz steka */
SUB #glpr.recordsize, SP

Za troadresni kod quicksort programa dat na Slici 12.11. bie generisana sekvenca naredbi data
na Slici 12.12.

/* kod za q
*/
action4
call p
action5
call q
action6
call q
return
Slika 12.11 Troadresni kod quicksort programa
/* Kod za proceduru s */
100: MOV #600, SP /* inicijalizacija steka */
108 : ACTION1
128: ADD #ssize, SP /* poziv potprograma */
136: MOV #152, *SP /* adresa povratka ide u stek */
144: GO TO 300 /* skok na pocetak pp q */
152: SUB #ssize, SP /* obnavljanje SP */
180 HALT

/* Kod za proceduru p*/


200: ACTION3
220: GO TO *0(SP) /* return */

/* Kod za proceduru q*/


300: ACTION4
320 : ADD #qsize, SP
328: MOV #344, *SP /* pamti se adresa povratka */
336: GO TO 200 /* poziv pp P */
344: SUB #qsize, SP
352: ACTION5
372: ADD #qsize, SP
380: MOV #396, *SP /* pamti se adresa povratka */
388: GO TO 300 /* poziv pp q */
396: SUB #qsize, SP
404: ACTION6
424: ADD #qsize, SP
432: MOV #448, *SP /* pamti se adresa povratka */
440: GO TO 300 /* poziv pp q */
448: SUB #qsize, SP
456: GO TO *0(SP) /* return */
.
600: /* Stek zapocinje ovde */

Slika 12.12 Generisani kod koji odgovara programu iz Primera 12.7

5. Tehnike prenosa parametara u potprogram


U ovom odeljku emo razmotriti kako se realizuju razliite tehnike prenosa parametara u
potprogram. Naime poznato je da se za prenos parametara u potprogram koriste razliite tehnike
prenosa meu kojima su nazastupljenije:
Poziv po vrednosti (call by value)
Poziv po referenci (call by reference)
Poziv po vrednosti i rezultatu (call by values and result)
Poziv po imenu (call by name) i sl.

You might also like