home *** CD-ROM | disk | FTP | other *** search
-
-
-
- PASCOMP
-
- PASCAL baut einen Pascal-Compiler
-
- Teil 7: Der P-Code Interpreter
- von Johannes Velmans
-
- Unser PASCOMP-Projekt nimmt langsam Gestalt an. Beschäftigten wir
- uns in den ersten Folgen hauptsächlich mit den Grundlagen und
- Theorien des Compilerbaus, so ist es jetzt an der Zeit, sich Ge-
- danken über den interpretativen Teil zu machen. Mit den bisheri-
- gen Hilfsmitteln sind wir in der Lage, ein beliebiges Pascal-
- Programm in ein äquivalentes P-Code- Programm zu übersetzen. Da
- der Prozessor unserer benutzten Maschine aber keinen P-Code ver-
- steht, müssen wir ein Programm schreiben, das in der Lage ist,
- eine P-Code-Maschine zu simulieren und somit unser Pascal- Pro-
- gramm auszuführen - den P-Code- Interpreter.
-
- Die letzte Folge dieser Serie war darauf ausgerichtet, einiges
- über die Struktur des P-Codes zu vermitteln. Dieser Teil baut nun
- im wesentlichen auf dem Wissen der letzten Folge auf. Deshalb
- sollte man sich ruhig noch einmal die letzte Folge zur Hand neh-
- men, damit man die eine oder andere Sache in diesem Kapitel nicht
- direkt als "böhmisches Dorf" betrachtet.
-
-
- Zweiteilung des Interpreters
- Beim Aufruf des Interpreters werden zwei große Prozesse nachein-
- ander bearbeitet. Der erste Prozeß ist der Assembler. In dieser
- Phase wird der vom Compiler abgelieferte P-Code-Text in eine äqu-
- ivalente Folge von P-Code-Maschinenbefehlen, die aus einzelnen
- Integer-Zahlen bestehen, umgewandelt. Im zweiten Prozeß, der In-
- terpretation, wird dann das Programm effektiv ausgeführt.
-
- Der Assembler erzeugt zwei Datenstrukturen für den späteren Ge-
- brauch durch den Interpreter. Die erste ist die erzeugte Code-
- Folge, welche die P-Code-Befehle in assemblierter Form, also in
- Zahlendarstellung beinhaltet. Diese Struktur ist intern in der
- Implementierung des Interpreters ein Array, das in jeder Kompo-
- nente drei Zahlen aufnehmen kann. Die erste Zahl ist der P-Code-
- Befehl - der Operator, die zweite und dritte Zahl können even-
- tuelle Parameter sein.
- In der zweiten durch den Assembler erzeugten Struktur werden Kon-
- stanten abgespeichert, die später vom Interpreter benutzt werden
- können. Dabei werden Konstanten bis auf die Ausnahme von Text-
- strings in separaten Arrays zur Speicherplatzersparnis unterge-
- bracht. Diese Konstantentabellen sind im Interpreter als globale
- Variable untergebracht und haben folgende Bezeichnung:
-
- Boundtable:
- Diese Tabelle findet bei der Grenzbereichsüberprüfung ihre Ver-
- wendung. In ihr werden die zu testenden Grenzen in Paarform (Un-
- tergrenze, Obergrenze) abgelegt.
-
- Longtable:
- Hier werden Longinteger-Konstanten untergebracht.
-
- Realtable, Settable:
- Entsprechende Konstanten-Tabellen für Realzahlen und Mengen-Kon-
- stanten.
-
- Alle anderen in einem Pascal-Programm verwendeten Konstanten wie
- integer, char, boolean usw. haben aufgrund ihrer geringen Spei-
- chergröße im Code-Array Platz und benötigen daher keine explizi-
- ten Tabellen zur Abspeicherung ihrer Werte.
-
-
- Aufruf des Assemblers
- Der Assembler-Prozess wird in der Implementierung des Interpre-
- ters durch eine Prozedur mit dem Namen 'Load' gestartet und er-
- zeugt zu jeder P-Code- Quellzeile einen äquivalenten Indexeintrag
- im Code-Array. Beispielsweise wird durch die P-Code-Zeile
-
- lodr 4 5
- der Eintrag
- '124 4 5'
-
- im Code-Array erzeugt. Parallel zu der Erzeugung des Maschinenco-
- des wird eine Tabelle zur Verwaltung der benutzten Sprungmarken
- aufgebaut und gewartet. Somit können direkte Sprünge berechnet
- und in den Code eingefügt werden. Diese Labeltabelle wird für die
- spätere Phase der Interpretation nicht mehr benötigt. Daher wird
- der für diese Tabelle benötigte Speicherplatz nach Abschluß der
- Assemblerphase dem Hauptspeicher des Rechners wieder zur Verfü-
- gung gestellt.
-
-
- Der Interpreter
- Nachdem der Assembler den P-Code in das Code-Array transformiert
- und eventuell aufgetretene Konstanten in den entsprechenden Kon-
- stanten-Tabellen untergebracht hat, tritt nun der Interpreter in
- Aktion. Dieser führt die P-Code-Befehle in einer großen While-
- Schleife aus. Innerhalb dieser Schleife befindet sich eine Case-
- Anweisung über alle P-Code-Befehle. Das Konzept des Interpreters
- ist, wie man sieht, eigentlich ganz trivial und dürfte dem mit-
- tlerweile erfahrenen PASCOMP-Leser keine Schwierigkeiten berei-
- ten. In der zentralen Schleife gibt es scheinbar nur wenige Pro-
- zeduren, die dem Namen nach nichts mit den P-Code-Befehlsnamen zu
- tun haben. Dazu gehören die Prozeduren 'Compareblock', 'Basis'
- sowie die Prozedur 'Callstdprocs'. Die Bedeutung der einzelnen
- Prozeduren sei hier kurz erklärt:
-
- Basis:
- Die Funktion 'Basis' wird vom Interpreter dazu benutzt, um die
- Verbindung zu unterschiedlichen Laufzeitschachteln herzustellen.
-
- Compareblock:
- Die Prozedur 'Compareblock' vergleicht Strings miteinander und
- legt das Ergebnis dieses Vergleichs als boole'schen Wert auf den
- Stack ab.
-
- Callstdprocs:
- Die Prozedur 'Callstdprocs' führt den Aufruf von Standardprozedu-
- ren aus, die in der P-Code-Source mit 'csp <stdprocname>' gekenn-
- zeichnet sind.
-
- Alle anderen Prozeduraufrufe, die in der zentralen Schleife des
- Interpreters auftreten, stehen in direktem Zusammenhang mit der
- Ausführung der P-Code-Befehle. Die Namen dieser Prozeduren setzen
- sich aus einem 'P' gefolgt von dem zugehörigen P-Code-Befehl zu-
- sammen - PEQU, PNEQ, PUNI, PCHK...
-
- Um die Analyse des Programms zu vereinfachen, stehen dem Benutzer
- des Interpreters während der Laufzeit einige Hilfsmittel zur Ver-
- fügung. Dazu gehört eine Prozedur 'Postmortemdump', die nach ei-
- nem erfolgten Absturz des Benutzerprogramms den Inhalt des Stack
- darstellt und die Werte des Programmzählers PC, des Markstack-
- pointers MP und des Newpointers NP ausgibt. Eine weitere Hilfs-
- Prozedur ist 'Writekeller', die bei einem Laufzeitfehler die Na-
- men sämtlicher auf dem Stack befindlichen Laufzeitschachteln auf
- dem Bildschirm ausgibt und somit die aktuelle Situation des
- Stacks wiederspiegelt.
-
- Dadurch wird eine Rückverfolgung der dynamischen Vorgänger we-
- sentlich vereinfacht. Als letztes Laufzeithilfsmittel steht dem
- Benutzer die Abbruchsfunktion zur Verfügung, das heißt, ein Pro-
- gramm kann zu jeder Zeit seiner Ausführung durch den Benutzer mit
- Ctrl-C abgebrochen werden. Als Abschluß ist hier noch ein Auszug
- aus dem Interpreter dargestellt, der nochmals das Prinzip und die
- Arbeitsweise desselbigen verdeutlicht.