Commodore-Basic erweitert
Mit dem hier vorgestellten Maschinenprogramm wird der Basic-Befehlssatz des VC 20 oder des C 64 um sechs Befehle erweitert.
Die 6 Befehle lauten, in die Basic-Schreibweise übersetzt, GOTO N, GOSUB N, RESTORE N, READ D,A, READ N,D,A, und POP. Einen kleinen Nachteil muß man dabei allerdings in Kauf nehmen, denn diese Routinen kann man nur dem SYS-Befehl ansprechen. Es ist also nicht möglich, eine der Routinen direkt mit einem Basic-Befehlswort aufzurufen.
Der Zugriff auf diese Befehle kann insbesondere dann von großem Nutzen sein, wenn man Programme von anderen Computern umschreiben will, die diese Befehle benutzen.
Will man einen der neuen Befehle in einem Basic-Programm benutzen, muß man nur das Basic-Wort in der oben aufgeführten Liste durch ein »SYS (Adresse)« ersetzen. Die Parameter hinter dem Befehl werden genauso hinter den SYS-Befehl geschrieben, als ob sie hinter dem Basic-Befehl stehen würden.
Bei den nun folgenden Erläuterungen wird davon ausgegangen, daß sich das Maschinenprogramm im Kassettenpuffer ab Adresse 828 befindet. Wurde eine andere Anfangsadresse gewählt, ändern sich auch die Adressen der einzelnen Routinen.
Der Befehl GOTO N sieht in der Form, wie er im Programm verwendet werden muß, so aus: SYS(828)N; also doch noch recht einfach. Dieser Befehl bewirkt, daß man direkt zu einer beliebigen Zeile springen kann, deren Zeilenummer »N« vorher berechnet wurde. Nun zur Syntax. Bei diesem, wie auch bei allen folgenden Befehlen ist darauf zu achten, daß die Startadresse der Routine nach dem SYS-Befehl, (hier 828) in Klammern steht, um Sie von der darauf folgenden Parameterliste zu trennen und so als Adresse kenntlich zu machen. »N« repräsentiert hier, wie auch bei den weiter folgenden Befehlen, eine beliebige gültige numerische Variable, eine Zahl oder einen numerischen Ausdruck. Für »N« ist also beispielsweise auch der Ausdruck »INT(RND( 1) * 20) * 10 +100« erlaubt. Der Ausdruck muß nur einen Ganzzahlenwert zum Ergebnis haben. Noch zu bemerken ist, daß zwischen der geschlossenen Klammer der Adresse und der ersten Variablen oder dem Ausdruck kein Komma stehen darf. Das Komma wirkt wie bei PRINT oder READ wie ein Trennzeichen. Da dieser Befehl aber nur eine Variable oder einen Ausdruck enthalten darf, würde das zu einem »SYNTAX ERROR« führen. Dies gilt auch bei allen folgenden Befehlen. Ist die berechnete Zeilennummer nicht im Programm enthalten, erfolg die Fehlermeldung »UNDEF’D STATEMENT ERROR«.
Für den Befehl GOSUB N gilt das gleiche, was auch zu GOTO N gesagt wurde, unter Berücksichtigung der Tatsache, daß es sich hier um einen Unterprogramm-Aufruf handelt Mit diesem Befehl kann man also zu einer vorher berechneten Unterprogramm-Adresse springen (SYS(834) N).
RESTORE N ermöglicht es, den DATA-Zeiger auf eine bestimmte Zeile zu setzen. SYS(866)100 beispielsweise setzt den DATA-Zeiger auf das erste Datum der Zeile 100. Mit einem anschließenden READ-Befehl kann man dann gezielt auf diesen Datensatz zugreifen. Ist die angegebene Zeilennummer im Programm nicht vorhanden, erfolgt ein »UNDEF’D STATEMENT ERROR«.
READ D, A (SYS(890) d, a) liest direkt den D-ten DATA-Wert in die Variable A. Anstelle von »A« kann sowohl eine numerische als auch eine Stringvariable stehen. »SYS(890) 5, A$« entspricht beispielsweise der Basic-Befehlsfolge »FOR I = 1 TO 5 : READ A$ : NEXT«. Auf etwas ist noch zu achten: Will man numerische Daten mit einer numerischen Variable lesen, darf keiner der vorhergehenden DATA-Werte ein String sein. Dies ist programmtechnisch bedingt und liegt daran, daß in Wirklichkeit die entsprechende Anzahl von READ-Befehlen durchgeführt wird. Ein direktes Lesen nur des gesuchten Datums würde das Maschinen-Programm dreimal so lang machen. Sollte es doch einmal vorkommen, daß man versucht, in eine numerische Variable einen String einzulesen, wird ein »SYNTAX ERROR« mit Angabe der entsprechenden DATA-Zeile ausgegeben. Am besten benutzt man immer Stringvariable zum Lesen.
Dann wäre da noch der Befehl »READ N,D,A« (entspricht SYS(927)N,D,A). Dieser Befehl ist eine Mischung des RESTORE- und des READ-Befehls.
SYS(927)N,D,A liest aus der Zeile N das D-te Datum dieser Zeile in die Variable »A«. Ist D größer als die Anzahl der Daten in dieser Zeile, wird in der nächsten DATA-Zeile weitergelesen.
Nun noch zu »POP« (SYS(937)). Springt man aus einem Unterprogramm anstatt mit »RETURN« mit einem direkten Sprungbefehl in die nächsthöhere Ebene (zum Beispiel ins Hauptprogramm) zurück, dann kann mit SYS(937) die letzte gespeicherte Rücksprungadresse im Stack, die dann nicht mehr gebraucht wird, gelöscht werden. Damit wird verhindert, daß der Stack überläuft, da er maximal 23 Rücksprungadressen speichern kann. Außerdem wird ein korrekter Programmablauf sichergestellt, wenn man »hart« aus einem Unterprogramm herausspringt, beispielsweise, um in eine Fehlerbehandlungsroutine zu gehen.
Tips für die Eingabe
Als erstes sollte man nur den Basic-Lader (Listing 1 oder 2, je nach Computer) ab Zeile 10000 eintippen und dann, ohne ihn zu starten, sicherheitshalber erst mal abspeichern. Dann gibt man noch eine Testzeile ein, und zwar: »10 GOSUB 10000:PRINT"Prüfsumme=";AS:END« und startet das Ganze mit »RUN«. Ergibt sich für die Prüfsumme ein anderer Wert als 18 413 für den VC 20 oder 17 901 für den C64, dann hat man sich irgendwo vertippt und die Datazeilen sind mit dem abgedruckten Listing noch einmal zu vergleichen. Eine genaue Kontrolle sollte man sowieso vornehmen, da sich durch Zufall eine richtige Prüfsumme ergeben kann, obwohl vielleicht zwei Werte falsch sind, die sich aber gegeneinander aufheben.
Sind alle Datazeilen fehlerfrei, löscht man Zeile 10 und speichert das Programm noch einmal ab, damit man den Basic-Lader an jedes gewünschte Programm anhängen kann.
Ist dies geschehen, kann man das Umrechnungsprogramm (Listing 3) eingeben. Es dient dazu, das Maschinenprogramm aus dem Kassettenpuffer an eine andere Stelle im Speicher zu verschieben. Der Kassettenpuffer hat ja den Nachteil, daß das Maschinenprogramm bei jeder Kassettenoperation zerstört wird. Außerdem können auch andere Befehlserweiterungen diesen Bereich benutzen, um Werte zwischenzuspeichern. Dadurch würde dann das Maschinenprogramm auch zerstört. Werden in einem Programm, das den Basic-Lader enthält, noch weitere DATA-Zeilen verwendet, so ist sicherzustellen, daß deren Zeilennummern größer sind als die höchste Zeilennummer des Basic-Laders, da sonst falsche Werte eingelesen würden.
Und noch ein Tip. Um die Adressen der Befehle nicht ändern zu müssen, wenn man das Maschinenprogramm in einen anderen Speicherbereich verlegt, verwendet man am besten Variablen, denen man am Anfang des Programms die Adresse zuweist. Dies könnte zum Beispiel so aussehen: »SM% = 828«.Für die einzelnen Befehle würde dann folgendes gelten:
GOTO N = SYS(SM%)
GOSUB N = SYS(SM% + 6)
RESTORE N = SYS(SM% + 38)
READ D,A = SYS(SM% + 62)
READ N,D,A = SYS(SM% + 99)
POP = SYS(SM% + 109)
Da alle diese Routinen weitgehend in das Betriebssystem des Computers eingebunden sind, werden bei Fehlern in der Ausführung die entsprechenden Systemfehlermeldungen ausgegeben.
(Wolfgang Thauer / ev)