Info
Sammeln
Dokumentation
Anleitungen
Schnittstellen
Prozessoren
Videochips
Soundchips
Computer
Videospiele


Sinclair ZX81 Basic
Sinclair ZX81 Basic
1. Einleitung

Basic ist eine sehr simple, dafür aber auch leicht erlernbare Programmiersprache. Im Gegensatz zu fast allen moderneren Sprachen ist Basic eine Interpretersprache. Das heißt, daß ein Programm, ein Programmteil oder auch nur ein einzelner Befehl jederzeit ausprobiert werden kann. Das Ergebnis kann sofort begutachtet werden.
So kann man Basic schon nach wenigen Minuten als Taschenrechner einsetzen, während andere Sprachen zuerst eine aufwendige Einarbeitung in Editor, Compiler und Entwicklungsumgebung voraussetzen.
Dadurch ist die Abarbeitungsgeschwindigkeit fertiger Basicprogramme aber auch nicht mit der von C- oder gar Assemblerprogrammen vergleichbar.
Sinclairs ZX81 zeigt, wie der wohl minimale Homecomputer aussieht. Mit nur 1 KB Hauptspeicher, monochromer Textdarstellung (bei der sogar der Prozessor noch mithelfen muß), ohne Tonausgabe und mit der denkbar primitivsten Tastatur ist irgendwie naheliegend, daß auch das Basic mit einer Minimalausstattung auskommen muß. Immerhin hat der Rechner nur ganze 8 KB ROM - kaum ein anderer Homecomputer kommt mit weniger als dem doppelten aus!
Auch wenn das Basic des ZX81 sogar rudimentäre Grafikbefehle kennt, darf das nicht darüber hinwegtäuschen, daß die Sprache an anderer Stelle nicht einmal das Niveau von Tiny-Basic erreicht.

1.1 Befehlsmodus

Der einfachste Einstieg in den Umgang mit Basic ist der Befehlsmodus. Er ist bei fast jedem Homecomputer direkt nach dem Einschalten verfügbar. Sie tippen einen Befehl ein, drücken am Ende die Eingabetaste und schon wird der Befehl ausgeführt.
In der Praxis wird der Befehlsmodus hauptsächlich für zwei Aufgaben genutzt: Erstens können Programme vom Befehlsmodus aus von einem Speichergerät geladen bzw. auf einem Speichergerät abgelegt werden, zweitens ist der Befehlsmodus ein sehr schöner Taschenrechner.

1.1.1 Laden und speichern von Programmen

Der ZX81 kennt nur ein Gerät zur Programmaufzeichnung - einen an die an der linken Gehäuseseite befindlichen Klinkenbuchsen angeschlossenen, gewöhnlichen Kassettenrekorder.

LOAD
LOAD "[<programmname>]"

LOAD "" lädt das erstbeste Programm von der Datasette. Wird ein Programmname angegeben, muß das von der Kassette eingespielte Programm genau diesen Namen haben. Um ein Programm erfolgreich zu laden, sollten Sie zuerst das Band an eine Stelle kurz vor dem Anfang des gewünschten Programms spulen, den LOAD-Befehl eintippen (noch nicht abschicken!), den Rekorder im Wiedergabebetrieb starten und dann sofort auf "NEW LINE" auf der Tastatur des ZX81 drücken. Während des Ladens erscheinen schwarzweiße Linienmuster auf dem Bildschirm.

SAVE
SAVE "<programmname>"

SAVE speichert das im Arbeitsspeicher befindliche Programm auf Kassette ab. Das bei LOAD erörterte Prozedere gilt in ähnlicher Form auch beim Speichern: Geben Sie zuerst den SAVE-Befehl ein (noch nicht abschicken), suchen Sie dann ein freies Plätzchen auf der Kassette und starten Sie die Aufnahme. Drücken Sie jetzt die Taste "NEW LINE" und die Speicherung beginnt.
SAVE kann auch von einem Programm aufgerufen werden. Dabei wird es so gespeichert, daß es nach dem erneuten Laden automatisch mit der auf den SAVE-Befehl folgenden Zeile gestartet wird.

1.1.2 Basic als Taschenrechner

Wenn der Computer etwas ausrechnen soll, brauchen Sie nur ein Fragezeichen, gefolgt von einem Leerzeichen und der Rechenaufgabe einzutippen und danach die Eingabetaste zu drücken. Das Ergebnis erscheint sofort auf dem Bildschirm.
Sie tippen ein:
? (23-7)*3
Der Computer antwortet mit: 48

Sie sehen, daß in Basic die normale mathematische Notation funktioniert. Ein paar Besonderheiten sollten Sie aber wissen:
- Als Multiplikationszeichen wird der Stern (*) verwendet. - Für Divisionen geben Sie den Schrägstrich (/) an. - Falls Sie keine Klammern angeben gilt "Punkt vor Strich".
Basic beherrscht die meisten mathematischen Funktionen, die auch auf einem besseren Taschenrechner zu finden sind. Dazu aber mehr im Kapitel "Arithmetik".

1.1.3 Befehlsübersicht des Direktmodus


RUN
RUN ["<Programmname>"|<Zeilennummer>]

RUN alleine führt das im Arbeitsspeicher befindliche Programm ab dem Programmanfang aus. Wird ein Programmname angegeben, sucht der Basicinterpreter dieses Programm auf der Datenkassette, lädt und startet es. RUN kann ein Programm aber auch ab einer bestimmten Stelle ausführen. Dazu geben Sie einfach die erste abzuarbeitende Zeilennummer an. (Was es mit den Zeilennummern auf sich hat, erfahren Sie im nächsten Kapitel.)

