Zeile 10 meldet SYNTAX ERROR, Zeile 20 nicht. Eigentlich müßten beide Zeilen völlig identische Wirkung haben, da die beiden Operanden um AND vertauschbar sein müssen.

Des Rätsels Lösung: Der Interpreter findet nach dem S den Befehl TAN (Tangens), aber dahinter keine Klammer. Und schon kennt er sich nicht mehr aus und bringt die Fehlermeldung. In Zeile 20 hat er keine Möglichkeit zu Fehlinterpretationen In Zeile 30 findet er nach S den Befehl TO (FOR..TO..NEXT). Ein Space nach ST in 10 und 30 behebt den Fehler.

Sollte man sich also mit einem hartnäckigen SYNTAX ERROR herumschlagen, kann eine derartige Mißdeutung die Ursache sein!

5.3 BASIC-Zeilenformat und Platzbedarf

Jede BASIC-Zeile beginnt mit einer Zeilennummer und kann, durch Doppelpunkt getrennt, mehrere Befehle aufnehmen.

Jedes BASIC-Befehlswort wird durch einen 1-Byte-Code komprimiert im Speicher gehalten. Jede andere Information innerhalb der Zeile braucht soviele Bytes, wie sie Zeichen umfaßt.

Jede BASIC-Zeile benötigt 5 Bytes für ihre Verwaltung. Im einzelnen sind das 2 Bytes für die Zeilennummer, 2 Bytes für einen Vorwärtszeiger auf die nächste BASIC-Zeile und der Code 0 als Abschluß der Zeile.

Durch die Beschränkung der Bildschirmeingabe kann eine BASIC-Zeile maximal ca. 80 Zeichen lang sein. Allerdings könnte der Interpreter BASIC-Zeilen bis zu einer internen (Interpretercode) Länge von 250 Bytes verarbeiten.

Es ist möglich, durch Verwendung der Befehlsabkürzungen mehr Information in die Zeile zu bringen, als die 80 Zeichen-Zeile normalerweise gestattet, aber dies sollte man nur in Ausnahmefällen nutzen, da LIST die betreffende Zeile ja nicht mit den Abkürzungen druckt, sondern durch Verwendung der vollen Befehlsworte die Zeile über mehr als 80 Zeilen auslistet. Zum Editieren müssen dann von Hand wieder alle Abkürzungen eingegeben werden, um die Zeile geändert wieder in der vollen Länge abspeichern zu können.

5.4 Speichereinteilung

Der freiprogrammierbare BASIC-Arbeitsbereich des Rechners (34 K) gliedert sich in folgende Teile:

Zero Page
-
Stack
-
Page 2,3
-
BASIC-Text (Programm)
-
Einfache Variable
-
Indizierte Variable (Felder)
-
Strings
-
Bildschirm

Die Zero Page ist ein 256 Bytes langer Bereich, auf den der Prozessor extrem schnell zugreifen kann. Alle besonders häufig benötigten Daten legt das Betriebssystem und der Interpreter dort ab.

Der Stack (Stapel) wird im nächsten Abschnitt mit seinen Konsequenzen für BASIC beschrieben.

Die folgenden 512 Bytes (Page 2,3) enthalten unter anderem die beiden Kassettenpuffer mit zweimal 191 Bytes Länge, den BASICEingabepuffer mit 80 Zeichen Länge, sowie den Tastaturpuffer mit 10 Zeichen Länge.

Ab dem Byte 1024 steht der Text des BASIC-Programms im komprimierten Interpreter-Code.

Sobald ein Programm (mit RUN) gestartet wird, wird automatisch der Anfang der Variablentabelle auf das Ende des BASIC Programms gesetzt. Das ist der Grund, warum andererseits nach einer Änderung im Programm die Variablen 'weg' sind.

Das Ende der Variablentabelle ist gleichzeitig der Anfang der Felder-Tabelle. Dies hat zur Folge, dass der gesamte Feldbereich nach hinten verschoben werden muß, wenn eine neue einfache Variable eingeführt wird.

Wichtig zu wissen ist, dass zwar jederzeit neue einfache und indizierte Variable eingeführt werden können, dass aber nicht einzelne Variable oder Felder gelöscht werden können!

Die Stringinhalte 'wachsen' von der oberen Speichergrenze (32K) her nach ,unten'.

Der Speicher wird also optimal den jeweiligen Gegebenheiten angepaßt. Trotzdem kann er natürlich irgendwann zu klein sein. Dies wird dann durch OUT OF MEMORY ERROR gemeldet. Bei folgenden Gelegenheiten kann diese Meldung auftreten:

