Inhaltsverzeichnis

4.3 Bedienung des Compilers Pascal2.0

Der Compiler übersetzt den Quelltext, der sich im Arbeitsspeicher befindet in einem Durchlauf (one pass) in ein direkt ausführbares Programm, das wie ein BASIC-Programm gestartet und gespeichert werden kann. Quelltext, Objektprogramm, Editor und Compiler residieren gleichzeitig im Arbeitsspeicher, so daß während der Programmentwicklung auf Diskettenzugriffe verzichtet werden kann.

4.3.1 Wahl der Optionen

Der Compiler wird aus dem Pascal-Menü (s. Abschnitt 4.2.1) mit der Eingabe »$« (beendet mit der RETURN-Taste) aufgerufen. Alle Ausgaben des Compilers erfolgen in dem Bildschirmmodus, in dem der Compiler aufgerufen wurde. War zum Beispiel im Pascal-Menü der 40-Zeichen Bildschirm aktiviert, so erscheinen die im Folgenden beschriebenen Dialoge auf diesem Bildschirm.

Sollten Sie über einen 80-Zeichen Monitor verfügen, ist es sinnvoll, den Rechner mit einer Taktfrequenz von 2 MHz (Kommando FAST in BASIC oder Pascal) zu betreiben, da dadurch die Compiler- geschwindigkeit praktisch verdoppelt wird.

Beim ersten Start des Systems nach dem Laden von der Diskette erscheint ein Copyright-Hinweis. Der Compiler meldet sich mit der folgenden Meldung:

PASCAL 2.0 (Rx.x)
-----------------

SELECT OPTION:
0 CHECK SYNTAX
1 GENERATE CODE
ELSE LOCATE ADDRESS

==>1

»x.x« bezeichnet dabei den release des Programmes. Durch die Eingabe einer ganzen Zahl können Sie den Übersetzungsmodus des Compilers wählen. Innerhalb des Compilers müssen >alle Eingaben mit der RETURN-Taste abgeschlossen werden.

Syntaxüberprüfung

Durch die Eingabe der Zahl 0 wird der Quelltext im Arbeitsspeicher mit eventuell vorhandenen Include-Files gelesen und auf syntaktische Korrektheit geprüft. Alle Fehler werden im Quelltext markiert. Jedoch wird kein ausführbarer Code erzeugt. Diesen Modus können Sie verwenden, um ein Programm auf Korrektheit zu überprüfen, ohne ein bereits zuvor erzeugtes Objektprogramm im Arbeitsspeicher zu überschreiben. Der Geschwindigkeitsgewinn gegenüber einer Übersetzung mit Codeerzeugung ist nur minimal.

Codeerzeugung

Mit der Zahl 1 wählen Sie den voreingestellten Compilermodus: Es wird der Quelltext gelesen, auf syntaktische Korrektheit geprüft und auftretende Fehler werden im ausgegebenen Programmlisting markiert. Werden keine Fehler entdeckt, so steht am Ende der Übersetzung ein ausführbares Objektprogramm im Arbeitsspeicher.

Suche nach Laufzeitfehlern

Jede andere Zahl als 0 oder 1 wird als eine Fehleradresse im Objektprogramm interpretiert, deren Lage im Quelltext lokalisiert werden soll. Bei dieser Eingabe liest der Compiler ebenfalls den Quelltext, ohne jedoch Code zu erzeugen. Stattdessen wird die Position des Laufzeitfehlers bestimmt. Diese Fehlerposition wird mit der Fehlernummer 0 und dem Fehlertext »ADDRESS OF RUNTIME ERROR« markiert. Beachten Sie bitte, daß eine Fehleradresse auch negativ sein kann, da die Adresse im Zweierkomplement dargestellt wird.

Nähere Informationen zum Thema Laufzeitfehler und Beispiele finden Sie in den Abschnitten 4.3.3 und 1.3.4.

Nach der Wahl des Compilermodus können Sie noch wählen, ob das Programmlisting auf dem Drucker ausgegeben werden soll:

LISTING TO PRINTER?
==>N

Durch die Eingabe eines anderen Buchstabens als »N« an dieser Stelle wird der Quelltext einschließlich Include-Files mit eventuell vorhandenen Fehlermeldungen und einer Übersicht über die Größe des erzeugten Codes auf das Peripheriegerät mit der Geräteadresse 4 an der seriellen Schnittstelle (das ist normalerweise der Drucker) ausgegeben.