LIST
LIST [<Zeilennummer>]

Um das Programm im Arbeitsspeicher oder einen Teil davon zu betrachten, benötigen Sie den LIST-Befehl. Für sich alleine zeigt er das ganze Programm an. Es kann aber auch eine Zeilennummer angegeben werden, ab der die Auflistung beginnen soll.

CLEAR

CLEAR löscht alle Variablen.

1.2 Programmieren

Der Befehlsmodus ist recht nützlich für einfache Rechenaufgaben - mit Basic-Programmierung hat seine Verwendung aber noch nichts zu tun.
Ein Programm ist eine Abfolge von Befehlen, die durch den Basicinterpreter abgearbeitet werden. Die Befehle stehen dabei in sogenannten Befehlszeilen, wobei jede Zeile normalerweise nur einen Befehl enthält. Die Reihenfolge, in der die Befehlszeilen abgearbeitet werden, wird durch Zeilennummern am Zeilenanfang bestimmt. Das Programm startet bei der kleinsten Zeilennummer und endet bei der größten. Die Nummern müssen nicht fortlaufend sein, es empfiehlt sich sogar, ein Programm zunächst z.B. in Zehnerschritten zu numerieren, um später Zeilen einfügen zu können.
Wenn Sie im Befehlsmodus eine Zeile mit einer Zeilennummer am Anfang eingeben, wird diese nicht sofort ausgeführt sondern gemäß ihrer Zeilennummer an der richtigen Stelle in das im Speicher befindliche Programm eingefügt. Ist der Speicher leer, wird das Programm mit der Eingabe der ersten Programmzeile angelegt.
Existiert bereits eine Zeile mit der Nummer der neu eingegebenen Zeile, so wird die alte kommentarlos durch die neue Zeile ersetzt. Die Eingabe einer Zeilennummer solo löscht eine bereits vorhandene Zeile mit dieser Nummer.
Für die Beispiele in diesem und den folgenden Kapiteln sollen drei einfache Basicbefehle schon an dieser Stelle vorgestellt werden. Sie werden in einem späteren Kapitel noch detailliert besprochen. Den ersten haben Sie schon kennengelernt: Das Fragezeichen im Direktmodus ist eigentlich die Abkürzung eines Basicbefehls, der ausgeschrieben "PRINT" heißt und für Bildschirmausgaben zuständig ist.
Eingaben des Benutzers kann ein Basicprogramm mit dem Befehl "INPUT" anfordern und der Befehl "LET" wird verwendet, um einer Variablen einen Wert zuzuweisen.
Am besten verstehen Sie diese drei Befehle anhand Ihres ersten Basicprogramms:
100 INPUT "GEBEN SIE EINE ZAHL EIN", A
110 LET B=A*A
120 PRINT "DAS QUADRAT VON "; A; " IST "; B

Die erste Zeile (Nummer 100) veranlasst den Computer, den Text "GEBEN SIE EINE ZAHL EIN" gefolgt von einem Fragezeichen und einem Eingabecursor auszugeben. Nun wartet der Computer auf die Eingabe einer Zahl. Diese wird dann in der Variablen "A" gespeichert.
In der zweiten Zeile (Nummer 110) wird einer neuen Variable "B" der Wert "A*A" zugewiesen. "B" enthält nun also den Wert von "A" im quadrat.
Die dritte Zeile schließlich gibt den Text "DAS QUADRAT VON ", den Wert der Variable "A", den Text " IST " und den Wert der Variable "B" nacheinander aus. Das Semikolon als Trennzeichen bewirkt, daß die Texte und Variableninhalte nahtlos aneinandergehängt werden.
Wenn Sie das Programm mit "RUN" ausführen, passiert auf dem Bildschirm zunächst folgendes:
GEBEN SIE EINE ZAHL EIN? _

Nun wartet der Computer auf Ihre Eingabe. Geben Sie nun z.B. eine 5 ein und drücken Sie dann die Eingabetaste. Folgendes steht nun auf dem Bildschirm:
GEBEN SIE EINE ZAHL EIN? 5
DAS QUADRAT VON 5 IST 25


1.3 Editieren eines Programms

