Luku 6

Aktivaatiotietueen rakentaminen

Tässä osiossa käydään läpi protokolla, joka kutsuvan ja kutsutun rutiinin pitää noudattaa aktivaatiotietueiden rakentamisessa ja purkamisessa.

Aktivaatiotietueen rakentaminen ja purku

Aktivaatiotietueen rakentaminen ja purku tapahtuvat kahdessa vaiheessa. Osan työstä tekee kutsuva rutiini usean konekäskyn avulla ja osan työstä tekee kutsuttu rutiini niin ikään usean konekäskyn avulla.

Kutsuva rutiini aloittaa työn ja laittaa pinoon ensin tilan paluuarvolle (jos kyseessä on funktio) ja sitten kaikki parametrien arvot, oman tyyppinsä mukaisesti.

push sp, =0        ; tila paluuarvolle
push sp, x         ; arvoparametri esimerkki
push sp, =x         ; viiteparametri esimerkki

Seuraavaksi call-käskyllä pinoon laitetaan PC:n nykyarvo eli paluuosoite ja FP nykyarvo eli kutsuvan rutiinin AT:n osoite. Tässä yhteydessä kontrolli siirtyy kutsutulle rutiinille, joka rakentaa sitten loput AT:stä ennen varsinaista laskentatehtäväänsä.

call sp, funcX     ; pinoon vanha PC ja vanha FP

Kutsuttu rutiini tekee nyt aluksi hallinnolliset alkutoimet, eli prologin. Siinä varataan tilat paikallisille tietorakenteille ja talletetaan tarvittavien työrekisterien arvot.

push sp, =0    ; tila ensimmäiselle paikalliselle muuttujalle, alkuarvo 0
pushr sp       ; talleta kaikki työrekisterit

Nyt AT on valmis ja itse rutiinin työ voidaan tehdä. Jos kyseessä on funktio, niin lopuksi pitää paluuarvo tallettaa omalle paikalleen AT:hen.

Lopuksi aloitetaan aktivaatiotietueen purku eli epilogi. Hyvin usein todellisissa symbolisissa konekielissä on tehokkaat makrot epilogin ja prologin koodien tuottamiseksi. Ensin palautetaan talletettujen työrekistereiden arvot ja vapautetaan paikallisten tietorakenteiden tilanvaraukset. Lopuksi kontrolli ja suoritusympäristö palautetaan kutsuvalle rutiinille exit-käskyllä, joka samalla vapauttaa parametrien tilanvaraukset pinosta.

popr sp     ; palauta kaikki työrekisterit
sub sp, =1  ; vapauta paikallisen muuttujan tilanvaraus
exit sp, =2 ; palauta PC ja FP pinosta, vapauta 2 parametrin tila

Nyt kontrolli on takaisin kutsuvalla rutiinilla, joka ottaa funktion paluuarvon käyttöönsä pinosta (jos kutsuttu rutiini oli funktio). Näin koko kutsutun rutiinin AT on purettu ja pinon sisältö on täsmälleen sama kuin mitä se oli ennen rutiinin kutsua.

pop sp, r1  ; poista funktion arvo pinosta rekisteriin r1

Esimerkki funktion toteutuksesta

Käytetään esimerkkinä kokonaislukuarvoista funktiota fA(x,y), joka käyttää paikallista muuttujaa z (alkuarvo 5) ja palauttaa arvonaan lausekkeen x*z+y arvon.

int fA (int x, y) {  /* x ja y arvoparametreja */
    int z = 5;

    z = x * z + y;
    return(z)
    }

Funktiota fA käytetään lauseen t = fA(200, r) toteutukseen, kun r ja t ovat globaaleja muuttujia.

Kutsuvan rutiinin koodi

Kutsuvassa rutiinissa funktion käyttö tapahtuu konekielellä seuraavanlaisesti.

r  dc 24      ; r on globaali muuttuja, alkuarvo 24
t  dc 55      ; t on globaali muuttuja, alkuarvo 55
   ...
;
; toteuta t = fA(200, r)
;
k1    push sp, =0   ; tila paluuarvolle
k2    push sp, =200 ; vakio 200
k3    push sp, r    ; muuttujan r arvo
k4    call sp, fA   ; funktion kutsu
k5    pop sp, r1    ; paluuarvon poisto pinosta
k6    store r1, t

Ennen funktion kutsun aloittamista (käsky k1) pinossa on kutsuvan rutiinin AT.

    FP  -->   ??    ; kutsuvan rutiinin AT
              ...
    SP -->    ??