Bestätigen Sie nach dem Aufruf des Compilers die beiden Vorgaben (»1« und »N«) einfach durch Betätigung der RETURN-Taste, so wird der Quelltext in ein Objektprogramm im Arbeitsspeicher übersetzt, wobei gleichzeitig ein Programmlisting mit Meldungen des Compilers am Bildschirm ausgegeben wird.

4.3.2 Meldungen innerhalb des Compilers

Während der Compilation wird der Quelltext zeilenweise am Bildschirm angezeigt. Bei der Umschaltung auf Include-Files (s. Abschnitt 4.4.6.2) wird auch der von der Diskette gelesene Text angezeigt.

Bei der Übersetzung jedes Programmblockes wird einmal geprüft, ob die RUN/STOP-Taste betätigt wurde. In diesem Fall wird folgende Bestätigungsmeldung ausgegeben:

BREAK IN xxxx
'*' STOP
ELSE CONTINUE
==>

Wollen Sie die Übersetzung tatsächlich abbrechen, so geben Sie jetzt »*« ein. Bei jeder anderen Eingabe setzt der Compiler seine Arbeit fort. Wird die Übersetzung abgebrochen, so kehren Sie direkt zum Pascal-Menü zurück. In diesem Fall steht natürlich kein ausführbares Objektprogramm im Arbeitsspeicher.

Stellt der Compiler einen Fehler im Quelltext fest, so wird mit einem Pfeil unterhalb der Zeile das Symbol markiert, bei dessen Verarbeitung der Fehler entdeckt wurde:

Beispiel: In dieser Anweisungsfolge fehlt zwischen den Zuweisungen ein Semikolon:

BEGIN X:=Y  Y:=Z END;
            ^ ERROR 14 IN 13

Die Fehlernummern werden im Anhang erläutert. Ein generelles Problem der Sprache Pascal besteht darin, daß Fehler in der Blockschachtelung unter Umständen erst lange nach der eigentlichen Fehlerursache vom Compiler entdeckt werden können. Sollten Sie z.B. die folgende Fehlermeldung erhalten,

END;
   ^ ERROR 20 IN 99

so finden Sie als Erklärung für die Fehlernummer 20 im Anhang B den Text »'.' erwartet«. Mit großer Wahrscheinlichkeit bestand aber der Fehler darin, daß Sie einige Zeilen zuvor das Wortsymbol END überflüssigerweise angegeben hatten, so daß der Compiler an dieser Stelle den Punkt am Programmende erwartet. Deshalb sollten Sie Ihre Fehlersuche nicht ausschließlich auf die mit einem Pfeil markierte Textposition beschränken.

Neben der Fehlernummer wird noch eine Zeilennummer angegeben. Sie bezieht sich immer auf die innerhalb des Editors angezeigten Zeilennummern, die von 0 in Einerschritten gezählt werden. Fehler in einem Include-File auf der Diskette werden mit einer Zeilennummer relativ zum Anfang des Include-Files markiert, so daß Sie die Zeilennummer für die Korrektur des Files im Editor kennen.

Nach dem Auftreten eines Fehlers besitzen Sie folgende Wahlmöglichkeiten:

'*' STOP  '?' EXPLANATION
ELSE CONTINUE
==>

Mit der Eingabe eines Sterns (»*«) brechen Sie die Übersetzung ab und kehren direkt zum Pascal-Menü zurück. Zu jeder Fehlernummer können Sie durch die Eingabe eines Fragezeichens (»?«) einen kurzen erläuternden Text erhalten. Diese Texte sind in englischer Sprache in dem File »ERRORS.TXT« auf Diskette gespeichert. Ist dieses File nicht auf der eingelegten Diskette vorhanden, wird statt einer Erläuterung der Text

NO MESSAGE FOUND

angezeigt. Geben Sie weder »*« noch »?« ein, so wird die Übersetzung fortgesetzt. Gelegentlich können auf einen Fehler mehrere Folgefehlermeldungen auftreten, die Sie durch einfache Betätigung der RETURN-Taste übergehen können.