Der ZX81 verfügt nur über einen Zeileneditor, mit dem es sich aber ganz gut leben läßt. Im Gegensatz zu anderen Homecomputern kann ein Programm nicht einfach "heruntergetippt" werden. Befehlsworte können nicht Buchstabe für Buchstabe eingegeben werden, sondern müssen direkt als Tastaturkommando aufgerufen werden. Bei einem Befehl, der ja naturgemäß am Anfang einer Zeile steht, macht der ZX81 dies automatisch. Erkennen können Sie das an der Schreibmarke, die aus einem inversen "K" besteht. Wenn Sie nun eine Taste drücken, erscheint nicht das Zeichen, das auf der Taste steht, sondern der Befehl, der oberhalb der Taste aufgedruckt ist. Etwas komplizierter stellt sich die Eingabe von Funktionsaufrufen dar. Hier müssen Sie zunächst mit SHIFT + NEW LINE in den Funktionseingabemodus wechseln, sichtbar an dem inversen "F" als Schreibmarke. Nun erscheint bei einem Tastendruck die unter der Taste aufgedruckte Funktionsbezeichnung auf dem Bildschirm. Auf einigen Tasten ist rechts noch ein Grafikzeichen aufgedruckt. Diese können Sie z.B. in PRINT-Befehlen verwenden. Ein Grafikzeichen geben Sie ein, indem Sie mit SHIFT + 9 in den Grafikzeichenmodus umschalten (Schreibmarke wird zum inversen G) und dann die gewünschte Taste drücken.
Ein weiterer Unterschied zu gewöhnlichen Basiceditoren besteht darin, daß alle neu eingegebenen Zeilen zunächst in der letzten Bildschirmzeile erscheinen und erst nach dem Drücken der "NEW LINE"-Taste nach oben wandern. Dabei wird jede neue Zeile an der richtigen Stelle in das Programm eingefügt. Eine Markierung (inverses Größerzeichen) zwischen Zeilennummer und Zeilentext zeigt im oberen Bildschirmbereich an, welche Zeile zuletzt bearbeitet wurde. Die Markierung kann mit den Pfeiltasten hoch / runter (SHIFT+6 bzw. SHIFT+7) durch das Programmlisting bewegt werden. Ein Druck auf die EDIT-Taste (SHIFT+1) holt die momentan markierte Programmzeile in die unterste Bildschirmzeile, wo Sie sie dann beliebig verändern und mit NEW LINE wieder abspeichern können.
2. Programmstruktur

Im letzten Kapitel wurde ausgeführt, daß ein Programm immer in der Reihenfolge aufsteigender Zeilennummern ausgeführt wird. Das trifft aber nur für sehr einfache Programme zu, die z.B. beim Start ein paar Informationen abfragen und daraus irgendetwas berechnen.
Die meisten Programme erfordern jedoch ein deutlich komplexeres Verhalten. Oft muß ein Programm aufgrund vorgegebener Bedingungen unterschiedlich reagieren, d.h. verschiedene Programmteile abarbeiten. Dies wird als "bedingte Verzweigung" bezeichnet.
Eine andere Form der Strukturierung sind Schleifen, also die mehrfache Abarbeitung eines Programmteils bis zur Erfüllung einer Bedingung.
Eine letzte Variante bei den Strukturbefehlen ermöglicht die Nutzung von Unterprogrammen. Diese können dann jederzeit und von mehreren Stellen des Hauptprogramms aus aufgerufen werden.
Doch eins nach dem anderen:

2.1 Verzweigungen

Im folgenden wird immer wieder von Bedingungen die Rede sein. Sie sollten daher wissen, wie eine Bedingung aussieht. Basic verfügt für Bedingungen über ein großes Repertoir an Vergleichsoperatoren:
> größer < kleiner = gleich >= größer oder gleich <= kleiner oder gleich <> ungleich
Diese funktionieren nicht nur mit Zahlen sondern auch mit Zeichenketten, wobei hier "größer" gleichbedeutend ist mit "steht weiter hinten im Lexikon".
Mehrere Vergleiche können mit den logischen Operatoren "AND", "OR" und "NOT" verknüpft werden. Die Hierarchie der Vergleiche wird im Bedarfsfall mit Klammern festgelegt.
Am besten verstehen Sie die Möglichkeiten auch hier mit Hilfe einiger Beispiele:
A>=5
...ist wahr, wenn der Wert der Variable A größer oder gleich 5 ist.
"Klaus"<"Peter"
...ist wahr, weil "Klaus" lexikalisch vor "Peter" kommt
( A>=5 AND A<=10 ) OR B=1
...ist wahr, wenn A zwischen 5 und 10 liegt oder B gleich 1 ist.
GOTO / GO TO
GOTO <Zeilennummer>

Die einfachste Verzweigungsanweisung ist der GOTO-Befehl. Wenn die Programmabarbeitung auf einen GOTO-Befehl stößt, wird das Programm in der angegebenen Zeile fortgesetzt, ohne wenn und aber.
Bei gutem Programmierstil sollte der Einsatz des GOTO-Befehls auf den Ausgleich der Defizite bei anderen Strukturbefehlen in einfachen Basicdialekten beschränkt bleiben (siehe die Beispiele bei IF / THEN und ON GOTO). Wildes Herumspringen im Programm macht es sehr unübersichtlich - dem Basicinterpreter macht das nichts aus, aber der Autor des Programms wird sich nach ein paar Wochen in seinem eigenen Werk nicht mehr zurechtfinden.
GOTO kann alternativ auch GO TO geschrieben werden.

IF / THEN
IF <Bedingung> THEN <Zeilennummer>

Die bedingte Verzweigung IF / THEN führt einen Programmteil abhängig von einer Bedingung aus. Trifft die Bedingung zu, wird das Programm ab der hinter THEN angegebenen Zeilennummer fortgesetzt, andernfalls läuft das Programm in der nächsten Zeile (also ganz normal) weiter.
Das folgende Programm berechnet die Quadratwurzel der eingegeben Zahl. Ist die Zahl kleiner als Null, erscheint eine Warnung und das Programm ermöglicht einen neuen Versuch, eine Zahl einzugeben:
100 INPUT "GEBEN SIE EINE POSITIVE ZAHL EIN", A
110 IF A>=0 THEN 140
120 PRINT "DIE ZAHL "; A; "IST NEGATIV!"
130 GOTO 100
140 PRINT "DIE WURZEL VON "; A; " IST "; SQR( A )