Juuri ennen funktion kutsua (käsky k4) pinossa on paikka paluuarvolle ja parametrit.

    FP  -->   ??    ; kutsuvan rutiinin AT
              ...
              ??
              0
              200
    SP -->    24

Heti funktiosta palattua (ennen käskyn k5 suoritusta) pinossa on kutsutun rutiinin AT:stä jäljellä vain paluuarvo (jos sitä yleensä oli).

    FP  -->   ??    ; kutsuvan rutiinin AT
              ...
              ??
    SP -->    1024  ; funktion paluuarvo

Lopulta käskyn k5 suorittamisen jälkeen pino on ennallaan ja suoritus jatkuu kutsuvan rutiinin ympäristössä.

    FP  -->   ??    ; kutsuvan rutiinin AT
              ...
    SP -->    ??

Kutsutun rutiinin koodi

Funktio fA() voidaan toteuttaa konekielellä seuraavalla tavalla. Määrittelemme aluksi symbolit paluuarvon, parametrien ja paikallisten tietorakenteiden suhteellisille sijainneille AT:ssä. Kaikki viitteet noihin tietorakenteisiin tehdään sitten noiden symbolien avulla käyttäen niitä suhteellisina osoitteina AT:ssa.

;
; funktio fA(x,y)    x ja y ovat arvoparametreja
;
retfA equ -4   ; paluuarvon suhteellinen osoite AT:ssa
parX  equ -3   ; parametrien x ja y suhteelliset osoitteet AT:ssa
parY  equ -2
locZ  equ 1    ; paikallisen muuttujan z suhteellinen osoite AT:ssä

fa    push sp, =0  ; tilanvaraus paikalliselle muuttujalle AT:ssä
      push sp, r1  ; talleta r1

      load r1, =5  ; alusta Z
f4    store r1, locZ(fp)  ; viite Z:aan fp:n kautta

      load r1, parX(fp)  ; funktion varsinainen koodi
      mul r1, locZ(fp)
      add r1, parY(fp)
      store r1, locZ(fp)

      store r1, retfA(fp) ; talleta paluuarvo

f10   pop sp, r1   ; palauta r1
      sub sp, =1   ; vapauta Z:n tilanvaraus
f12   exit sp, =2  ; paluu kutsuvaan rutiiniin

Kun kontrolli on siirtynyt fA:lle (käsky fa), pinossa on paikka paluuarvolle, parametrit sekä vanha PC ja FP:

              ??
vanha FP -->  ...   ; kutsuvan rutiinin AT
              ??
              0
              200
              24
              vanha PC
FP, SP -->    vanha FP

Kun prologi ja paikallisen muuttujan z alustus on tehty (käsky f4), uusi AT on valmis ja pinon sisältö on seuraavanlainen:

              ??
vanha FP -->  ...  ; kutsuvan rutiinin AT
              ??
              0
              200
              24
              vanha PC
    FP -->    vanha FP
              5
    SP -->    vanha r1

Juuri ennen epilogia (f10) funktion työ on tehty ja paluuarvo on paikallaan:

              ??
vanha FP -->  ...  ; kutsuvan rutiinin AT
              ??
              1024
              200
              24
              vanha PC
    FP -->    vanha FP
              5
    SP -->    vanha r1

Epilogissa palautetaan r1:n vanha arvo ja vapautetaan Z:n tilanvaraus:

              ??
vanha FP -->  ...   ; kutsuvan rutiinin AT
              ??
              1024
              200
              24
              vanha PC
FP, SP -->    vanha FP
              5
              vanha r1

Lopulta exit-käsky (f12) palauttaa pinosta FP:n ja PC:n arvot ennalleen (ja SP:n arvo vähenee vastaamaan pinosta poistettua määrää eli vähenee kahdella) ja poistaa lisäksi 2 parametria pinosta (tarkemmin ottaen siis vähentää SP:n arvosta 2). Nyt pino-osoitin SP osoittaa funktion paluuarvoon (1024). Tämän jälkeen suoritus siirtyy kutsuvalle rutiinille. Kutsuva rutiini sitten poistaa paluuarvon pinosta (pop sp, r1) ja käyttää haluamallaan tavalla.

              ??
      FP -->  ...   ; kutsuvan rutiinin AT
              ??
      SP -->  1024
              200
              24
              vanha PC
              vanha FP
              5
              vanha r1
Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan:

Muistathan tarkistaa pistetilanteesi materiaalin oikeassa alareunassa olevasta pallosta!