Tritt sie bei der Programmeingabe auf, so ist das Programm alleine schon zu groß, könnte also nie laufen, da zu diesem Zeitpunkt noch keine Variable im Speicher steht. In diesem Fall kann nur 'Overlay' (LOAD) helfen.

Tritt sie nach dem Start des Programms auf, ist die häufigste Ursache eine Dimensionierung von Feldern (DIM), da hiermit auf einmal sehr viel Speicherplatz belegt werden kann. Man kann leicht nachprüfen, ob dies der Fall ist: Erstens muß in der gemeldeten Zeile ein DIM stehen und zweitens muß der Platzbedarf des Feldes (s. indizierte Variable) größer sein, als der noch freie Speicherplatz (FRE).

Scheidet DIM aus, kann es ein String sein, da Strings immerhin auch auf einmal 255 Bytes belegen können. In diesem Fall muß in der gemeldeten Zeile eine Stringzuweisung stehen.

Ist auch das nicht der Fall, könnte theoretisch eine neu eingeführte einfache Variable den Speicher gerade um 7 Bytes zu klein gefunden haben.

Wahrscheinlicher ist aber, dass der Stack 'übergelaufen' ist:

5.5 Stack (Stapel)

Der Stack ist ähnlich wie die Zero Page ein bevorzugter Speicherbereich des Prozessors. Der Stack eignet sich sehr gut zur Aufnahme von hierarchischen Strukturen, wie sie die Daten für Unterprogramme (GOSUB/RETURN), Schleifen (FOR NEXT) und Klammerebenen in Ausdrücken darstellen.

Deshalb legt der Interpreter die nötigen Verwaltungsinformationen für Unterprogramme, Schleifen und Ausdrücke im Stack ab. Dies hat den Vorteil, dass der Rücksprung aus Unterprogrammen (RETURN), der Rücksprung in Schleifen, sowie die Überprüfung des Endwertes und die Berechnung von Ausdrücken in sehr kurzer Zeit durchgeführt werden kann. Andererseits ist der Stack ein endlicher Speicherbereich, der relativ schnell 'überläuft'.

Wie schon erwähnt, kann auch dies der Grund für OUT OF MEMORY ERROR sein. Die folgenden Werte sollen Ihnen einen Anhaltspunkt geben, wieviel Ebenen jeweils möglich sind.

GOSUB 26
FOR NEXT 10
Klammerebenen 10

Diese Werte sind exklusiv, d.h. wenn Sie z.B. 26 GOSUB Ebenen haben, kann keine Schleife und kein Ausdruck mehr existieren, ohne dass OUT OF MEMORY gemeldet wird.

Sollten Sie OUT OF MEMORY erhalten, helfen Ihnen vielleicht folgende Überlegungen weiter: Eine Ausdrucksebene benötigt im Stack genausoviel Platz, wie eine FOR NEXT Schleife (18 Bytes), eine GOSUB Ebene dagegen nur 5 Bytes. Sie können also durch Verzicht auf eine Ausdrucksebene eine Schleife gewinnen oder 3 GOSUB Ebenen gegen eine Schleife eintauschen.

Beispiele für die Stackgrenzen:

200 A=2*(2*(2*(2*(2*(2*(2*(2*(2*(2*2)))))))))
301 GOSUB 302:RETURN
302 GOSUB 303:RETURN
.
.
.
325 GOSUB 326:RETURN
326 GOSUB 327:END
327 RETURN

401 FOR A = 0 TO 1
402 FOR B = 0 TO 1
.
.
.
409 FOR 1 = 0 TO 1
410 FOR J = 0 TO 1
420 PRINT A;B;C;D;E;F;G;H;l;J
430 NEXT J,1,H,G,F,E,D,C,B,A

Die Beispiele in 2009 300 ..., und 400 ... zeigen die jeweilsmaximal mögliche Schachtelungstiefe, nämlich log 26 und 10. Es sei nochmal betonte dass die drei Beispiele nicht kombiniert werden können, weil jedes für sich den Stack vollkommen in Anspruch nimmt.

Wenn Sie jeweils eine Ebene mehr anfügen, wird OUT OF MEMORY IN ... gemeldet.

Lösungsvorschläge

Am leichtesten kann die Schachtelungstiefe von Ausdrücken vermindert werden, da man sie nur in Teilausdrücke zu zerlegen braucht, deren Ergebnisse schrittweise zusammengefaßt werden (s. numerische Ausdrücke).