Den im Tiny-Basic vorhandenen Befehl ON GOTO kennt der ZX81 leider nicht.

2.2 Schleifen


FOR / TO / NEXT
FOR <Variable>=<Ausdruck> TO <Ausdruck> [STEP <Ausdruck>]
...
NEXT <Variable>

Bei einer Schleife werden ein oder mehrere Befehle mehrfach ausgeführt. Diese Befehlsgruppe wird eingerahmt durch einen Schleifenbefehl am Anfang und einen am Ende. Bei der FOR/NEXT-Schleife handelt es sich um eine Zählschleife, d.h. bereits der Schleifenbefehl am Anfang legt die Zahl der Schleifendurchläufe fest. Dazu wird einer Variablen das Ergebnis eines Ausdrucks zugewiesen. Diese Variable wird dann mit jedem Durchlauf der Schleife um den hinter "STEP" angegeben Wert erhöht. Fehlt die Angabe von "STEP", wird um eins erhöht.
Die Schleife endet mit dem Erreichen des Wertes, der hinter "TO" angegeben ist.
Zwei Beispiele:
1. Der Computer soll die 7er-Reihe aufsagen:
100 FOR I=7 to 70 STEP 7
110 PRINT I
120 NEXT I

In der ersten Zeile wird der Variablen "I" zunächst der Wert 7 zugewiesen. Dieser wird in der zweiten Zeile dann auf dem Bildschirm ausgegeben. Die dritte Zeile veranlasst, daß "I" um die Schrittweite 7 erhöht wird und prüft, ob der Endwert 70 bereits erreicht ist. Da dem nicht so ist, wird die Schleife erneut durchlaufen und so der neue Wert von "I", also 14, ausgegeben. Das wird nun so fortgesetzt, bis "I" nach der Erhöhung um 7 den Wert 77 annimmt. Der Endwert 70 ist nun überschritten und die Schleife endet.
2. Der Computer soll das gesamte kleine Einmaleins anzeigen:
100 FOR A=1 TO 10
110 FOR B=1 TO 10
120 PRINT A*B;
130 NEXT B
140 PRINT
150 NEXT A

Jetzt wird klar, warum beim NEXT-Befehl nochmal der Variablenname steht: Er macht klar, welcher NEXT-Befehl zu welchem FOR-Befehl gehört.
Das Programm beginnt in Zeile 100 mit der Zuweisung des Werts 1 an die Variable "A". In Zeile 110 erhält "B" ebenfalls den Wert 1. Zeile 120 gibt nun den Wert von 1*1 auf dem Bildschirm aus. Das Semikolon am Zeilenende bewirkt, daß die nächste Ausgabe mit PRINT in der gleichen Zeile angehängt wird. In der folgenden Zeile (130) wird nun "B" um eins erhöht, mit dem Endwert 10 verglichen und das Programm in Zeile 120 fortgesetzt. Nun erscheint das Ergebnis von 1*2 auf dem Bildschirm. Dies wiederholt sich nun solange, bis die Schleife mit einem Wert von 10 in der Variable "B" durchlaufen wurde. Nun ist der Endwert erreicht und das Programm geht mit Zeile 140 weiter. Diese macht keine Ausgabe, sondern veranlaßt, daß der nächste PRINT-Befehl seine Ausgabe in einer neuen Bildschirmzeile beginnt. Nun wird in Zeile 150 der Wert von "A" um eins erhöht, mit dem Endwert für "A" verglichen und das Programm in Zeile 110 fortgesetzt. Dort erhält "B" wieder den Wert 1 und die innere Schleife (Zeilen 110 - 130) läuft wieder von 1 bis 10 und gibt dabei die Zeierreihe auf dem Bildschirm aus. Das Spiel wiederholt sich solange, bis auch "A" den Endwert erreicht hat und das geamte kleine Einmaleins auf dem Bildschirm steht.

2.3 Unterprogramme


GOSUB / RETURN
GOSUB <Zeilennummer>
RETURN

Der Befehl "GOSUB" springt zunächst genauso wie "GOTO" einfach zu der angegebenen Zeilennummer und setzt das Programm dort fort. Der Basicinterpreter merkt sich aber, welche Zeile auf die mit dem GOSUB-Befehl folgt. Falls das Programm nun auf einen "RETURN"-Befehl stößt, wird die Programmausführung in der gemerkten Zeile fortgesetzt.
Als Beispiel soll ein Unterprogramm dienen, das einen Text nacheinander zeichenweise auf den Bildschirm schreibt. Machen Sie sich nichts daraus, wenn Sie die folgenden Zeilen noch nicht ganz verstehen - es genügt für's erste zu wissen, daß sie den Inhalt der Stringvariablen "A$" zeichenweise auf den Bildschirm schreiben. Eine Stringvariable ist eine Variable, die Text enthalten kann.
1000 FOR I=1 TO LEN(A$)
1010 PRINT MID$(A$,I,1);
1020 NEXT I
1030 RETURN