Nach dem Auftreten eines Fehlers prüft der Compiler weiterhin nur noch auf syntaktische Korrektheit, ohne Code zu erzeugen.

Wurde die Adresse eines Laufzeitfehlers gefunden (Modus LOCATE ADDRESS), so erscheint die Meldung:

WRITELN(1/0);
         ^ ERROR 0 in xxxx

Zur Fehlernummer 0 erhalten Sie folgende Erläuterung

ADDRESS OF RUNTIME ERROR FOUND

Anschließend kehren Sie direkt zum Pascal-Menü zurück.

Wurden keine Fehler im Programm gefunden, so steht am Ende der Übersetzung ein ablauffähiges Programm im BASIC-Arbeitsspeicher. Dieses Programm besteht aus einem kleinen Vorspann und dem eigentlichen Pascalcode. Einen Teil des Codes bilden compilierte Konstanten, die beim Programmstart in Bank 1 kopiert werden (s. Abschnitt 4.3.4 über die Speicherverteilung bei Pascal-Programmen). Die Lage und Größe des erzeugten Code können Sie der folgenden Meldung entnehmen:

ERRORS DETECTED: 0
     P-CODE FROM 7391 TO xxxx
  CONSTANTS FROM 8192 TO yyyy

(HIT RETURN FOR MENU)

Die Rückkehr zum Pascal-Menü erfolgt erst, wenn Sie die RETURN-Taste betätigt haben.

Wenn Sie Programme entwickeln, die länger als 25 K werden, so reicht der erzeugte Programmcode in Bank 0 bis in den für Quelltexte reservierten Speicherbereich hinein (s. Abschnitt 4.3.4). In diesem Fall beginnt der Compiler zwei temporäre Dateien mit den Namen »C$« und »F$« auf der eingelegten Diskette zu erzeugen. Nachdem das Programm fehlerfrei übersetzt wurde, wird am Ende der Compilation der Inhalt der temporären Dateien geladen. Dadurch wird der Quelltext des Programmes überschrieben und die Auswahlmöglichkeit »?« (RESUME EDIT) im Pascal-Menü gesperrt. Zur Warnung erscheint die Meldung:

SOURCE OVERWRITTEN

Sollten Sie Programme größer als 48 K entwickeln, so wird beim Nachladen der temporären Dateien »C$« und »F$« auch der Editor überschrieben. Deshalb wird zunächst die Warnmeldung

EDITOR OVERWRITTEN

ausgegeben. Bei der Rückkehr vom Compiler wird das Pascal-System automatisch ausgeschaltet. Nach der Copyrightmeldung des BASIC- Interpreters erscheint die Meldung:

SYSTEM SWITCHED OFF

Das gesamte Objektprogramm steht dann wie im folgenden Kapitel beschrieben zum Ausführen und Speichern im Arbeitsspeicher. Vor einer erneuten Übersetzung muß jedoch das Pascal-System wieder von Diskette geladen werden.

4.3.3 Rückkehr zu BASIC

Bei der Eingabe »*« im Pascal-Menü verlassen Sie das Pascal-System. Alle nachfolgenden Eingaben werden vom BASIC-Interpreter ausgewertet. Es erscheint die übliche BASIC-Einschaltmeldung:

COMMODORE BASIC V7.0 122365 BYTES FREE
  (C)1985 COMMODORE ELECTRONICS, LTD.
        (C)1977 MICROSOFT CORP.
          ALL RIGHTS RESERVED
Der Rechner befindet sich auch in dem selben Zustand wie direkt nach dem Einschalten, jedoch mit folgenden Unterschieden: In der Speicherbank 0 ist Speicher für den Editor reserviert worden, während in Speicherbank 1 der Compiler und das File »PAS.LIB« gespeichert sind.

Zur Ausführung des übersetzen Programmes genügt die Eingabe des BASIC-Befehls RUN, da der Objektcode einen Vorspann besitzt, der unter anderem aus einer BASIC-Zeile besteht. Diese können Sie sich mit dem BASIC-Befehl LIST anzeigen lassen:

1986 GRAPHICCLR:BANK0:SYS7200: PASCAL 2.0

Dieses Programm sollten Sie nicht verändern oder löschen, da dieser Vorspann für spätere Übersetzungen wiederverwendet wird. Übersetzte Pascalprogramme können auch wie BASIC-Programme gespeichert und geladen werden:

DSAVE"TEST.M"
DLOAD"TEST.M"

Damit Sie später den Quelltext und das Objektprogramm leicht identifizieren können, bietet sich folgende Namenskonvention an: Beim Erstellen von Quelltexten mit dem Editor verwenden Sie das Suffix ».P«, während Sie Objektprogramme mit dem Suffix ».M« speichern.

Beim Start eines Objektprogrammes wird zunächst geprüft, ob das File »PAS.LIB« bereits geladen wurde. Bei Bedarf wird es von der Diskette nachgeladen. Daher muß diese Datei auf jeder Diskette, die Pascal-Programme enthält, ebenfalls vorhanden sein. Beim Start des Pascal-Systems wird die Datei »PAS.LIB« automatisch geladen.

Wird diese Datei auf der Diskette nicht gefunden, erscheint die Meldung

PAS.LIB NOT FOUND ON DISK

In diesem Fall können Sie eine Diskette mit dem File »PAS.LIB« einlegen und das Programm erneut mit RUN starten.

Um von BASIC (nach der Meldung READY.) wieder in das Pascal-Menü zu gelangen, genügt die Eingabe eines Sterns »*« am Anfang einer Zeile, die mit RETURN beendet wird.

Möchten Sie das Pascal-System ganz ausschalten, so geben Sie zwei Sterne »**« am Anfang der Zeile an. Dadurch erzeugen Sie den selben Zustand wie nach dem Einschalten des Rechners, jedoch bleibt ein eventuell vorhandenes Objektprogramm im Speicher erhalten. Das Pascal-System verabschiedet sich mit der Meldung:

COMMODORE BASIC V7.0 122365 BYTES FREE
  (C)1985 COMMODORE ELECTRONICS, LTD.
        (C)1977 MICROSOFT CORP.
          ALL RIGHTS RESERVED

SYSTEM SWITCHED OFF
READY.

Treten Fehler während der Ausführung des Objektprogrammes auf, so erscheint eine der in Anhang C aufgeführten Laufzeitfehlermeldungen. Neben der Adresse des Fehlers im übersetzten Code, wird auch eine Auflistung der Aufrufadressen (dynamic chain) ausgegeben:

Beispiel:

PROGRAM LAUFZEITFEHLER(INPUT,OUTPUT);


  FUNCTION KEHRWERT(X: INTEGER): REAL;
  BEGIN
    KEHRWERT:= 1 / X;
  END; (* KEHRWERT *)


  PROCEDURE P;
  BEGIN
    WRITELN(KEHRWERT(0));
  END; (* P *)


BEGIN
  P;
END.

Dieses Programm können Sie ohne Fehlermeldung übersetzen lassen. Der erzeugte Code liegt im Bereich von 7391 bis 7473:

ERRORS DETECTED: 0  
     P-CODE FROM  7391 TO 7473
  CONSTANTS FROM  8192 TO 8192 

Bei der Ausführung des Programmes werden Sie jedoch feststellen, daß der Prozeduraufruf P im Hauptprogramm eine Division durch Null in der Funktion KEHRWERT zur Folge hat. Daher erscheint folgende Meldung nach dem Programmstart mit RUN:

DIVISION BY ZERO
 ERROR AT 7437 IN KEHRWERT
CALLED AT 7453 IN P
CALLED AT 7469 IN LAUFZEITFEHLER

READY.

Natürlich läßt sich bei diesem kleinen Programm der Fehler innerhalb der Funktion KEHRWERT sofort lokalisieren, jedoch kann es notwendig sein, die exakte Fehlerposition zu finden. Deshalb können Sie den Compiler vom Pascal-Menü starten und die Fehleradresse 7437 eingeben:

PASCAL 2.0 (Rx.x)
-----------------

SELECT OPTION:
0 CHECK SYNTAX
1 GENERATE CODE
ELSE LOCATE ADDRESS

==>7437

Die Fehleradresse wird dann mit einem Pfeil und der Fehlernummer 0 vom Compiler im Quelltext markiert:

   KEHRWERT:= 1 / X;
           ^ ERROR 0 IN 4

Mit der eben beschriebenen Methode lassen sich alle beim Programm- abbruch genannten Adressen (also auch die Aufrufadressen der Prozeudren) lokalisieren.

