Nascom Journal

  

Dezember 1981 · Ausgabe 11/12

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 MOVE­BYTES 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
Seite 3 von 55