Dieses Unterprogramm für sich auszuführen macht keinen Sinn: Erstens hat A$ noch keinen Inhalt, es wird also auch nichts auf den Bildschirm geschrieben. Zweitens würde der Basicinterpreter in Zeile 1030 auf den RETURN-Befehl stoßen, ohne daß er zuvor bei einem GOSUB vorbeigekommen wäre. Das Programm würde daher mit einer Fehlermeldung abbrechen.
Wir benötigen daher noch ein Hauptprogramm, das unser Unterprogramm nutzt. Es kann es nicht nur einmal, sondern beliebig oft und von verschiedenen Stellen aus aufrufen:
100 A$="ACHTUNG! ACHTUNG! HIER SPRICHT DEIN COMPUTER!"
110 GOSUB 1000
120 PRINT
130 A$="IN MEINEM SPEICHER HAT SICH EIN BIT VERKLEMMT."
140 GOSUB 1000
150 PRINT
160 A$="BITTE DREH MICH UM UND KLOPF MIR AUF DEN RUECKEN!"
170 GOSUB 1000
180 PRINT
190 END

Zeile 190 enthält einen weiteren neuen Befehl: END. Er führt dazu, daß das Programm an dieser Stelle beendet wird. Es gilt als ordentlicher Programmierstil, alle Unterprogramme am Ende des Programmes (d.h. bei den hohen Zeilennummern) unterzubringen. Das davorstehende Hauptprogramm endet dann mit dem END-Befehl, andernfalls wird zuletzt das erste Unterprogramm nach dem Hauptprogramm ausgeführt und der Basicinterpreter scheitert am RETURN-Befehl, der dieses Unterprogramm abschließt.
Den im Tiny-Basic vorhandenen Befehl ON GOSUB kennt der ZX81 leider nicht.

2.4 Programmsteuerung


STOP

STOP ist normalerweise ein Befehl, den Sie zu Testzwecken in einem Programm einbauen können. Das Programm wird bei der Ausführung des STOP-Befehls anhalten, Sie können z.B. Variableninhalte ansachauen und das Programm mit CONT fortsetzen lassen.
Der ZX81 kennt aber noch eine weitere Finesse: Während ein INPUT-Befehl auf Ihre EIngabe wartet, können Sie "STOP" (SHIFT+A) über die Tastatur eingeben und das Programm wird beendet.
3. Arithmetik und Variablen

3.1 Variablen

In den letzten Kapiteln war schon mehrfach von Variablen die Rede. Nun wollen wir sie etwas genauer betrachten.
Sie kennen Variablen aus der Mathematik als Platzhalter für Zahlen. Man kann mit Variablen ausdrücken, daß eine Formel gilt - unabhängig welche Zahlen man für die darin enthaltenen Variablen einsetzt.
In allen gängigen Programmiersprachen erfüllen Variablen die gleiche Funktion: Sie können stellvertretend für Zahlen angegeben werden. Man kann einer Variablen einen Wert zuweisen. Überall, wo diese Variable dann im Programm vorkommt, wird sie dann so behandelt als stünde da direkt der Wert dieser Variablen.

LET
[LET] <Variablenname>=<Ausdruck>

Mit dem LET-Befehl gibt man einer Variablen einen Wert. Hatte diese Variable zuvor bereits einen anderen Wert, so wird dieser überschrieben. Der LET-Befehl kann auch weggelassen werden.
A=5
weist also der Variablen A den Wert 5 zu.
Das folgende Beispiel berechnet mit Hilfe der Formel des Pythagoras die Länge der langen Seite (Hypotenuse) eines rechtwinkligen Dreiecks:
100 INPUT "LAENGE DER 1. KATHETE:", A
110 INPUT "LAENGE DER 2. KATHETE:", B
120 C = SQR( A*A + B*B )
130 PRINT "LAENGE DER HYPOTENUSE: "; C


3.2 Rechnen mit Zahlen

Ein Computer wäre kein Computer, könnte er nicht rechnen. Bisher haben Sie in den Programmbeispielen fast nur die Grundrechenarten sehen können. Basic kann aber noch mehr:

Operatoren

Als Operatoren bezeichnet man die normalen mathematischen Rechenzeichen. Neben den bereits vorgestellten "+" (Addition), "-" (Subtraktion), "*" (Multiplikation) und "/" (Division) kennt Basic noch Klammern zur Festlegung der Auswertungsreihenfolge eines Ausdrucks und das "^" als Exponentzeichen.
2*(4+1) ergibt 10
3^2 ergibt 9
5/2 ergibt 2.5

Am Ergebnis des letzten Beispiels sehen Sie, daß Basic auch mit nichtganzen Zahlen umgehen kann. Entgegen der in Deutschland gebräuchlichen Notation wird in Basic jedoch statt dem Komma ein Punkt verwendet.

INT()

INT() rundet auf die nächste ganze Zahl ab.
INT( 5.32 ) ergibt 5
INT( -2.3 ) ergibt -3

ABS()

ABS() bildet den Betrag.
ABS( 23 ) ergibt 23
ABS( -4 ) ergibt 4

SIN(), COS(), TAN()

SIN() errechnet den Sinus. Das Argument wird im Bogenmaß erwartet. Das gleiche gilt für den Cosinus COS() und den Tangens TAN().
SIN( 3.1415 / 2 ) ergibt 1

SGN()

SGN() liefert 1 bei positivem Argument, -1 bei negativem Argument und 0, falls das Argument gleich Null ist.
SGN( 0.3 ) ergibt 1
SGN( -1423 ) ergibt -1

SQR()

SQR() errechnet die Quadratwurzel.
SQR( 16 ) ergibt 4

LN(), EXP()

LN() bestimmt den natürlichen Logarithmus, EXP() die Exponentialfunktion (d.h. die Eulersche Zahl hoch dem Argument).
LN( 1 ) ergibt 0
EXP( 1 ) ergibt 2.7172...

