FORTH für den NASCOM
Teil 4 von Günter Kreidl
Zunächst einige Fehlerkorrekturen zum
letzten Beitrag:
Die als "<" bezeichnete Funktion
muß natürlich "<=" heißen (da hab' ich
einfach gepennt!). Bei der Beschreibung der
Funktion FILL muß es heißen: "an die Adresse
(T-2)". Außerdem ist im Druck bei der
Funktion MCODE das abschließende Semicolon
verloren gegangen. Nun aber zu den neuen
Funktionen:
: SPACE 32 COUT ;
: SPACES 1 FOR SPACE LOOP ;
: CLS 12 COUT ;
SPACES erwartet die gewünschte Anzahl der
Leerzeichen als Argument auf dem Stack, sie
kann z.B. so aufgerufen werden "10 SPACES".
3113 CONSTANT CURSADR
: LINE 64 * 1994 + CURSADR POKEW ;
: POSITION DEC CURSADR MEM+ ;
: SCREEN SWAP LINE POSITION ;
Die ersten beiden Funktionen erwarten je
einen Wert auf dem Stack und setzen den
Cursor in die entsprechende Zeile bzw. Position
einer Zeile. SCREEN kombiniert diese
beiden Funktionen und erwartet deshalb zwei
Werte: "(Zeile) (Position) SCREEN".
Einige weitere recht triviale Funktionen:
: ' SCAN IF FIRST POP PEEKB
ELSE ERROR TYPE THEN ;
: PRINTHEX 3084 POKEW 102 NAS-SYS ;
: = CONBXA PRINTS ;
: . DUP = ;
: BACKSPACE 8 COUT ;
Die Funktion "'" gibt den dezimalen Wert eines ASCII-Zeichens
auf den Stack. Folgendes Beispiel illustriert mehrere Funktionen
gleichzeitig:
' S . 2 SPACES PRINTHEX
83 0053 (Antwort des Interpreters)
Die Tastaturabfrage TERMINAL? muß wieder in Maschinencode
programmiert werden, Sie gibt 0 auf den Stack, wenn keine Eingabe von
der Tastatur erfolgt ist, sonst den Wert des Zeichens und -1 (=FFFFH) :
MCODE TERMINAL?
XXXX DF 62 21 00 00 30 07 6F
XXXX 26 00 E5 21 FF FF E5.
Die Adressen XXXX werden vom Monitor angegeben. Die folgende Funktion
druckt das jeweils gewünschte "Dictionary" aus, dessen
Startadresse auf dem Stack übergeben wird
| |
(z.B. mit NAMES PEEKW für den Interpreter).
PRINTDIC REPEAT DUP FIRST DUP EQZ UNTIL
+ SWAP PRINTS 2 SPACES
INC INC LOOP
CLEAR ;
In der Grundversion belegt der Interpreter 4 KB Speicher, wobei das
Dictionary am oberen Ende des Speicherbereichs liegt. Es ist nun sehr
leicht möglich und mit den gezeigten Erweiterungen auch bald nötig, das
Dictionary zu verschieben. Die obere und untere Grenze sind durch die
Variablen MEMORY und NAMES gegeben, und die Verschiebung wird mit der
Funktion MOVEBYTES ausgeführt.
Anschließend müssen die Variablen NAMES und MEMORY natürlich angepaßt
werden und ebenfalls eine Variable CDICT, die aber nicht im Dictionary
enthalten ist und deshalb absolut eingegeben werden muß (bei 1297H bzw.
4759 dezimal). Will man nun das erweiterte Programm auf Cassette
speichern, so müssen zwei getrennte Blöcke gespeichert werden, Das
geschieht mit der folgenden Funktion:
: WRITEM 4096 3084 POKEW CODEADR PEEKW
3086 POKEW 87 NAS-SYS
NAMES PEEKW 3084 POKEW MEMORY
PEEKW INC 3086 POKEW 87 NAS-SYS ;
Es folgt nun ein neuer, vereinfachter
Interpreter, den wir für den Bildschirm-Editor brauchen sowie die
Hilfsvariable:
NEGONE VARIABLE IFLAG
: INTERPRETER NEGONE IFLAG POKEW READLINE
REPEAT SCAN IFLAG PEEKW * EQZ UNTIL
NAMES PEEKW LOOKUP
IF EXECUTE
ELSE CONAXB EQZ IF ERROR TYPE
PRINTS ZERO IFLAG POKEW
THEN THEN LOOP
IFLAG PEEKW EQZ IF CLEAR THEN ;
Dieser Interpreter arbeitet ähnlich wie
die Funktion INTERACT, nur ohne Prompt-Zeichen und ohne Anzeige des
obersten Stackwertes. Mit Hilfe der folgenden Funktion kann man von
INTERACT nach INTERPRETER umsteigen und umgekehrt:
: ENTRY GETWORD NAMES PEEKW LOOKUP
IF EXEC POKEW
ELSE ERROR TYPE PRINTS THEN ;
Der Aufruf erfolgt mit "ENTRY INTERPRETER". Für
den Editor benötigen wir noch eine Variable, Konstanten und eine
Hilfsfunktion:
ONE VARIABLE RFLAG
CADR BLINK CONSTANT BLADR
|