Laufende Pascalprogramme können nur mit der Tastenkombination RUN-STOP und RESTORE abgebrochen werden. Auch in diesem Fall wird die Adresse des zuletzt ausgeführten Befehls und die dynamic-chain angezeigt.

BREAK
 ERROR AT 7468 IN TESTPROGRAMM

4.3.4 Speicherverteilung im Pascal-System

Möchten Sie reine Pascal-Programme mit dem Compiler entwickeln, so können Sie das folgende Kapitel überschlagen, da es Hinweise enthält, die nur für denjenigen gedacht sind, der Pascal-Programme mit Programmen in Maschinensprache koppeln möchte. Nur dann ist es nämlich wichtig, die Speicherverwaltung bei übersetzten Pascal-Programmen zu kennen.

Zunächst soll die Speicherverteilung während der Ausführung eines übersetzten Programmes beschrieben werden, ohne daß das Pascal-System vorhanden ist. Von der Diskette laden Sie eine Mischung aus BASIC-Programm, Maschinenprogramm, Pascalcode und compilierten Konstanten. Dieser Code muß ab der absoluten Adresse $1C01 in der Bank 0 geladen werden. Das Ende des Codes erfahren Sie bei der letzen Meldung des Compilers.

Beim Programmstart wird zunächst die Bibliothek »PAS.LIB« von der Diskette in Bank 1 ab der absoluten Adresse $0400 geladen. Dieses File enthält die gesamte Pascal-Laufzeitbibliothek. Anschließend werden alle Konstanten in Bank 1 (hinter PAS.LIB) kopiert. Den Anfang und das Ende der Konstanten in Bank 1 erfahren Sie ebenfalls in der letzten Meldung des Compilers.

Während der Ausführung des Pascalcodes werden zwei Speicherbereiche in Bank 1 verwaltet. Auf dem stack werden alle lokalen Variablen und Zwischenergebnisse gespeichert. Der stack beginnt direkt hinter den Konstanten und wächst von niedrigen zu hohen Speicheradressen. Dynamische Variablen (erzeugt mit der Standardprozedur NEW) werden auf dem heap verwaltet. Dieser wächst in Bank 1 vom oberen Speicherende abwärts. Bei der Kollision von heap und stack wird ein Speicherüberlauf gemeldet. Der Speicherbereich ab der Adresse $FF00 in Bank 0 und Bank 1 ist für das Betriebssystem reserviert. Damit ergibt sich die in Bild 115 gezeigte Speicherverteilung:

Bild 115: Speicherverteilung ohne Pascal-System

Bei Programmen, die Darstellungen im Grafikmodus verwenden, wird in Bank 0 Speicherplatz am Beginn des BASIC-Arbeitsspeichers benötigt. Solche Programe müssen deshalb im Programmkopf die Kennzeichnung GRAPHIC erhalten. Sofort beim Programmstart (nach der Kopie der Konstanten) wird dann das Pascalprogramm in BANK 0 um 8K nach oben geschoben. Jedoch ist der Pascalcode nicht relokatibel.

Ist bei der Ausführung des Objektcodes noch das Pascal-System geladen, so endet der verfügbare Arbeitsspeicher in Bank 1 bei der Adresse $9B00, da dort der Compiler beginnt. Andererseits muß in Bank 0 noch der Sourcetext und der Editor untergebracht werden. Der Sourcetext beginnt bei der absoluten Adresse $8000. Der Editor selbst beginnt bei der Adresse $DB00. Schließlich wird der Speicherbereich zwischen $1400 und $1600 in Bank 0 für das Pascal-System reserviert. Summa summarum ergibt sich die in Bild 116 gezeigte memory-map:

Bild 116: Speicherverteilung im Pascal-System

Es folgt eine Auflistung aller überhaupt vom Laufzeitsystem verwendeten (Zero-Page-) Variablen, dabei sind nur die Zeiger T, P, B, B1, F, MAXME0, MAXME1 und TOP innerhalb von SYS-Befehlen vor Veränderungen zu schützen.