Die Funktionsdefinition mit dem Befehl "DEF FN" kennt der ZX81 leider nicht.

ATN(), ASN(), ACS()

Berechnet den Arkustankens, Arkussinus bzw. Arkuscosinus. Das Ergebnis ist im Bogenmaß

RND

RND liefert Pseudozufallszahlen, die größer oder gleich Null und kleiner als eins sind. "Pseudo" deshalb, weil die Zahlen nicht ganz zufällig sind: Eine Zufallszahl wird immer aus der vorhergehenden berechnet und - was noch schwerer wiegt: Nach jedem Neustart des Basicinterpreters produziert RND wieder die exakt gleichen Zufallszahlen.
Bei den meisten Basics benötigt die RND-Funktion ein in Klammern eingeschlossenes Argument. Beim ZX81 wird RND wie eine Variable verwendet.

RAND
RAND <startwert>

Mit RAND können Sie einen neuen Startwert für die Zufallszahlenberechnung mit RND festlegen. Der gleiche Startwert führt immer zur gleichen Folge von Zufallszahlen. So etwas wie "echte" Zufälligkeit erreichen Sie mit "RAND 0". Dabei wird der Startwert aus der Laufzeit des Computers ermittelt.

PI

PI ist als Konstante fest definiert. Sie können daher PI wie eine Variable in Ausdrücken verwenden. Einen anderen Wert können Sie allerdings nicht dafür definieren.
100 INPUT "RADIUS : ", R
110 PRINT "UMFANG : U="; R*2*PI
120 PRINT "FLAECHE: A="; R^2*PI


3.3 Strings

Strings sind Zeichenketten, d.h. eine Abfolge von Buchstaben, Zahlen oder Sonderzeichen. Es gibt spezielle Variablen, die anstelle von Zahlen Strings als Wert annehmen können. Diese werden als Stringvariablen bezeichnet und durch ein Dollarzeichen am Ende des Variablennamens kenntlich gemacht.
Mit Strings kan man natürlich nicht im herkömmlichen Sinne rechnen. Zumindest die Addition ist jedoch definiert. Sie hängt die "Summanden" einfach aneinander.
A$="DIES IST "
B$="EIN BEISPIEL"
C$=A$+B$
PRINT C$

Der PRINT-Befehl schreibt den Wert der Stringvariablen C$ auf den Bildschirm. Es erscheint
DIES IST EIN BEISPIEL

Verschiedene Funktionen ermöglichen sehr interessante Anwendungen von Strings:

LEN()

LEN() ermittelt die Länge eines Strings
LEN( "HALLO" ) ergibt 5


Stringabschnitte
<variablenname>([<von>][TO[<bis>]])

Die meisten Basic-Varianten kennen die Funktionen LEFT$, RIGHT$ und MID$ um Teile von Strings anzusprechen. Nicht so der ZX81. Hier kann an einen String in Klammern eine Bereichsangabe angehängt werden. Fehlt dabei die Angabe die Startposition (z.B. A$(TO 4)), so wird 1 als Startposition angenommen. Fehlt die Endposition (z.B. A$(3 TO)), so gilt das letzte Zeichen des Strings als Endposition. Wird nur eine Position ohne "TO" angegeben, so wird nur das Zeichen an der entsprechenden Stelle angesprochen.
Ein ähnliches Verfahren wird bei Atari-Basic eingesetzt.

CODE()

Jeder Buchstabe, jede Ziffer und jedes Sonderzeichen wird vom Computer intern als Zahl gespeichert. Welches Zeichen dabei welcher Zahl entspricht, ist in einem Code festgelegt. Etwa die Hälfte dieses Codes ist standardisiert und auf jedem Computer gleich. Dieser Code heißt "ASCII" (american standard code for information interchange).
Mit der CODE()-Funktion können Sie die Zahl ermitteln, die dem ersten Zeichen des angegebenen Strings zugeordnet ist. Diese Funktion kennt nahezu jeder andere Basicinterpreter unter dem Namen ASC().
CODE( "A" ) ergibt 65


CHR$()

Die umgekehrte Funktion zu ASC() stellt CHR$() dar. Die angegebene Zahl wird in das zugehörige Zeichen nach dem ASCII-Code umgewandelt.
CHR$( 65 ) ergibt 65

So können Sie sehr einfach ein Programm schreiben, das eine ASCII-Codetabelle auf den Bildschirm schreibt:
100 FOR I=0 TO 255 STEP 4
110 FOR J=0 TO 3
120 PRINT I+J; ":"; CHR$( I+J ); " ";
130 NEXT J
140 PRINT
150 NEXT I

VAL, STR$

VAL wandelt einen Zahlenstring in eine Zahl, STR$ tut genau das Gegenteil. Stößt VAL bei der Umwandlung des Strings auf ein Zeichen, das nicht zu einem Zahlenstring paßt, bricht die Wandlung ab.
Auch hier wird die Wirkungsweise wohl am ehesten durch einige Beispiele klar:
VAL( "12" ) ergibt die Zahl 12
VAL( "35.6" ) ergibt die Zahl 35,6
VAL( "23.07.1998" ) ergibt die Zahl 23,07 (eine Zahl kann nur ein Komma
enthalten) VAL( "7A12" ) ergibt die Zahl 7 (der Rest läßt sich nicht als Zahl lesen)

