Funktionsweise des Zwischencodeinterpreters

Virtuelle Maschine


Eine virtuelle Maschine ist ein Rechner, der physisch nicht existiert. Seine Bestandteile werden durch ein Programm simuliert. Es muss alle Bestandteile eines physischen Rechners nachbilden.



Je nach Arbeitsweise unterscheidet man zwischen



Der Befehlssatz (code.h)


Die virtuelle Maschine zum Modellcompiler wurde als Stackmaschine realisiert. Der Befehlssatz ist in dem Headerfile code.h enthalten. Bei genauerer Betrachtung lassen sich 4 Befehlsgruppen erkennen.

  1. Keller-Befehle

    Push-Befehle schreiben Werte oder Adressen in den Keller. Als Operand ist immer die Relativadresse der betreffenden Variable anzugeben. Handelt es sich um eine zur aktuellen Prozedur globale Variable, so ist die Prozedurnummer der Prozedur, die die Variablendefinition enthält, zusätzlich anzugeben. Der PuConst Befehl kellert eine zu indizierende Konstante aus dem Konstantenblock. Der storeVal Befehl entfernt aus dem Keller einen zu speichenden Wert und die Zieladresse und speichert den Wert auf die Adresse.

  2. Arithmetische und Vergleichsbefehle

    Die arithemetischen und Vergleichsbefehle entnehmen dem Stack ein (unäre Operatoren odd und - ) bzw. zwei (binäre Operatoren) Operanden und speichern das Ergebnis wieder im Stack. Bei Vergleichsbefehlen oder dem Befehl odd ist das Ergebnis ein Wahrheitswert.

  3. Sprungbefehle

    - unbedingter Sprung(jmp): Das Sprungziel wird als Differenz zwischen dem aktuellen Programmcounter und dem Sprungziel angegeben. Der aktuelle Programmcounter zeigt hinter die Relativadresse des Sprungbefehls.

    - bedingter Sprung (jnot): Das Sprungziel wird ebenfalls als Differenz angegeben, zusätzlich wird ein Wert ausgekellert, der als Wahrheitswert interpretiert wird.

    - Unterprogramm: call hat als Parameter die Prozedurnummer der zu rufenden Prozedur (siehe Sematikroutinen/Namensliste). Die virtuelle Maschine hält eine Prozedurtabelle, in der ua. Die Anfangsadressen der Prozeduren abgelegt sind. Der call -Befehl legt den aktuellen Programmcounterwert auf den Stack und schreibt die Startadresse der Prozedur, die aus der Prozedurtabelle durch Indizierung mit der Prozedurnummer ermittelt wird in den Programmcounter. Der erste Befehl der aufgerufenen Prozedur ist immer entryProc. Seine Parameter sind die Codelänge, die vom Codelader ausgewertet wird, die Variablenlänge und die Prozedurnummer. Dieser Befehl richtet die Prozedur, ihre Variablen und den Stackpointer ein. Über retProc wird die Prozedur schließlich verlassen.

  4. Ein-Ausgabebefehle

    putVal: Ausgabe eines Wertes aus dem Keller, der Wert wird aus dem Keller entfernt.

    getVal: Eingabe eines Wertes, der Wert wird auf eine Adresse geschrieben, die vom Stack geholt wird.


Die virtuelle Maschine arbeitet mit folgenden Datenstrukturen:


Register

Variable der VM

ProgrammCounter

pC

Stackpointer

pS

Prozedurtabelle

pInfProc

KonstantenPointer

pConst

Aktuelle Prozedur

iCProc



Der Ladevorgang





Datenstruktur nach dem Laden


Situation nach dem Laden, nach entryProc des Hauptprogramms
Programmbeispiel
DrawObject
var a,b,Max;
procedure p1;
begin
  if a>=b then Max:=a;
  if a< b then Max:=b
end;
begin
  ?a;?b;
  call p1;
  !Max
end.


Nach dem Laden wird entryProc des Hauptprogramms ausgeführt, danach ergibt sich die dargestellte Situation. Die Prozedurtabelle (pInfProc) ist ausgefüllt, der Stack ist angelegt, ebenso die Variablen des Hauptprogramms (a,b,Max). Stackpointer und Programmcounter sind mit den entsprechenden Werten belegt.

Beispiel