While och bytecode
Hej Alla!
Någon kanske har funderat över kopplingen mellan Adubakod och bytecode-instruktionerna som användes i det förra inläggets uppladdade källkod. Vi tänker använda WhileLoopTest()-metoden som finns där, för att visa de bakomliggande tankarna. I WhileLoopTest()-metoden kör vi följande Adubakod:
MODULE test; VAR i:INTEGER; BEGIN i := 0; WHILE i < 3 DO BEGIN i := i + 1; END END
Innan tittar på motsvarande bytecode-instruktioner måste vi reda ut några saker:
Var/hur lagrar man variabler?
Hur går det till när man beräknar uttryck?
Vi har löst baserat vårt exekveringssystem på ECMA-335 när vi har lekt med programkod (speciellt kapitel I.12 samt III.3). ECMA använder något som de kallar för Local Variable Array (LVA) för att lagra variabler. För vår del är det inget annan än ett fält (eng. array) som består av ValueType’s vilket är bastypen för en variabel. LVA är vår bas för lagring och det är där variabeln i kommer att finnas som ett element.
Ett enkelt sätt att utföra uttryck är att använda en stack och det är bra för vår motor är stackbaserad. ECMA kallar denna “beräkningsstack” för Evaluation Stack (ES). Vi använder ordet ‘stack’ i texten om inget annat anges. Det är via denna stack som vi t ex utför i < 3 och i + 1. Så, för att utföra i + 1 kommer innehållet av variablen i samt 1 att läggas på stacken varefter operatorn + hämtar dessa två stackelement och adderar dessa. Resultatet av additionen läggs sedan tillbaka på stacken.
Vi behöver en sak till och det är ett sammanhang för vår LVA och ES. Anledningen till detta är vi inte vill blanda samman egenskaper som är specifika för procedureanrop (även om det skulle gå, så gör detta hanteringen enklare). Detta sammanhang kallas för ‘Method State’ av ECMA och är alltså en samling av egenskaper som är till för hålla ordning på saker och ting när man exekverar ett anrop. Ytterligare egenskaper, annat än LVA och ES, som placeras där är t ex den aktuella instruktionspekaren.
Nu är vi framme vid instruktionerna och om ni tittar i ECMA’s kapitel III.3 så ser ni var inspirationen kommer ifrån. I varje instruktionsbeskrivning nedan finns följande delar:
En kort sammanfattning över vad instruktionen gör.
Eventuella parametrar.
Stackens utseende före och efter att instruktionen utförts. Den notationen finns beskriven i ECMA dokumentet kapitel III.1.3.
Listan av instruktioner som används för att köra Adubakoden ovan:
LdLoc (Load Location)
Ladda variabel till stacken (push).
Parameter: index i LVA där variabeln är lagrad.
Stack: … —> …, värde
StLoc (Store Location)
Hämta värde från stacken (pop) och lagra i variabel.
Parameter: index i LVA där variabeln är lagrad.
Stack: …, värde —> …
LdcInt (Load Constant Int)
Ladda heltalsvärde till/på stacken.
Parameter: Heltalsvärde.
Stack: … —> …, värde
Clt (Compare Less Than)
Utför värde1 < värde2. Om sant är resultat satt till 1, annars 0.
Stack: …, värde1, värde2 —> …, resultat
BrFalse (Break if false)
Hoppa till <instruktionsadress> om värdet på stacktoppen är 0.
Parameter: Instruktionsadress.
Stack: …, värde —> …
Br (Break)
Hoppa till <instruktionsadress>.
Parameter: Instruktionsadress.
Stack: … —> …
Add
resultat = värde1 + värde2.
Stack: …, värde1, värde2 —> …, resultat
Exit
Avsluta exekvering.
Äntligen, översättningen från Aduba till bytecode instruktioner. Nedanstående rader är uppdelade i fyra kolumner: den första är radnummer för att göra det lättare att hänvisa till i själva förklaringen, den andra är minnespositionens start för instruktionen, den tredje är själva instruktionen och slutligen den fjärde som är en kommentar. Variabeln i kommer att ligga på plats 0 i LVA och ES är tom när exekveringen startar.
Rad Pos Instruktion Kommentar =================================================================================== 1 00 LdcInt, 0 Lägg 0 på stacken. 2 02 StLoc, 0 Spara värdet på stacken i variabeln i. 3 04 LdLoc, 0 Lägg i’s värde på stacken. 4 06 LdcInt, 3 Lägg 3 på stacken. 5 08 Clt Utför i < 3 och lägg 1 på stacken om det är sant, annars 0. 6 09 BrFalse, 20 Om 0 ligger på stacken hoppa till instruktionen som har minnespos 20 7 11 LdLoc, 0 Här hamnar vi om i < 3 är sant. Lägg i’s värde på stacken. 8 13 LdcInt, 1 Lägg 1 på stacken. 9 15 Add Addera. 10 16 StLoc, 0 Spara värdet på stacken i variabeln i. 11 18 Br, 4 Hoppa till instruktionen på minnespos 4 (rad 3). 12 20 Exit Här hamnar man om i < 3 inte är sant.
Man kan också sammanfatta kopplingen mellan Adubakoden och instruktionerna så här:
BEGIN Rad 1-2 i:=0 Rad 3-6 WHILE i < 3 DO BEGIN Rad 7-10 i:=i+1; Rad 11 END Rad 12 END
En något kort förklaring, men det var det hela.
Är det någon som vill vara med och skapa Aduba så är ni ypperligt välkomna oavsett kunskapsnivå! Det viktiga är att vi har kul tillsammans!