STR$( 14.5 ) ergibt den String "14.5"
STR$( 64 ) ergibt den String "64"


3.4 Felder

Oft ist es notwendig, viele gleichartige Informationen in Variablen abzulegen. Der einfachste Weg, dies zu tun ist die Verwendung von Feldvariablen. Einem Variablennamen kann dabei eine vorher festzulegende Anzahl verschiedener Werte zugewiesen werden. Dem Variablennamen wird dabei in eckigen Klammern ein Index mitgegeben, der die verschiedenen möglichen Werte mit Nummern versieht.

DIM
DIM <Variablenname>[<Anzahl Feldelemente>]

Wie gesagt, die Anzahl möglicher verschiedener Werte in einer Feldvariable muß zuvor festgelegt werden. Dazu dient der DIM-Befehl. Er muß im Programm ausgeführt werden, bevor die zugehörige Feldvariable erstmals benutzt wird.
100 DIM U[12]
110 FOR I=1 TO 12
120 PRINT "UMSATZ IM "; I; ". MONAT DES JAHRES:";
130 INPUT U[I]
140 NEXT I
150 FOR I=1 TO 12
160 PRINT I,
170 FOR J=1 TO U[I]
180 PRINT "#";
190 NEXT J
200 PRINT
210 NEXT I

Das Beispielprogramm definiert in Zeile 100 eine Feldvariable mit 12 Elementen. In den Zeilen 110 bis 140 werden diese dann vom Anwender des Programms mit Werten gefüllt. Der Rest des Programms gibt die eingegebenen Werte dann als Balkendiagramm wieder aus.

3.5 Programminterne Daten

Oftmals werden in einem Programm Daten benötigt, die fest hinterlegt sein sollen, d.h. nicht jedes mal von Neuem abgefragt werden sollen. Tiny-Basic bietet dafür einen einzigartigen Mechanismus: Beliebige Daten können, durch Komma getrennt, in sogenannten DATA-Zeilen abgelegt werden. Der Zugriff auf DATA-Zeilen erfolgt durch den READ-Befehl.
Sollen Daten mehrfach gelesen oder selektiv auf bestimmte Datenbereiche zugegriffen werden, kann per RESTORE-Befehl festgelegt werden, ab welcher DATA-Zeilennummer folgende READ-Befehle ihre Daten lesen sollen.
Dieser Mechanismus fehlt dem Basic des ZX81. Programminterne Daten lassen sich hier am besten erzeugen, indem Sie im Direktmodus an Variablen zugewiesen werden. Das Speichern des Programms speichert auch die Variablen mit ab. Nach dem Einladen dürfen Sie das Programm nur nicht mit RUN starten, sondern müssen mit GOTO in die erste Zeile springen, da andernfalls der Variablenspeicher gelöscht wird.
4. Ein- / Ausgabe

4.1 Textausgabe auf dem Bildschirm


PRINT
PRINT [<Ausdruck>[;|,[<Ausdruck>]][...]]

Der PRINT-Befehl ermöglicht die Ausgabe beliebiger Informationen auf den Bildschirm Als <Ausdruck> können Sie entweder Strings, Stringvariablen oder numerische Ausdrücke angeben, wobei letztere vor der Ausgabe ausgerechnet werden. Werden zwei Ausdrücke durch Semikolon getrennt, hängt sie der Printbefehl direkt aneinander. Ein Komma als Trennzeichen lässt eine Lücke. Komma oder Semikolon können auch am Ende des Printbefehls stehen, sie wirken sich darauf aus, wie die Ausgabe des nächsten Printbefehls angefügt wird.
Ein PRINT-Befehl alleine bewirkt einen Zeilenvorschub, d.h. der darauf folgende PRINT-Befehl beginnt mit der Ausgabe eine Zeile tiefer.
Es gibt noch einige weitere Möglichkeiten, die den PRINT-Befehl noch universeller machen:
Die Funktion TAB ermöglicht eine tabularische Ausgabe, indem sie die nächste horizontale Ausgabeposition auf die als Argument angegebene Spaltennummer setzt. Natürlich kann das nur funktionieren, wenn die nächste Ausgabeposition vor dem Aufruf von TAB noch links der angegebenen Spalte gewesen wäre. Andernfalls erfolgt die Ausgabe in der nächsten Zeile.
100 PRINT "NAME";TAB 8;"PUNKTE"
110 PRINT "KLAUS";TAB 8;"15"
120 PRINT "SANDRA";TAB 8;"18"
130 PRINT "PAUL";TAB 8;"9"
140 PRINT "MARGARETHE";TAB 8;"10"

Das Beispielprogramm produziert folgende Ausgabe:
NAME PUNKTE
KLAUS 15
SANDRA 18
PAUL 9
MARGARETHE
10

Die letzte Zeile zeigt, daß durch den langen Namen die Punktzahl bei Margarethe nicht mehr auf die Tabulatorposition 8 geschrieben werden kann.
Eine weitere Ergänzung ermöglicht die exakte Positionierung einer PRINT-Ausgabe auf dem Bildschirm: AT <y-pos>,<x-pos>.
PRINT AT 2,10; "TEST"
schreibt das Wort "TEST" ab der 10. Spalte in die zweite Bildschirmzeile.

CLS

Der Befehl CLS löscht den gesamten Bildschirm.

SCROLL

Der Befehl SCROLL schiebt den gesamten Bildschirminhalt um eine Zeile nach oben. Die erste Zeile verschwindet dabei und die letzte Bildschirmzeile ist leer.

