Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
elektronik:u883:mpbasic [2021/08/02 13:37] – [7.3.2. Anweisungen] volkerp | elektronik:u883:mpbasic [2024/02/02 13:47] (aktuell) – volkerp | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
====== MPBASIC ====== | ====== MPBASIC ====== | ||
- | REIHE AUTOMATISIERUNGSTECHNIK Band 216 | + | REIHE AUTOMATISIERUNGSTECHNIK Band 216\\ |
- | + | Programmieren mit BASIC \\ | |
- | Programmieren mit BASIC | + | |
Siegmar Müller | Siegmar Müller | ||
- | 1. Auflage | + | 1. Auflage\\ |
© VEB Verlag Technik, Berlin, 1985 | © VEB Verlag Technik, Berlin, 1985 | ||
- | S. 60 ff. | + | **7. Tiny MPBASIC** |
- | + | ||
- | **7. Tiny MPBASIC** | + | |
===== 7.1. Tiny BASIC ===== | ===== 7.1. Tiny BASIC ===== | ||
Zeile 27: | Zeile 24: | ||
Damit ergeben sich für Tiny BASIC andere Anwendungsbereiche als für ein „großes" | Damit ergeben sich für Tiny BASIC andere Anwendungsbereiche als für ein „großes" | ||
- | Ein Echtzeitproblem besteht dann, wenn der Rechner auf ein externes Ereignis innerhalb einer vorgegebenen Zeit in einer diesem Ereignis entsprechenden Art und Weise reagieren | + | Ein Echtzeitproblem besteht dann, wenn der Rechner auf ein externes Ereignis innerhalb einer vorgegebenen Zeit in einer diesem Ereignis entsprechenden Art und Weise reagieren |
- | Ein generelles Problem bei der Anwendung höherer Programmiersprachen in Echtzeitproblemen besteht darin, | + | Ein generelles Problem bei der Anwendung höherer Programmiersprachen in Echtzeitproblemen besteht darin, |
10 FOR I=1 TO 1000 | 10 FOR I=1 TO 1000 | ||
Zeile 35: | Zeile 32: | ||
1000 NEXT I | 1000 NEXT I | ||
- | Mißt man hier x Sekunden, dann dauert die Abarbeitung des Programmstücks etwas weniger als x Millisekunden. (Weniger, weil FOR und NEXT noch hinzu kommen) | + | Misst man hier x Sekunden, dann dauert die Abarbeitung des Programmstücks etwas weniger als x Millisekunden. (Weniger, weil FOR und NEXT noch hinzu kommen) |
- | In der Praxis sind jedoch meist nur wenige Programmstellen zeitkritisch, | + | In der Praxis sind jedoch meist nur wenige Programmstellen zeitkritisch, |
===== 7.2. Konzept von Tiny MPBASIC ===== | ===== 7.2. Konzept von Tiny MPBASIC ===== | ||
- | Wie bei BASIC gibt es auch bei Tiny BASIC eine kaum überschaubare Vielzahl von Versionen. Tiny MPBASIC (winziges Mikroprozessor-BASIC) wurde ursprünglich für den Einchipmikrorechner U883 geschrieben, | + | Wie bei BASIC gibt es auch bei Tiny BASIC eine kaum überschaubare Vielzahl von Versionen. Tiny MPBASIC (winziges Mikroprozessor-BASIC) wurde ursprünglich für den Einchipmikrorechner U883 geschrieben, |
- | Der Interpreter gestattet die Einbindung von Programmen in Maschinensprache. Wir sprechen hierbei von Prozeduren. Eine Prozedur in Tiny MPBASIC ist ein in Maschinensprache geschriebenes Programm, das Daten vom Interpreter übernimmt, verarbeitet, | + | |
+ | Der Interpreter gestattet die Einbindung von Programmen in Maschinensprache. Wir sprechen hierbei von Prozeduren. Eine **Prozedur** in Tiny MPBASIC ist ein in Maschinensprache geschriebenes Programm, das Daten vom Interpreter übernimmt, verarbeitet, | ||
Tiny MPBASIC gestattet darüber hinaus die Verarbeitung von Traps (Fallen). Das sind Programmunterbrechungen, | Tiny MPBASIC gestattet darüber hinaus die Verarbeitung von Traps (Fallen). Das sind Programmunterbrechungen, | ||
+ | |||
Ein weiteres Problem bei der Schaffung eines möglichst geräteunabhängigen Interpreters sind die Eingabe- und die Ausgabeschnittstellen für INPUT bzw. PRINT. Um hier alle Möglichkeiten offen zu lassen, ruft PRINT ein Unterprogramm PUTCHR auf, das ein Zeichen ausgibt und vom Anwender des U883 erstellt wird. Wenn PRINT eine Zeile ausdruckt, dann wird PUTCHR so oft aufgerufen, wie Zeichen in dieser Zeile sind. Zum Einlesen von Zahlen ruft INPUT ein, ebenfalls vom Anwender geschriebenes, | Ein weiteres Problem bei der Schaffung eines möglichst geräteunabhängigen Interpreters sind die Eingabe- und die Ausgabeschnittstellen für INPUT bzw. PRINT. Um hier alle Möglichkeiten offen zu lassen, ruft PRINT ein Unterprogramm PUTCHR auf, das ein Zeichen ausgibt und vom Anwender des U883 erstellt wird. Wenn PRINT eine Zeile ausdruckt, dann wird PUTCHR so oft aufgerufen, wie Zeichen in dieser Zeile sind. Zum Einlesen von Zahlen ruft INPUT ein, ebenfalls vom Anwender geschriebenes, | ||
Zeile 50: | Zeile 50: | ||
==== 7.3.1. Ausdrücke ==== | ==== 7.3.1. Ausdrücke ==== | ||
- | Wir unterscheiden in Tiny MPBASIC arithmetische und logische Ausdrücke. Letztere haben immer die Gestalt | + | Wir unterscheiden in Tiny MPBASIC arithmetische und **logische Ausdrücke**. Letztere haben immer die Gestalt |
aausdruck vop aausdruck , | aausdruck vop aausdruck , | ||
wobei aausdruck ein arithmetischer Ausdruck und vop einer der Vergleichsoperatoren | wobei aausdruck ein arithmetischer Ausdruck und vop einer der Vergleichsoperatoren | ||
>, <,>=, <=, = und < > | >, <,>=, <=, = und < > | ||
- | ist. Das Ergebnis eines logischen Ausdrucks ist eine logische Größe (wahr oder falsch) und kein Zahlenwert. Hier besteht ein grundsätzlicher Unterschied zu anderen BASIC- Interpretern | + | ist. Das Ergebnis eines logischen Ausdrucks ist eine logische Größe (wahr oder falsch) und kein Zahlenwert. Hier besteht ein grundsätzlicher Unterschied zu anderen BASIC- Interpretern, |
- | In arithmetischen Ausdrücken werden ganzzahlige Konstanten, Variablen und Funktionen verknüpft. Da es Gleitkommagrößen ohnehin nicht gibt, entfällt die Kennzeichnung mit %. Dieses Zeichen hat in Tiny MPBASIC eine andere Bedeutung. Vor einer Konstanten kennzeichnet es die hexadezimale Darstellung. Der zulässige Bereich liegt zwischen %0000 und %FFFF bei hexadezimaler und zwischen -32767 und 32767 bei dezimaler Schreibweise. (Die Zahl -32768 kann intern verarbeitet, | + | |
+ | In **arithmetischen Ausdrücken** werden ganzzahlige Konstanten, Variablen und Funktionen verknüpft. Da es Gleitkommagrößen ohnehin nicht gibt, entfällt die Kennzeichnung mit %. Dieses Zeichen hat in Tiny MPBASIC eine andere Bedeutung. Vor einer Konstanten kennzeichnet es die hexadezimale Darstellung. Der zulässige Bereich liegt zwischen %0000 und %FFFF bei hexadezimaler und zwischen -32767 und 32767 bei dezimaler Schreibweise. (Die Zahl -32768 kann intern verarbeitet, | ||
+ | |||
+ | Es gibt die arithmetischen Operatoren +, -, *, / und $MOD.\\ | ||
$MOD, modulo, liefert den Rest, den eine ganze Zahl bei der Division durch eine andere ganze Zahl gibt. Es gilt | $MOD, modulo, liefert den Rest, den eine ganze Zahl bei der Division durch eine andere ganze Zahl gibt. Es gilt | ||
| A $MOD B | = | A - (A/B*B) | . | | A $MOD B | = | A - (A/B*B) | . | ||
Bei der Division wird der gebrochene Teil weggelassen. Das Dollarzeichen vor MOD hat nichts mit einem String zu tun; Strings sind nicht implementiert. Es kennzeichnet vielmehr $MOD als einen Operator. Das trifft auch auf die bitweisen logischen Operatoren | Bei der Division wird der gebrochene Teil weggelassen. Das Dollarzeichen vor MOD hat nichts mit einem String zu tun; Strings sind nicht implementiert. Es kennzeichnet vielmehr $MOD als einen Operator. Das trifft auch auf die bitweisen logischen Operatoren | ||
$AND, $OR und $XOR | $AND, $OR und $XOR | ||
- | zu. Diese arbeiten anders als die im Abschn. 2.4.2. beschriebenen | + | zu. Diese logischen |
A $AND 1 | A $AND 1 | ||
- | erhält man den Zustand vom Bit 0 in A, indem mit der UND-Verknüpfung die restlichen Bits zurückgesetzt werden. Mit $OR können Bits auf Eins gesetzt werden. | + | erhält man den Zustand vom Bit 0 in A, indem mit der UND-Verknüpfung die restlichen Bits zurückgesetzt werden. Mit $OR können Bits auf Eins gesetzt werden. |
$XOR eignet sich u. a. zum bitweisen Vergleich von Daten. Der Ausdruck | $XOR eignet sich u. a. zum bitweisen Vergleich von Daten. Der Ausdruck | ||
A $XOR %70 $AND %F0 | A $XOR %70 $AND %F0 | ||
- | liefert z. B. genau dann den Wert Null, wenn in A die Bits 4, 5 und 6 Eins sind und Bit 7 Null ist. Alle bitweisen logischen und arithmetischen Operatoren haben dieselbe Priorität. Sie dürfen gemeinsam in arithmetischen Ausdrücken auftreten. Damit werden arithmetische Ausdrücke streng von links nach rechts abgearbeitet. Wird eine andere Reihenfolge der Berechnung gewünscht, so ist das mit Klammern zu regeln. Weiterhin stehen die in Tafel 8 aufgeführten allgemeinen, | + | liefert z. B. genau dann den Wert Null, wenn in A die Bits 4, 5 und 6 Eins sind und Bit 7 Null ist. Alle bitweisen logischen und arithmetischen Operatoren haben dieselbe Priorität. Sie dürfen gemeinsam in arithmetischen Ausdrücken auftreten. Damit werden |
+ | |||
+ | Die Funktionsparameter werden grundsätzlich in eckige Klammern geschrieben. | ||
+ | |||
+ | Beim Rotieren nach links werden alle 16 Bits um eine Stelle nach links geschoben, und das höchstwertige Bit wird zum niederwertigsten Bit. Rotiert man z. B. die Zahl -32767, die intern die binäre Darstellung 1000 0000 0000 0001 hat, nach links, so ergibt das 0000 0000 0000 0011 (binär) bzw. 3 in dezimaler Schreibweise. Das Rotieren nach rechts funktioniert prinzipiell genauso, nur eben in die andere Richtung. RR ist somit die inverse Funktion zu RL. Programmiert man RR[RL[x]], so ergibt das immer x. Man braucht diese Funktion z. B., wenn Eingabeports multiplex abgefragt werden sollen. | ||
Tafel 8, Funktionen in Tiny MPBASIC | Tafel 8, Funktionen in Tiny MPBASIC | ||
Zeile 73: | Zeile 80: | ||
INPUT Zahl von der Konsole holen | INPUT Zahl von der Konsole holen | ||
RL[x] x um ein Bit nach links rotieren | RL[x] x um ein Bit nach links rotieren | ||
- | RR[x) x um ein Bit nach rechts rotieren | + | RR[x] x um ein Bit nach rechts rotieren |
Tafel 9. Maschinenorientierte Funktionen im U8S3 | Tafel 9. Maschinenorientierte Funktionen im U8S3 | ||
Zeile 79: | Zeile 86: | ||
GETRR[r] Inhalt des Registerpaares r, r+1 lesen | GETRR[r] Inhalt des Registerpaares r, r+1 lesen | ||
GETEB[a] Inhalt des auf der Adresse a abgespeicherten Bytes im Datenspeicher lesen | GETEB[a] Inhalt des auf der Adresse a abgespeicherten Bytes im Datenspeicher lesen | ||
- | GETEW(a) Inhalt der auf den Adressen a, a+1 abgespeicherten Bytes im Daten-Speicher lesen | + | GETEW[a] Inhalt der auf den Adressen a, a+1 abgespeicherten Bytes im Daten-Speicher lesen |
Darüber hinaus gibt es für den U883 einige Funktionen, mit denen man auf Register bzw. auf den Datenspeicher zugreifen kann (Tafel 9). Dadurch hat der Anwender sofort, d. h. ohne erst eigene Funktionen schreiben zu müssen, Zugriff auf fast alle Schaltkreisfunktionen. BASIC-Programme, | Darüber hinaus gibt es für den U883 einige Funktionen, mit denen man auf Register bzw. auf den Datenspeicher zugreifen kann (Tafel 9). Dadurch hat der Anwender sofort, d. h. ohne erst eigene Funktionen schreiben zu müssen, Zugriff auf fast alle Schaltkreisfunktionen. BASIC-Programme, | ||
- | GETB(a) Byte aus dem Speicher von Adresse a lesen | + | GETB[a] Byte aus dem Speicher von Adresse a lesen |
GETW[a] Bytes aus dem Speicher von den Adressen a und a+1 lesen | GETW[a] Bytes aus dem Speicher von den Adressen a und a+1 lesen | ||
IN[p] Port p lesen | IN[p] Port p lesen | ||
Zeile 94: | Zeile 101: | ||
Tafel 10. Anweisungen in Tiny MPBASIC | Tafel 10. Anweisungen in Tiny MPBASIC | ||
- | LET variable = aausdruck GOTO aausdruck | + | LET variable = aausdruck |
+ | | ||
IF lausdruck THEN anweisung | IF lausdruck THEN anweisung | ||
IF lausdruck THEN anweisungsblock | IF lausdruck THEN anweisungsblock | ||
Zeile 103: | Zeile 111: | ||
INPUT {" | INPUT {" | ||
PRINT {" | PRINT {" | ||
- | PRINTHEX {" | + | PRINTHEX {" |
STOP | STOP | ||
END | END | ||
Zeile 113: | Zeile 121: | ||
WAIT aausdruck | WAIT aausdruck | ||
- | Bei der Anweisung **GOTO** ist ein Ausdruck zur Angabe der Zeilennummer zugelassen. Gleiches trifft auf **GOSUB** zu. Die Anweisungen ON...GOTO und ON...GOSUB sind dadurch leicht zu umgehen. Ein Anweisungsblock besteht aus beliebig vielen, durch Semikolon getrennten Anweisungen, | + | Bei der Anweisung **GOTO** ist ein Ausdruck zur Angabe der Zeilennummer zugelassen. Gleiches trifft auf **GOSUB** zu. Die Anweisungen ON...GOTO und ON...GOSUB sind dadurch leicht zu umgehen. Ein Anweisungsblock besteht aus beliebig vielen, durch Semikolon getrennten Anweisungen, |
10 LET T = INPUT+2732 | 10 LET T = INPUT+2732 | ||
programmieren. | programmieren. | ||
- | Die Anweisung **PRINTHEX** unterscheidet sich von PRINT nur dadurch, | + | Die Anweisung **PRINTHEX** unterscheidet sich von PRINT nur dadurch, |
Mit der Anweisung **PROC** werden Prozeduren vom BASIC-Interpreter aufgerufen. Die Variablenliste sind in eckige Klammern gesetzte und durch Komma getrennte Variablen. Bei der Parameterliste handelt es sich um in eckige Klammern gesetzte und durch Komma getrennte Ausdrücke. Zum Beispiel | Mit der Anweisung **PROC** werden Prozeduren vom BASIC-Interpreter aufgerufen. Die Variablenliste sind in eckige Klammern gesetzte und durch Komma getrennte Variablen. Bei der Parameterliste handelt es sich um in eckige Klammern gesetzte und durch Komma getrennte Ausdrücke. Zum Beispiel | ||
- | 10 PROC [A, 3, X] = MPROG [3*A, X, 2] . | + | 10 PROC [A, B, X] = MPROG [3*A, X, 2] |
- | Es gibt bereits implementierte Prozeduren (Tafel 11). Der Sinn der Prozeduren besteht allerdings vor allem darin, | + | Es gibt bereits implementierte Prozeduren (Tafel 11). Der Sinn der Prozeduren besteht allerdings vor allem darin, |
Tafel 11. Prozeduren im U883 | Tafel 11. Prozeduren im U883 | ||
PTC[z] Zeichen z an die Konsole ausgeben (benutzt PUTCHR) | PTC[z] Zeichen z an die Konsole ausgeben (benutzt PUTCHR) | ||
- | SETR(r, | + | SETR[r, |
SETRR[r, | SETRR[r, | ||
SETEB[a, | SETEB[a, | ||
SETEW[a, | SETEW[a, | ||
- | Die SET-Prozeduren in Tafel 11 sind, wie die GET-Funktionen, | + | Die SET-Prozeduren in Tafel 11 sind, wie die GET-Funktionen, |
- | Eine weitere, speziell für Steuerungen gedachte Anweisung, ist **TRAP** (Falle). Nachdem TRAP abgearbeitet wurde, testet der Interpreter vor der Abarbeitung jeder neuen Programmzeile die gesetzte Trapbedingung (lausdruck). Sobald diese erfüllt ist, erfolgt automatisch ein GOSUB zu der durch aausdruck gegebenen Zeile. Die Bedingung wird vorher gelöscht. Danach wird die Traproutine abgearbeitet, | + | Eine weitere, speziell für Steuerungen gedachte Anweisung, ist **TRAP** (Falle). Nachdem TRAP abgearbeitet wurde, testet der Interpreter vor der Abarbeitung jeder neuen Programmzeile die gesetzte Trapbedingung (lausdruck). Sobald diese erfüllt ist, erfolgt automatisch ein GOSUB zu der durch aausdruck gegebenen Zeile. Die Bedingung wird vorher gelöscht. Danach wird die Traproutine abgearbeitet, |
10 TRAP AD1/201 $OR (AD2/ | 10 TRAP AD1/201 $OR (AD2/ | ||
programmieren. Die Division AD1/201 ergibt so lange Null, wie AD1<=200 ist, weil die Stellen nach dem Komma abgeschnitten werden. Genauso bleibt AD2/181 Null, wenn AD2<=180 ist. Überschreitet einer der beiden, AD1 oder AD2, den vorgeschriebenen Maximalwert, | programmieren. Die Division AD1/201 ergibt so lange Null, wie AD1<=200 ist, weil die Stellen nach dem Komma abgeschnitten werden. Genauso bleibt AD2/181 Null, wenn AD2<=180 ist. Überschreitet einer der beiden, AD1 oder AD2, den vorgeschriebenen Maximalwert, | ||
Zeile 139: | Zeile 147: | ||
Will man die Trapbedingung nur löschen, ohne dabei eine neue zu setzen, so gibt man die Anweisung **CLRTRP** (clear trap, lösche Trap). | Will man die Trapbedingung nur löschen, ohne dabei eine neue zu setzen, so gibt man die Anweisung **CLRTRP** (clear trap, lösche Trap). | ||
- | Schließlich sei noch **WAIT** erläutert. Diese Anweisung berechnet zunächst den Ausdruck und ruft danach eine Software-Warteschleife auf, die so oft durchlaufen wird, wie das Ergebnis des Ausdrucks angibt. Ein Durchlauf dauert genau eine Millisekunde. (Beim U883 wird dabei ein 8-MHz-Quarz vorausgesetzt.) Bei der Anwendung von WAIT beachte man, daß die Berechnung des Ausdrucks und die vor- und nachher abzuarbeitenden Anweisungen ebenfalls Zeit brauchen. Weiterhin hat man bei WAIT mit großen Zeiten zu beachten, | + | Schließlich sei noch **WAIT** erläutert. Diese Anweisung berechnet zunächst den Ausdruck und ruft danach eine Software-Warteschleife auf, die so oft durchlaufen wird, wie das Ergebnis des Ausdrucks angibt. Ein Durchlauf dauert genau eine Millisekunde. (Beim U883 wird dabei ein 8-MHz-Quarz vorausgesetzt.) Bei der Anwendung von WAIT beachte man, dass die Berechnung des Ausdrucks und die vor- und nachher abzuarbeitenden Anweisungen ebenfalls Zeit brauchen. Weiterhin hat man bei WAIT mit großen Zeiten zu beachten, |
===== 7.4. Anwendungsbeispiele ===== | ===== 7.4. Anwendungsbeispiele ===== | ||
+ | |||
+ | **Beispiel 1**. Trotz des bescheidenen Zahlenbereiches lassen sich eine Reihe von mathematischen Berechnungen auch in Tiny BASIC mit hinreichender Genauigkeit ausführen, wiewohl etwas mehr Sorgfalt bei der Programmierung erforderlich ist, um Bereichsüberschreitungen zu vermeiden. | ||
+ | Wir wollen mit dem Newton-Verfahren die Quadratwurzel aus einer Zahl berechnen. Dazu wird von einer Anfangsnäherung X0 ausgegangen und so lange eine bessere Näherung berechnet, bis sich die erreichbare Genauigkeit eingestellt hat. Die Formel zur Berechnung der verbesserten Näherung Xn+1 aus der Näherung Xn lautet | ||
+ | |||
+ | Xn+1 = Xn – (Xn^2 – Y) / (2Xn), | ||
+ | |||
+ | wobei Y die zu radizierende Zahl ist. Würde man nun | ||
+ | LET X = X-(X*X-Y)/ | ||
+ | programmieren, | ||
+ | |||
+ | Xn+1 = Xn – (Xn^2 – Y) / (2Xn) = Xn – Xn / 2 + Y / (2Xn) | ||
+ | |||
+ | Bei dieser Umformung sind sowohl das Quadrat als auch die kritische Differenz verschwunden. Wir können folgendes Programm aufschreiben: | ||
+ | |||
+ | < | ||
+ | 10 INPUT "Y = " Y | ||
+ | 20 LET X=1, N=10 | ||
+ | 30 LET X=X-(X/ | ||
+ | 40 LET N=N-1; IF N>0 THEN GOTO 30 | ||
+ | 50 PRINT " | ||
+ | </ | ||
+ | |||
+ | Als Anfangsnäherung benutzen wir die 1, und die zehnte Näherung ist bei unserem Zahlenbereich immer genau genug. | ||
+ | |||
+ | |||
+ | **Beispiel 2**. In dem nun folgenden Beispiel benutzen wir den Operator $MOD. Es handelt sich um eine Primfaktorzerlegung. Man benötigt so etwas z.B., um die Frequenzen zu ermitteln, die sich leicht aus einer gegebenen (Quarz-) Oszillatorfrequenz mittels Teilerstufen erzeugen lassen. Das benutzte Verfahren ist recht einfach. Es werden alle möglichen Faktoren ausprobiert, | ||
+ | < | ||
+ | 10 INPUT "ZAHL: " Z | ||
+ | 20 LET F=2 | ||
+ | 30 IF Z $MOD F=0 THEN LET Z=Z/F; PRINT F | ||
+ | 40 ELSE LET F=F+1 | ||
+ | 50 IF F*F<=Z THEN GOTO 30 | ||
+ | 60 PRINT Z | ||
+ | </ | ||
+ | |||
+ | Die Zeile 30 lautet verbal umschrieben: | ||
+ | |||
+ | **Beispiel 3**. Wir wollen den Inhalt des Datenspeichers des U883 in einem gewissen Adressbereich ausdrucken. Dabei soll das folgende Druckbild auf jeder Zeile entstehen: | ||
+ | |||
+ | adresse daten1 daten2 ... daten8 ascii | ||
+ | |||
+ | Die Daten geben wir zu je zwei Bytes aus. also kommen 16 Bytes auf jede Zeile. Rechts erscheinen die Bytes, die als druckbare ASCII-Zeichen interpretiert werden können, als solche ausgedruckt. Damit kann man leicht abgespeicherte Texte erkennen. Das Programm hierfür sieht folgendermaßen aus: | ||
+ | |||
+ | < | ||
+ | 10 REM RAM DUMP | ||
+ | 20 INPUT " | ||
+ | 25 IF I<=0 THEN END | ||
+ | 27 REM AUF VIELFACHES VON 16 AUFRUNDEN | ||
+ | 30 IF I $MOD 16<>0 THEN LET I=I/ | ||
+ | 40 REM EINE ZEILE | ||
+ | 45 REM ADRESSE | ||
+ | 50 LET J=0; PRINTHEX A, " ", | ||
+ | 55 REM DATEN | ||
+ | 60 | ||
+ | 70 LET I=I-2, J=J+2, A=A+2 | ||
+ | 80 IF J <16 THEN GOTO 60 | ||
+ | 90 LET A=A-16 | ||
+ | 95 REM ASCII | ||
+ | 100 PRINT " ", | ||
+ | 110 LET C=GETEB[A] | ||
+ | 120 IF C>%1F THEN IF C<%7F THEN PROC PTC[C] | ||
+ | 130 ELSE PROC PTC[%2E]; REM PUNKT | ||
+ | 140 LET J=J-1, A=A+1 | ||
+ | 150 IF J>0 THEN GOTO 110 | ||
+ | 160 PRINT | ||
+ | 170 IF I>0 THEN GOTO 50 | ||
+ | </ | ||
+ | |||
+ | In Zeile 30 wird die eingegebene Länge auf eine durch 16 teilbare Zahl aufgerundet, | ||
+ | |||
+ | **Beispiel 4**. Wir wollen nun die Benutzung von TRAP mit einem formalen Beispiel illustrieren. Es bringt darüber hinaus einige typische Details bei der Anwendung von Tiny MPBASIC. | ||
+ | |||
+ | < | ||
+ | 10 REM ZEICHENSATZ AUSDRUCKEN UND | ||
+ | 20 REM IM HINTERGRUND TASTENEINGABEN LESEN | ||
+ | 30 LET C=%20, A=%1300, I=0 | ||
+ | 40 GOSUB 250 | ||
+ | 50 PROC PTC[C] | ||
+ | 60 LET W=100 | ||
+ | 70 LET W=W-1 | ||
+ | 80 IF W>0 THEN GOTO 70 | ||
+ | 90 LET C=C+1 | ||
+ | 100 IF C<%5F THEN GOTO 50 | ||
+ | 110 IF I=0 THEN GOTO 30 | ||
+ | 115 REM EINGABEN WIEDER AUSDRUCKEN | ||
+ | 120 LET J=0 | ||
+ | 130 PROC PTC[%0D] | ||
+ | 140 PROC PTC[GETEB[A+J]] | ||
+ | 150 WAIT 100; LET J=J+1 | ||
+ | 160 IF I>J THEN GOTO 140 | ||
+ | 170 END | ||
+ | 200 REM TRAPROUTINE | ||
+ | 210 PROC SETR[%FA, GETR[%FA]$AND %F7] | ||
+ | 220 PROC SETEB[A+I, GETR[%F0]] | ||
+ | 230 LET I=I+1 | ||
+ | 240 IF I>%FF THEN LET I=0 | ||
+ | 250 TRAP GETR[%FA]$MOD 8<>0 TO 210 | ||
+ | 260 RETURN | ||
+ | </ | ||
+ | |||
+ | Dieses Programm druckt fortwährend alle ASCII-Zeichen mit den Kodes %20 . .. %5E bis während des Druckens über die SIO Zeichen empfangen worden sind. Dann werden die empfangenen Zeichen ausgedruckt, | ||
+ | |||
+ | ===== 7.5. Benutzen des Interpreters im U883 ===== | ||
+ | |||
+ | Der Interpreter im U883 ist als Unterprogramm ausgeführt, | ||
+ | |||
+ | Das BASIC-Programm wird ohne Leerzeichen im ASCII-Kode abgelegt. Die Zeilennummern werden binär abgespeichert, | ||
+ | |||
+ | < | ||
+ | Tafel 12. Abkürzungen in Tiny MPBASIC | ||
+ | |||
+ | LET L | ||
+ | GOTO G | ||
+ | IF ... THEN F ... ; | ||
+ | ELSE >; | ||
+ | GOSUB S | ||
+ | RETURN R | ||
+ | PROC O | ||
+ | TRAP ... TO ! ... , | ||
+ | CLRTRP / | ||
+ | INPUT I | ||
+ | PRINT P | ||
+ | PRINTHEX H | ||
+ | STOP T | ||
+ | END E | ||
+ | WAIT W | ||
+ | CALL C | ||
+ | REM M | ||
+ | SAND $A | ||
+ | SOR $O | ||
+ | SXOR $X | ||
+ | SMOD $M | ||
+ | </ | ||
+ | |||
+ | Das folgende kleine Programm, das 1 KByte Speicher ab Adresse %1000 löscht, wird so, wie in Tafel 13 aufgezeigt, abgespeichert. Zum Ausdrucken der internen Darstellung kann z.B. das im letzten Abschnitt (Beispiel 2) aufgeführte Programm benutzt werden. | ||
+ | |||
+ | < | ||
+ | 10 LET A=%1000, L=%400 | ||
+ | 20 PROC SETEB[A,0] | ||
+ | 30 LET A=A+1, L=L-1 | ||
+ | 40 IF L>0 THEN GOTO 20 | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | Tafel 13. Interne Darstellung eines Programms in Tiny MPBASIC | ||
+ | |||
+ | 2000 80 0A 4C 41 3D 25 31 30 30 30 2C 4C 3D 25 34 30 ..LA=%1000, | ||
+ | 2010 30 0D 80 14 4F 53 45 54 45 42 5B 41 2C 30 5D 0D 0...OSETEB[A, | ||
+ | 2020 80 1E 4C 41 3D 41 2B 31 2C 4C 3D 4C 2D 31 0D 80 ..LA=A+1, | ||
+ | 2030 28 46 4C 3E 30 3B 47 32 30 0D 00 00 00 00 00 00 (FL> | ||
+ | </ | ||
+ | |||
+ | Es sei angenommen, dass dieses Programm auf der Adresse %2000 stehe. Dann kann es mit den folgenden Maschinenbefehlen aufgerufen werden: | ||
+ | |||
+ | < | ||
+ | ... | ||
+ | LD 6, #%20 | ||
+ | CLR 7 | ||
+ | CLR 8 | ||
+ | CLR 9 | ||
+ | SRP #%10 | ||
+ | CALL %07FD | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | Für die Programme **PUTCHR** und **GETCHR**, die das Benutzen von PRINT, PRINTHEX und INPUT ermöglichen, | ||
+ | |||
+ | |||
+ | Die **Prozedurtabelle**, | ||
+ | Byte 0|1|2|3|4| . . . |N|N+1|N+2| ... | ||
+ | Byte 0 enthält die Länge N des Prozedurnamens, | ||
+ | %04|%50|%52|%4F|%5A|%20|%10|%05|%46|%55|%4E|%4B|%54|%30|%00|%FF | ||
+ | |||
+ | Die **Übergabe der Parameter** vom Interpreter an die Prozedur und der Ergebnisse von der Prozedur an den Interpreter erfolgt über den Stack. Wenn die Prozedur m Ergebnisse an den Interpreter übergibt und n Parameter von diesem übernimmt, dann befindet sich der Stack beim Aufruf der Prozedur in dem in Tafel 14 aufgezeigten Zustand. Vor dem letzten RET in der Prozedur, das wieder zum Interpreter führt, muss der Stackpointer um 2n-2 erhöht worden sein (wenn n>1) und natürlich auf die Rückkehradresse zum Interpreter zeigen. | ||
+ | |||
+ | < | ||
+ | Tafel 14. Datenübergabe bei Prozeduren im U883 | ||
+ | |||
+ | Stack Inhalt | ||
+ | SP+2n+2m+1 Platz für das m-1te bis erste Ergebnis, | ||
+ | ... SP+2n+2 wenn m>1. Der Wert für das letzte (mte) Ergebnis ist in das Arbeitsdoppelregister RR2 zu schreiben. | ||
+ | SP+2n+1 ... SP+2n Wird vom Interpreter benutzt. | ||
+ | SP+2n-1 Erster bis n-1ter Parameter, wenn n>1. | ||
+ | ... SP+2 Der Wert des letzten Parameters befindet sich im Arbeitsdoppelregister RR4. | ||
+ | SP, SP+1 Rückkehradresse zum Interpreter | ||
+ | SP Inhalt vom Stackpointer | ||
+ | </ | ||
+ | |||
+ | Schließlich sei noch erwähnt, daß der U883 auf der Adresse %812 startet, falls dort ROM liegt und sonst auf %E000. | ||
+ | |||
+ | |||
+ | ===== 7.6. Editor/ | ||
+ | |||
+ | Vom Hersteller des U883 wird auch der zugehörige [[elektronik: | ||
+ | LIST {zeilennummer}\\ | ||
+ | RUN\\ | ||
+ | CONT {zeilennummer}\\ | ||
+ | STEP {zeilennummer}\\ | ||
+ | Mit LIST wird das gesamte Programm bzw. die angegebene Zeile aufgelistet. Drücken von Return nach LIST mit Zeilennummer führt zum Auflisten der Folgezeile. RUN startet das Programm an dessen Anfang, während man mit CONT von der eingegebenen Zeilennummer ab starten kann. Darüber hinaus kann mit diesem Kommando die Programmabarbeitung nach STOP fortgesetzt werden. STEP schließlich gestattet das Abarbeiten einer einzelnen Zeile. Anschließendes Drücken von Return bewirkt das Abarbeiten der Folgezeile. | ||
+ | |||
+ | ===== Anhang B. Syntaxbeschreibung von Tiny MPBASIC ===== | ||
+ | |||
+ | Metalinguistische Konstanten sind mit Großbuchstaben gedruckt. Das sind Zeichen bzw. Zeichenketten, | ||
+ | |||
+ | < | ||
+ | -> | ||
+ | => | ||
+ | | oder | ||
+ | {xxx} darf weggelassen werden | ||
+ | {xxx}* darf beliebig oft dastehen oder auch weggelassen werden | ||
+ | {xxx}*n darf maximal n mal dastehen oder auch weggelassen werden | ||
+ | |||
+ | Syntaxbeschreibung | ||
+ | |||
+ | programm => | ||
+ | zeile => | ||
+ | zeilennummer => | ||
+ | anweisung => | ||
+ | anweisungsname => | ||
+ | anweisung => | ||
+ | ausdruck => | ||
+ | aausdruck => | ||
+ | wert => konst|var|fkt|(aausdruck) | ||
+ | alop => +|-|*|/ | ||
+ | konst => | ||
+ | var => buchst | ||
+ | fkt => funktionsname {parameterliste} | ||
+ | pkonst -> | ||
+ | nkonst => | ||
+ | funktionsname => | ||
+ | name => buchst buchst|ziffer {buchst|ziffer}*252 | ||
+ | buchst => | ||
+ | ziffer => | ||
+ | lausdruck => | ||
+ | vop => > | ||
+ | variablenliste => | ||
+ | prozedurname => | ||
+ | parameterliste => | ||
+ | text -> bei. ASCII-Zeichenfolge ohne " | ||
+ | kommentar -> | ||
+ | </ | ||
+ | |||
+ | ===== Literatur ===== | ||
+ | |||
+ | |||
+ | (11) Bennewitz, W.Podszuweit, | ||
+ | (12) Müller, S.: Einchipmikrorechner U883 interpretiert Tiny MPBASIC. radio fernsehen elektronik 34(1985) 3, S. 143 f.\\ | ||
+ | (13) Technische Beschreibung Einchipmikrorechner U883. Erfurt: veb mikroelektronik „karl marx" 1985 | ||