Name Adresse Bedeutung
T 47/48 top of stack (Bank 1 aufwärts wachsend)
P 49/50 program counter (Bank 0)
B 59/60 base register (Bank 1)
B1 51/52 help pointer to stack (Bank 1)
F 55/56 file descriptor (Bank 1)
MAXME0 4626/4627 top of BASIC ram (Bank 0)
MAXME1 57/58 top of free ram (Bank 1)
TOP 53/54 top of heap (Bank 1 abwärts wachsend)
VAR 67/77 variable assignation
FAC 99..104 floating point accu
ARG 106..111 floating point accu (2)
SIGN 112 SGN(FAC * ARG)
FACLSB 113 LSB of FAC
TAB 256 scratch area
TABI 512 scratch area for input
FARCNF 2  
FARPCH 3  
FARPCL 4 für bankübergreifende Sprünge
FARST 5  
IODEV 21  
DIRECT 127  
M 4080216  
HIRES 215xxx  
MMUCR 65280..65284  

Alle Adressen sind dezimal angegeben. 2-Byte Werte sind in der Reihenfolge L/H gespeichert.

Um Speicherplatz für Unterprogramme in Maschinenprogramme zu reservieren, bietet sich das obere Speicherende in Bank 1 und Bank 0 an. Sie müssen dazu nur vor der ersten NEW-Operation die Zeiger MAXME0 bzw. MAXME1 modifizieren.

Jedoch kann der Pascalcode, die Konstanten und der Stack bei Bedarf auch an einer anderen Stelle gespeichert werden. Diese Modifikationen werden durch Parameter im Programmkopf gesteuert. Neben den Parametern INPUT, OUTPUT und GRAPHIC sind in Pascal 2.0 in der Parameterliste des Programmes ganze Zahlen zuläsig, die getrennt durch Semikola die Codeerzeugung beeinflussen.

Beispiel:

PROGRAM MODIFIKATION(INPUT,OUTPUT; 10000; 24576; 1000);

Die erste Adresse gibt an, ab welcher absoluten Adresse in Bank 0 der Code bei seiner Ausführung stehen soll. Der zweite Parameter gibt an, wohin das erste Byte der Konstanten in Bank 1 kopiert werden soll. Schließlich definiert der dritte Parameter, um welches Offset der Code in Bank 0 gegenüber der ersten Zahl verschoben gespeichert werden soll.

Im Beispiel wird der Compiler den erzeugten Code ab der Adresse 11000 (= 10000 + 1000 ) speichern. Die Konstanten beginnen in Bank 1 ab der Adresse $6000 (=24576). Jedoch ist der Code nur lauffähig, falls er vor der Ausführung wieder an die Adresse 10000 verschoben wird.

Nach der Übersetzung muß noch der Vorspann, in dem sich der Code zum Laden des Files »PAS.LIB« befindet, angepaßt werden, damit der Pascalcode im Speicher gefunden wird. Daher müssen Sie ab der Adresse $1CDF (dies ist der normale Codeanfang) mit dem ROM-Monitor folgende Bytes definieren:

$1CDF AKONST Anfang der Konstanten in Bank 0 (L/H)
$1CE1 EKONST Ende der Konstanten in Bank 0 (L/H)
$1CE3 ZKONST Anfang der Kopie der Konstanten in Bank 1 (L/H)
$1CE5 PCODE Anfang des Programmcodes in Bank 1 (L/H)

Diese 8 Bytes werden bereits vom Compiler mit dem Pascalcode erzeugt, so daß Sie im obigen Beispiel mit folgendem Transferbefehl (im Monitor) diese Bytes kopieren können:

T +11000,+11007,$1CDF

Damit erhalten Sie zur Laufzeit folgende Speicherverteilung, wobei Sie zwischen $1CE7 und +11000 in Bank 0 sowie $2000 und $6000 in Bank 1 Speicherplatz für eigene Maschinencoderoutinen besitzen.

Mit dieser Modifikation beginnt der stack direkt hinter der Kopie der Konstanten. Der Stackanfang läßt sich jedoch ebenfalls (innerhalb Bank 1) verschieben. Dazu muß in der durch PCODE indizierten Adresse die Basisadresse des Stack verändert werden. Diese doch recht seltene Modifikation wird in Abschnitt 3.4 in Form von BASIC-Befehlen durchgeführt.

Bild 117: Beispiel einer modifizierten Speicherverteilung

Inhaltsverzeichnis