4.2 Eingaben über die Tastatur


INPUT
INPUT <Variablenname>

Der INPUT-Befehl erwartet vom Benutzer des Programms die Eingabe eines Wertes für die angegebene Variable.

INKEY$

INKEY$ prüft, ob über die Tastatur ein Zeichen eingegeben wurde. Wenn ja, liefert INKEY$ dieses Zeichen, andernfalls einen Leerstring. Im Gegensatz zum INPUT-Befehl wartet INKEY$ nicht auf eine Tastatureingabe.

4.3 Grafik

Wenn der ZX81 mit ein paar Verrenkungen und einer Speichererweiterung auch echte hochauflösende Grafik hinbekommt - das Basic unterstützt dergleichen leider nicht. Allerdings enthält der Zeichensatz sogenannte Blockgrafikzeichen, mit denen eine einfache Grafik mit immerhin doppelter Buchstabenauflösung, d.h. 64 x 48 Bildpunkten realisierbar ist. Diese Pseudografik kann mit der normalen Textdarstellung gemischt werden. Zur Ansteuerung gibt es zwei Basicbefehle:

PLOT
PLOT <x-pos>,<y-pos>

PLOT zeichnet einen schwarzen Punkt an der angegebenen Position. Die Koordinaten entsprechen dabei den mathematischen Konventionen, der Ursprung liegt also in der linken unteren Ecke.

UNPLOT
UNPLOT <x-pos>,<y-pos>

UNPLOT zeichnet einen weißen Punkt an der angegebenen Position. Sie können damit also mit PLOT gezeichnete Punkte wieder löschen.

4.4 Ansteuerung von Peripheriegeräten


4.4.1 Dateioperationen

Dateioperationen basieren darauf, daß zunächst ein Kanal auf einem bestimmten Gerät geöffnet wird, aus dem dann gelesen oder in den geschrieben werden kann. Ist die Operation abgeschlossen, wird der Kanal wieder geschlossen.
Diesen Mechanismus kennt das Basic des ZX81 nicht. Der einzige Weg, Variableninhalte dauerhaft zu speichern, besteht in der Speicherung eines Programms - die Variablen werden dabei mitgesichert.

4.4.2 Drucker

Zu einem minimalen Computer gehört auch ein ebensolcher Drucker. Sinclair ist dabei ein besonderes Meisterstück gelungen. An dem metallisierten Papierstreifen rast mit mehr als einem Kilometer pro Stunde ein Draht vorbei, der eine elektrisierbare Spitze trägt. Wo immer diese unter Strom gesetzt wird, entsteht auf dem Papier ein geschwärzter Punkt.
Für die Ansteuerung dieses Druckers kennt das Basic des ZX81 drei Befehle:

LPRINT

LPRINT funktioniert grundsätzlich genauso, wie der normale PRINT-Befehl. Die Ausgabe landet aber nicht auf dem Bildschirm sondern auf dem Drucker.

LLIST

LLIST ist eine Variante des LIST-Befehls, die das Programmlisting auf dem Drucker ausgibt.

COPY

COPY erzeugt auf dem Drucker ein exaktes Abbild des aktuellen Bildschirminhalts.
5. Fortgeschrittene Programmierung


5.1 Langsame und schnelle Abarbeitung, Pausen

Beim ZX81 muß der Prozessor beim Bildschirmaufbau mithelfen, was ihn ganz schön auf Trab hält und ihm nur wenig Zeit läßt, sich um seine übrigen Aufgaben zu kümmern. Deswegen kann ein Basicprogramm glatt vier mal so schnell abalufen, wenn der Prozessor von der Aufgabe der Bilderzeugung entbunden wird. Leider verschwindet dabei aber auch die Bildschirmanzeige. Trotzdem kann dieser Verzicht bei manchen Programmen das kleinere Übel sein:

SLOW, FAST

Sie können es sich vermutlich schon denken: FAST schaltet die Bildschirmanzeige ab und führt dazu, daß das Programm etwa vier mal so schnell läuft. Mit SLOW beenden Sie den Spuk wieder.

PAUSE
PAUSE <dauer>

PAUSE hält das Programm für die angegebene Dauer an. Die Einheit der Dauer ist eine fünfzigstel Sekunde. Die können die Warterei durch Druck auf eine beliebige Taste beenden. Die Leertaste bricht dabei das Programm ganz ab, jede andere Taste läßt es weiterlaufen.

5.2 Manipulation von Speicherstellen

Die meisten Basicdialekte ermöglichen die Manipulation beliebiger Speicherstellen des Arbeitsspeichers. So auch das Basic des ZX81. Während das Auslesen des Speicherinhalts noch recht ungefährlich ist, müssen Sie bei der Veränderung schon sehr genau wissen, was Sie tun.

POKE
POKE <adresse>,<wert>

POKE schreibt an der angegebenen Adresse den Wert (1 Byte) in den Arbeitsspeicher. Die Adresse muß im Bereich von 0 bis 65535 liegen.

PEEK
PEEK( <adresse> )

Die Funktion PEEK liefert den Inhalt der angegebenen Speicherstelle.

USR
USR( <startadresse> )

Die USR-Funktion ruft ein Maschinenprogramm ab der angegebenen Adresse im Hauptspeicher auf. Endet das Maschinenprogramm, so liefert USR den Inhalt des Registerpaares bc an das Basicprogramm zurück.