GOSUB-Ebenen kann man simulieren, indem das Unterprogramm statt mit GOSUB mit GOTO angesprungen wird. Anstatt des RETURN muß dann am Ende des Unterprogramms ein ON .. GOTO Verteiler dafür sorgen, dass das Unterprogramm wieder zum aufrufenden Programm zurückspringt. [Das aufrufende Programm muß dem Unterprogramm dann lediglich in einer zusätzlichen Variable mitteilen, wer es gerufen hat (s. ON GOTO).

FOR NEXT Schleifen sind sehr leicht durch IF THEN usw. zu ersetzen.

Natürlich sollte man zu solchen 'Krücken' erst greifen, wenn es wirklich nötig ist, weil sie die Programmstruktur verschlechtern und langsamer sind.

CCOM - CBM 4032 Benutzerhandbuch

5. Interpreter und Organisation

Das BASIC Programm im Arbeitsspeicher wird Zeichen für Zeichen vom Interpreter abgetastet und ausgeführt. Dabei muß der Interpreter im ersten Schritt jeden Befehl erst einmal analysieren. Erst nachdem dies geschehen ist, kann der Befehl ausgeführt werden.

Der Interpreter ist selbst ein Programm, allerdings in Maschinensprache geschrieben. Dieses Programm ist in ROMs (nichtlöschbare Speicherbausteine) eingespeichert und deshalb sofort beim Einschalten verfügbar.

Der Vorteil der Interpretersprache liegt darin, dass man relativ einfach im 'Dialog' mit dem Rechner Programme erstellen kann. Allerdings wird dies durch den Nachteil erkauft, dass Interpreterprogramme relativ langsam ablaufen.

5.1 Geschwindigkeit

Bei manchen Programmteilen wäre es wünschenswert, dass sie schneller laufen. Es ist nicht sinnvoll, exakte Laufzeiten von einzelnen Statements anzugeben, da sie oft von vielen Parametern abhängen. Trotzdem ist es oft hilfreich, wenigstens die Größenordnung von Befehlsausführungszeiten zu kennen: Zwischen

1 ms und 100 ms

können einfache BASIC Statements zur Ausführung brauchen. Sehr umfangreiche Ausdrücke können auch länger als 100 ms dauern.

Es können also sicher nicht mehr als 1000 BASIC Befehle pro Sekunde ablaufen. Als grobe Näherung ist der Wert 100 Befehle pro Sekunde ganz nützlich.

Soweit es sinnvoll ist, werden bei einzelnen Befehlen qualitative Hinweise zur Ausführungszeit gegeben.

Hier sollen einige generelle Hinweise gegeben werden, die sich nicht auf spezielle Befehle beziehen:

Mehrere Befehle pro Zeile

Commodore-BASIC bietet im Gegensatz zu vielen anderen BASIC-Dialekten die Möglichkeit, mehrere Anweisungen durch Doppelpunkt getrennt in eine Zeile zu schreiben. Diese Möglichkeit sollte aus zwei Gründen ausgenützt werden: Erstens dauert der Übergang zu einer neuen Zeile länger, als der Übergang zu einem neuen Statement und zweitens steigt die Zeit für Sprünge mit der Anzahl der Zeilen. Außerdem braucht eine neue Zeile 5 Bytes an Verwaltung, während der Trenn-Doppelpunkt zwischen zwei Befehlen nur 1 Byte benötigt. Pro weiterem Statement in einer Zeile spart man also vier Bytes ein.

Keine überflüssigen SPACEs

Wenn Zeit und Platz knapp sind, sollte nicht die Lesbarkeit des Listings durch Spaces erhöht werden, weil jedes Space 1 Byte benötigt und vom Interpreter qelesen werden muß.

Kurze Variablennamen

In zeitkritischen Schleifen sollten möglichst nur einbuchstabige Variablen verwendet werden. Das bedeutet, dass auch keine Integervariablen verwendet werden sollten, da das '%' auch gelesen werden muß. Außerdem muß erst das Integerformat in Gleitkomma umgewandelt werden, was zusätzlich Zeit kostet.

5.2 Spaces im BASIC Text

Prinzipiell brauchen im BASIC Text keine Spaces als Trennzeichen stehen. Es gibt allerdings einige Ausnahmefälle, wo durch Spaces eindeutige Verhältnisse geschaffen werden müssen:

Beispiel:

10 IFSTAND64THEN ... (IF ST AND 64 THEN)
20 1F64ANDSTTHEN ... (IF 64 AND ST THEN)
30 IFSTOR64THEN .... (IF ST OR 64 THEN)