C 64
Listing des Monats

Tiny-Forth-Compiler zum Abtippen

Die Programmiersprache Forth ist zur Zeit in aller Munde. Unser Listing des Monats gibt Ihnen die Möglichkeit, Forth einmal praktisch zu erleben.

Forth ist eine der jüngsten Programmiersprachen. Sie wurde 1969 von Charles Moore am National Radio Astronomy Observatory in den USA entwickelt. Der Name der Sprache lautete eigentlich Fourth (das Vierte), aber der IBM-Computer, auf dem Forth entwickelt wurde, ließ nur fünf Buchstaben als Namensangabe zu, so entstand »Forth«.

Forth ist eine der schnellsten Programmiersprachen, die es gibt. Vor allem auf Heimcomputern wird es deshalb gerne eingesetzt. Dazu kommt, daß Forth nicht viel Speicherplatz beansprucht. Die Sprache besteht nicht nur aus einem Compiler, sondern auch aus einem Interpreter; beide arbeiten Hand in Hand.

Die wohl auffälligste Eigenart von Forth ist die Art und Weise, in der Forth rechnet. Es ist die sogenannte »UPN« (Umgekehrte Polnische Notation), auch Postfix-Notation genannt. Sie ist es unter anderem, die Forth die Geschwindigkeit verleiht (10 bis 20mal so schnell wie Basic). Doch was bedeutet UPN?

Ein Beispiel: Sie wollen das Ergebnis von 8 + 5 auf dem Bildschirm ausgeben. In Basic sähe das dann so aus: »PRINT 8 + 5«. In Forth schreibt sich das etwas anders: »5 8 + .«. Scheinbar verwirrend, aber nur auf den ersten Blick. Denn das Prinzip ist einfach. Im Mittelpunkt von Forth steht der Stack (Stapel). Man stelle sich einen Stapel Papier vor, auf den man Blätter obenauflegen kann und auch nur von oben wieder nehmen kann. Das bedeutet, das Blatt, welches Sie zuletzt draufgelegt haben, wird als erstes wieder heruntergenommen. Man nennt dieses System auch »LIFO« (Last In — First Out). Doch wie kann man damit rechnen? Kommen wir wieder zu unserem Beispiel zurück. Der Computer legt als erstes die Zahl 5 auf den Stack. Bild 1 verdeutlicht das Prinzip. Der TOS (Top of Stack) hat jetzt den Wert 5. Dann folgt die »8« nach dem gleichen Verfahren. Darauf addiert der Computer die zwei obersten Zahlen und legt das Ergebnis auf den Stack, dafür ist »+« verantwortlich. Jetzt haben wir zwar das Ergebnis auf dem Stack, können es aber nicht sehen. Für die Ausgabe von 16 Bitzahlen ist der Befehl ».« zuständig. Damit wird immer der jeweilige Wert des TOS ausgegeben.

Bild 1. Die Rechnung »5 + 8 = 13« als UPN-Demo

Diese Art des Rechnens mittels UPN mag für Menschen sehr gewöhnungsbedürftig sein, für den Computer ist sie ideal. Doch Forth besitzt neben seiner Geschwindigkeit auch noch weitere Vorteile:

Sie sehen also, Forth ist eine Sprache, mit der zu beschäftigen es sich lohnt.

(Alexander Schindowski/ev)

Forth ist sicher eine der interessantesten Programmiersprachen überhaupt. Unser neues Listing des Monats stellt diese Sprache jedem C 64-Besitzer zur Verfügung.

Die folgende Anleitung zur Handhabung des Forth-Compilers kann natürlich kein Lehrbuch ersetzen. Falls Sie mit Foth noch keinerlei Erfahrungen haben, finden Sie im Anhang eine Übersicht über Forth-Literatur. Doch nun zur Beschreibung unseres Tiny-Forth-Compilers.

Die folgenden Befehle haben so gut wie alle einen Einfluß auf den Stack. Deshalb wird eine verkürzte Schreibweise verwendet, um das Verhalten der einzelnen Befehle darzustellen: »(Stack vorher - - - Stack nachher) «.

Die verwendeten Symbole haben folgende Bedeutung: n = 16-Bit-Zahl, b = 8-Bit-Zahl, c = ASCII, addr = Adresse, f = Flag (0/1).

Die einzelnen Befehle des Tiny-Forth-Compilers sind in Tabelle 1 noch einmal übersichtlich dargestellt. Im folgenden werden die Befehle genauer beschrieben:

Arithmetikbefehle

Addition »+« (n2 n1 - - - n3)

Der Additionsbefehl holt die ersten beiden Argumente (n1,n2) vom Stack, addiert sie miteinander und legt das Ergebnis (n3) in den TOS (Top of Stack).

Subtraktion »-« (n2 n1 - - - n3)

Der Subtraktionsbefehl holt, wie bei der Addition, die ersten zwei Argumente (n1,n2) vom Stack, das Ergebnis (n3) wird wieder im TOS abgelegt.

Multiplikation »*« (n2 n1 - - - n3)

Die Multiplikation verhält sich analog zur Addition und Subtraktion.

Division »/« (n2 n1 - - - n3)

Analog zu Multiplikation.

Modulo »MOD« (n2 n1 - - - n3)

Ähnlich einer Division, es wird aber nicht das Ergebnis der Division, sondern der Divisionsrest auf den Stack gelegt.

Vergleichsbefehle

Gleich »=« (n2 n1 - - - f1)

Es werden die zwei obersten Werte auf Gleichheit geprüft.

Größer »<« (n2 n1 - - - f1)

Es wird geprüft, ob n2 größer als n1 ist.

Kleiner »>« (n2 n1 - - - f1)

Es wird geprüft, ob n2 kleiner als n1 ist.

Logische Verknüpfungen

AND (n2 n1 - - - n3)

Zwischen den Werten n1 und n2 wird eine logische UND-Operation ausgeführt.

OR = (n2 n1 - - - n3)

Es wird ein logisches ODER ausgeführt.

XOR (n2 n1 - - - n3)

Es wird ein logisches exklusives ODER ausgeführt.

NOT (f1 - - - f2)

Das oben liegende Flag wird invertiert.

Stackoperatoren

DROP (n2 n1 - - - n2)

Der oberste Wert wird vom Stack entfernt.

DUP (n1 - - - n1 n1)

Der oberste Wert auf dem Stack wird dupliziert.

SWAP (n2 n1 - - - n1 n2)

Die obersten beiden Werte werden vertauscht.

OVER (n2 n1 - - - n2 n1 n2)

Kopiert den zweiten Wert zum neuen TOS.

PICK (n1 n - - - n1 n2)

Pick holt den n-ten Wert in den TOS.

ROT (n3 n2 n1 - - - n2 n1 n3)

Rot läßt die ersten drei Elemente des Stack gegen den Uhrzeigersinn rotieren.

@ (addr - - - n1)

Holt eine 16-Bit-Zahl aus der Adresse addr.

! (n1 addr - - -)

Speichert eine 16-Bit-Zahl in der Adresse addr.

c@ (addr - - - b1)

Holt eine 8-Bit-Zahl aus der Adresse addr.

c! (b1 addr - - -)

Speichert eine 8-Bit-Zahl in der Adresse addr.

Kontrollstrukturen

BEGIN — UNTIL (f - - -)

Der Programmteil zwischen BEGIN und UNTII wird solange ausgeführt, bis der TOS bei UNTIL ungleich Null ist.

BEGIN — WHILE — REPEAT (f - - -)

Der Programmteil zwischen BEGIN und REPEAT wird solange ausgeführt, wie der TOS bei WHILE ungleich Null ist.

IF — ENDIF (f - - -)

Der Programmteil zwischen IF und ENDIF wird nur dann ausgeführt, wenn der TOS bei IF ungleich Null ist.

IF — ELSE — ENDIF (f - - -)

Bei erfüllter Bedingung wird der Programmteil zwischen IF und ELSE ausgeführt, bei nichterfüllter Bedingung der zwischen ELSE und ENDIF.

Schleifen

DO (n2 n1 - - -)

DO legt die Argumente n1 (Endwert), n2 (Startwert) auf den Returnstack und leitet eine Schleife ein.

LOOP (- - -)

LOOP erhöht den Schleifen-Zähler um 1, ist der Endwert nicht erreicht, wird wieder zu dem auf DO folgenden Befehl gesprungen.

I (- - - n)

Der Befehl I legt den Wert des Schleifenzählers auf den TOS.

+LOOP (n - - -)

+LOOP erhöht den Schleifenzähler um n, weiter wie LOOP.

Ein-/Ausgabeoperatoren

KEY (- - - c)

Holt den ASCII-Wert, der gerade gedrückten Taste in den TOS, ist keine Taste gedrückt, so wird eine 0 in den TOS gelegt.

GET (- - - c)

Wartet, bis eine Taste gedrückt wird und legt dann ihren ASCII-Wert in den TOS.

EXPECT (addr n - - -)

Erwartet eine Eingabe, die mit Return abgeschlossen wird, und legt sie bei addr mit einer maximalen Länge n im Speicher ab. Als Abschlußzeichen wird eine 13 in den Speicher gesetzt.

EMIT (c - - -)

EMIT gibt den auf dem TOS liegenden ASCII-Wert auf dem Bildschirm aus.

TYPE (addr n - - -)

TYPE gibt n Zeichen, welche ab addr im Speicher stehen, auf dem Bildschirm aus.

CR (- - -)

CR bewirkt einen Zeilenvorschub.

CLS (- - -)

Löscht den Bildschirm.

."TEXT" (- - -)

Gibt den Text zwischen »."« und »"« aus (funktioniert nur in compilierter Form).

Definitionsbefehle

n CONSTANT ⟨Name⟩ (n - - -)

CONSTANT definiert eine Konstante mit dem Wert n und dem Namen ⟨Name⟩. Wird ⟨Name⟩ im Programm aufgerufen, so wird n auf den TOS gelegt.

n VARIABLE ⟨Name⟩ (n - - -)

VARIABLE definiert eine Variable mit dem Wert n und dem Namen ⟨Name⟩. Wird ⟨Name⟩ im Programm aufgerufen, so wird die Adresse der Varible auf den Stack gelegt. Ein Wert wird mit @ (lies: Fetch) auf den TOS geholt und mit! (lies: Store) an eine Variable übergeben.

n MEMORY ⟨Name⟩ (n - - -)

MEMORY definiert einen Speicherbereich mit dem Namen ⟨Name⟩ und der Länge n. Wird ⟨Name⟩ im Programm aufgerufen, so wird die Adresse des Speicherbereichs übergeben. In Adresse-2 ist die Länge zu finden und kann mit @ ausgelesen werden. MEMORY ist kein Standardwort!

: ⟨Name⟩…; (- - -)

Der Doppelpunkt definiert ein neues Forth-Wort mit dem Namen ⟨Name⟩. Die Definition muß mit »;« abgeschlossen werden.

Systembefehle

BASIC: Kehrt zum Basic zurück.

RESET: Kehrt zum Ausgangszustand zurück.

LIST n: Listet Screen n auf dem Drucker oder dem Bildschirm. CLEAR n: Löscht SCREEN n auf der Diskette.

LOAD n: Compiliert Screen n in das Vocabulary.

FORGET ⟨Name⟩: Löscht das Wort ⟨Name⟩ aus dem Vocabulary.

VLIST: Listet das Vocabulary.

SAVE-SYSTEM ⟨Name⟩: Speichert den Objektcode und Vocabulary-Einträge aller selbstdefinierten Befehle auf Diskette.

LOAD-SYSTEM ⟨Name⟩: Lädt den Objektcode und die Vocabulary-Einträge wieder. Das System muß vorher mit RESET wieder in den Ausgangszustand gebracht werden und in Zeile 380 muß die Variable VOC denselben Wert wie beim Speichern haben, da sonst die Sprungadressen im Objektcode nicht stimmen.

EDIT n: Ruft den Bildschirmeditor auf, n ist die Nummer des Screens.

Spezialbefehle

CALL (addr - - -)

Ruft ein Maschinenprogramm mit der Adresse addr auf. Es können, wie bei SYS in Basic, in den Speicherzellen 780 das A-, 781 das X-, 782 das Y-Register mit übergeben werden.

R⟩ (- - - n)

Bringt das oberste Element des Return-Stacks auf den Stack.

⟩ R (n - - -)

Bringt das oberste Element des Stacks auf den Return-Stack.

;S (- - -)

Dieser Befehl sorgt für den vorzeitigen Abbruch des aktuellen Befehls.

Das Programm

Das Programm wurde mit Absicht sehr flexibel gehalten. Nach oder während des Abtippens können Sie einige Dinge nach Ihrem eigenen Ermessen ändern. So zum Beispiel die Startadresse des Objektcodes in Zeile 380; die Variable VOC enthält den Startwert. Allerdings sollten Sie nicht unter VOC=5 * 4096 gehen, da sonst eine Kollision mit dem String-Bereich möglich ist. Dies macht sich durch eine »OUT OF MEMORY«-Meldung oder durch einen Systemabsturz bemerkbar. Das Programm kann nur mit 16-Bit-Zahlen arbeiten und umfaßt nicht den gesamten Forth-Standard. Das Programm besteht aus einem Compiler, der in den Zeilen 1540 bis 2610, und einem Interpreter, der in den Zeilen 700 bis 1530 steht. Der Interpreter ist nicht in der Lage, alle Befehle auszuführen. Um Ihnen zu helfen, welche Befehle interpretierbar sind und welche nicht, sind nur die interpretierbaren im Vocabulary aufgeführt. Andere Befehle wie VARIABLE, MEMORY, etc., kurzum alle Definitionsbefehle, dürfen nicht im Compilermodus angewendet werden.

Das Programmieren in Forth

Nach dem Starten des Programms wird zuerst das Maschinenprogramm »VOCABULARY« in den Bereich 49152 bis 50160 geladen. Nach etwa einer Sekunde erscheint ein blinkender Cursor; jetzt können Sie Ihre Eingaben machen. Sie befinden sich im Interpretermodus, das heißt alle eingegebenen Befehle werden sofort ausgeführt. Daß dies im Interpretermodus so langsam geht, liegt nur daran, daß der Interpreter in Basic geschrieben ist; compilierte Befehle laufen dagegen etwa 10- bis 20mal so schnell wie Basic (sie werden vollkommen in Maschinensprache übersetzt). Vielleicht geben Sie mal das folgende Beispiel ein: »8 5 + .« (RETURN). Sie müßten jetzt 13 auf dem Bildschirm erhalten; wenn nicht, dann müssen Sie irgendwo im Programm einen Fehler gemacht haben. Sie können auch Kommentare einfügen, sie werden mit einer »(« begonnen und mit »)« abgeschlossen. Jeder Befehl wird durch ein Leerzeichen (oder Return) vom anderen getrennt.

Doch wie definiert man einen neuen Befehl? Diese Frage wird Ihnen sicher schon lange auf den Lippen brennen. Doch auch hier macht es Ihnen Forth sehr einfach. Um die Definition eines neuen Befehls einzuleiten wird »:« benutzt, gefolgt von dem Namen des neuen Befehls (bitte vergessen Sie nicht das Leerzeichen hinter jedem Befehl.) Dann folgen die Befehle, die in das Wort compiliert werden sollen. Ein »;« beendet die Definition. Danach ist der Befehl wie jeder andere Befehl benutzbar. Auf Fehler reagiert der Compiler, indem er die Compilation abbricht. Danach sollte man den Befehl mit FORGET löschen, da sonst das Programm abstürzt, wenn Sie den Befehl aufrufen.

Der Editor

Nun ist es ziemlich zeitaufwendig, wenn man bei jedem Fehler den Befehl neu eingeben muß, deshalb bietet Forth einen zweiten Editor. Es ist ein Bildschirmeditor, welcher mit dem Systembefehl »EDIT n« aufgerufen wird, n bezeichnet hier die Nummer des Screens, der editiert werden soll. Ein Screen ist einfach eine Bildschirmseite, auf der der zu compilierende Sourcecode steht.

Geben Sie einmal »EDIT 1« ein. Das System versucht nun, Screen 1 von der Diskette zu laden. Ist der Screen nicht auf Diskette vorhanden, so wird trotzdem in den Editor gesprungen, nur daß der Screen leer ist. Nachdem sich das System im Editor befindet, sehen Sie links die Zeilennummern von 0 bis 23 mit folgendem Doppelpunkt (dieser Doppelpunkt hat keine Bedeutung). Sie können nun mit dem Cursor hinter den Doppelpunkt fahren und eine Zeile eingeben. Jede Zeile muß mit RETURN abgeschlossen werden. Eine Zeile darf nicht länger als 35 Zeichen sein. Geben Sie doch einmal das vorherige Beispiel ein. Die Nummer am Anfang jeder Zeile entspricht in etwa einer Zeilennummer in Basic.

Um nun den Editor zu verlassen, gibt es zwei Möglichkeiten, einmal mit »e«, damit der Screen n abgespeichert wird und mit »s«, so wird der Editor ohne Änderung des Screens verlassen. Die Buchstaben müssen in der ersten Spalte einer Zeile stehen, also dort, wo die Zeilennummer steht. Es gibt noch mehr dieser Editorbefehle (siehe Tabelle 4). Zum Einfügen von Zeilen benützen Sie »I Zeile Anzahl«, mit »D Zeile Anzahl« löschen Sie Zeilen. Mit »L« listen Sie den Screen noch einmal, das ist dann von Nutzen, wenn Sie versehentlich die CLR-Taste betätigt haben. Mit »N Nummer« ändern Sie die Nummer eines Screens. Das Compilieren eines Screens geschieht mit LOAD n. Soll der nächste Screen (n + 1) auch noch compiliert werden, so muß in der letzten Zeile des Screens n der Befehl »-->« vorhanden sein. Experimentieren Sie doch mal ein bißchen mit dem Editor.

In den Bildern 2 bis 6 finden Sie einige selbstdefinierte Befehle. Die Befehle J und LEAVE in Bild 3 möchte ich näher erklären. J gibt den Schleifenwert der zweitinnersten Schleife aus. Die Befehle R> und >R manipulieren den Returnstack (der Returnstack funktioniert genauso wie der normale Stack). Hier werden Werte für Schleifen zwischengespeichert und zwar im Format Endwert, Zähler. R> holt den obersten Wert des Returnstacks auf den Stack, >R tut das Gegenteil. Die 704 ist nur Zwischenspeicher. LEAVE schließt eine Schleife vorzeitig ab, indem Endwert und Zähler gleichgesetzt werden.

Viel Spaß beim Programmieren in Forth.

(Alexander Schindowski/ev)

Info: Literatur zu Forth:

1) Rechenoperationen:

1.1) +

(n2 n1 - - - n3)

1.2) -

{n2 n1 - - - n3)

1.3) *

(n2 n1 - - - n3)

1.4) /

(n2 n1 - - - n3)

1.5) MOD

(n2 n1 - - - n3)

2) Vergleichsoperatoren:

2.1) =

(n2 n1 - - - f)

2.2) >

(n2 n1 - - - f)

2.3) <

(n2 n1 - - - f)

3) Logische Verknüpfungen:

3.1) AND

(n2 n1 - - - n3)

3.2) OR

(n2 n1 - - - n3)

3.3) NOT

(f1 - - - f2)

3.4) XOR

(n2 n1 - - - n3)

4) Stackoperatoren:

4.0) DROP

(n1 - - -)

4.1) DUP

(n1 - - - n1 n1)

4.2) SWAP

(n2 n1 - - - n1 n2)

4.3) OVER

(n2 n1 - - - n2 n1 n2)

4.4) PICK

(n1 n - - - n1 n2)

4.5) ROT

(n3 n2 n1 - - - n2 n1 n3)

4.6) @

(addr - - - n1)

4.7) !

(n1 addr - - -)

4.8) c@

(addr - - - b1)

4.9) c!

(b1 addr - - -)

5) Kontrollstrukturen:

5.1) BEGIN — UNTIL

(f - - -)

5.2) BEGIN — WHILE — REPRAT

(f - - -)

5.3) IF — ENDIF

(f - - -)

5.4) IF — ELSE — ENDIF

(f - - -)

6) Definitionsworte:

6.1) VARIABLE

(n - - -)

6.2) CONSTANT

(n - - -)

6.3) MEMORY

(n - - -)

6.4) : ... ;



7) Ein-/Ausgabe:

7.1) EXPECT

(addr n - - -)

7.2) TYPE

(addr n - - -)

7.3) KEY

(- - - c)

7.4) GET

(- - - c)

7.5) EMIT

(c - - -)

7.6) ."

(- - -)

7-7) •

(n - - -)

7.8) CR

(---)

7.9) CLS

(- - -)

8) Schleifen:

8.1) DO

(n2 n1 - - -)

8.2) LOOP

(- - -)

8.3) +LOOP

(n - - -)

8.4) I

(- - - n)

9) Sonstige Befehle:

9.1) call

(addr - - -)

9.2) >R

(n - - -)

9.3) R>

(- - - n)

9.4) DEPTH

(- - - n)
Tabelle 1. Der Befehlssatz des Tiny-Forth-Compilers
A,X,I,Z Lauf- und Hilfsvariablen
VOC Vocabulary-Zeiger
BE Beginn des Vocabulary
SP Zeiger für Compilerstack
AN Anzahl der Vocabulary-Einträge
ZE$ Eingabezeile
BE$ Einzelner Befehl
COMP Flag für Compilation
AD Adressen-Zwischenspeicher
OK Zahlenumwandlung geglückt?
A$ Hilfsvariable
WO$(X) Wörterverzeichnis
AD(X) Startadressen-Verzeichnis
BLOCK Flag für Compilation von Diskette
Z1 Zeilenzähler
XX Umgewandelte Zahl
X Top of Stack (TOS)
Tabelle 2. Variablenübersicht zum Tiny-Forth-Compiler
BASIC Zurück zu Basic
RESET Zurück in Ausgangsstellung
VLIST Listet das Vocabulary
FORGET Lösche ein Wort
FLOPPY Gibt einen Befehl an die Floppy
SAVE-SYSTEM Speichert das Vocabulary ab
LOAD-SYSTEM Lädt das Vocabulary
LIST n Listed eine Screen
LOAD n Compiliert eine Screen
CLEAR n Löscht eine Screen
EDIT n Ruft den Editor auf
Tabelle 3. Forth-Systembefehle
E Beendet das Editieren und speichert die Screens ab
S Beendet das Editieren
L Listet die Screens
I (z,a) Fügt Zeile(n) ein
D (z,a) Löscht Zeile(n)
N (x) Ändert die Screen-Nummer
Tabelle 4. Befehle des Forth-Editors
100 rem ****************************
110 rem *                          *
120 rem *       forth-compiler     *
130 rem *                          *
140 rem *           fuer           *
150 rem *                          *
160 rem *        commodore-64      *
170 rem *                          *
180 rem ****************************
190 rem *                          *
200 rem *  alexander schindowski   *
210 rem *                          *
220 rem *  6000 frankfurt/main 50  *
230 rem *                          *
240 rem * rudolf-hilferding-str.49 *
250 rem *                          *
260 rem ****************************
270 rem *                          *
280 rem *  telephon:(069)/570520   *
290 rem *                          *
300 rem ****************************
310 :
320 :
330 :
340 if a=0 thena=1:load"vocabulary",8,1
350 def fnh(x)=(int(x/256))
360 def fnl(x)=(x-256*fnh(x))
370 poke 53272,23:print"{clr}{lblu}";chr$(8);
380 voc=6*4096:be=voc:sp=0:z1=0
390 poke 55,fn l(be):poke 56,fn h(be)
395 dim st(20),sc$(24),wo$(100),ad(100)
400 print tab(14);"Forth-Compiler"
410 print tab(17);"fuer den"
420 print tab(15);"Commodore-64"
430 print"----------------------------------------";
440 print"     Von Alexander Schindowski 1985{down}{down}{down}{down}{down}{down}{down}{down}"
450 data 38
460 data "+",49563
470 data "cls",49158,"depth",49968
480 data "@",50012,"drop",49236
490 data "emit",49855,"expect",49936
500 data "=",49410,"i",49766
510 data "key",49880
520 data "+loop",49821,"mod",49733
530 data "not",49458,"over",49284
540 data ".",49163,"-",49578
550 data "swap",49248,">r",49751
560 data "and",49497,"cr",49384
570 data "/",49721,"do",49757,"!",49977
580 data "dup",49239,"xor",49541
590 data "get",49862,">",49434
600 data "<",49452,"loop",49811
610 data "*",49596,"or",49519
620 data "c@",50030,"c!",49996
630 data "r>",49745,"type",49915
640 data "pick",50062,"call",50047,"rot",50085
650 read an
660 for i=1 to an
670 read wo$(i),ad(i)
680 next i:poke 2,0:poke 252,0
690 gosub 3830
693 :
695 rem **************************
700 rem *** befehls-auswertung ***
705 rem **************************
708 :
710 gosub 2630
715 :
720 if be$=":" then 1540
725 :
730 for i=an to 1 step -1
740 if be$=wo$(i) then 760
750 next i:goto 770
760 sys ad(i):goto 700
765 :
770 gosub 3030
780 if ok=0 then 830
790 poke 781,fn l(xx)
800 poke 780,fn h(xx)
810 sys 49194
820 goto 700
825 :
830 if be$="reset" then run
835 :
840 if be$="basic" then end
845 :
850 if be$<>"vlist" then 900
860 print:for i=an to 1 step-1
870 print wo$(i)"  ";
880 next:print
890 goto 700
895 :
900 if be$<>"forget" then 950
910 gosub 2630:for i=an to 1 step-1
920 if be$<>wo$(i) then next i
930 if i>an then print be$" I can't find":goto 700
935 :
940 voc=ad(i):an=i-1:goto 700
950 if be$<>"(" then 980
960 if be$<>")" then gosub2630:goto960
970 goto 700
975 :
980 if be$<>"edit" then 1020
990 gosub 2630 :sc=val(be$)
1000 print"Screen:";sc:gosub 3280
1010 if be$="-->"then ze$="":sc=sc+1:goto1000
1012 goto 700
1015 :
1020 if be$<>"load" then 1050
1030 gosub 2630:sc=val(be$)
1040 block=1:z1=0:gosub 3110:goto 700
1050 if be$<>"-->" then 1070
1060 sc=sc+1:gosub3110:comp=1:block=1:z1=0:goto 700
1070 :
1080 if be$<>"variable" then 1145
1085 gosub 2630:an=an+1:wo$(an)=be$
1090 ad(an)=voc:xx=voc+8
1095 gosub 3470:poke voc,169
1100 poke voc+1,fn h(xx)
1105 poke voc+2,162
1110 poke voc+3,fn l(xx)
1115 poke voc+4,32:poke voc+5,42
1120 poke voc+6,192:poke voc+7,96
1125 poke voc+8,fn l(x)
1130 poke voc+9,fn h(x)
1135 voc=voc+10
1140 goto 700
1145 :
1150 if be$<>"memory" then 1220
1155 gosub 2630:an=an+1:wo$(an)=be$
1160 ad(an)=voc
1165 gosub 3470:poke voc,169
1170 poke voc+1,fn h(voc+12)
1175 poke voc+2,162
1180 poke voc+3,fn l(voc+12)
1185 poke voc+4,32:poke voc+5,42
1190 poke voc+6,192:ad=voc+12+xx
1195 poke voc+7,96
1200 poke voc+8,fn l(ad):poke voc+9,fn h(ad)
1205 poke voc+10,fn l(xx):poke voc+11,fn h(xx)
1210 voc=ad:goto 700
1220 :
1230 if be$<>"constant" then 1280
1240 gosub 2630:a$=": "+be$+" "
1250 gosub 3470
1260 ze$=a$+str$(x)+" ;"+ze$
1270 goto 700
1280 :
1290 if be$<>"clear" then 1350
1300 gosub 2630:sc=val(be$)
1310 for ze=0 to 24
1320 sc$(ze)=""
1330 next ze:gosub3220
1340 goto700
1350 :
1360 ifbe$="save-system"then3510
1365 :
1370 ifbe$="load-system"then3720
1380 :
1390 if be$<>"floppy" then 1420
1400 gosub2630
1410 open1,8,15,be$:close1:goto 700
1420 :
1430 ifbe$<>"list" then 1520
1440 gosub2630:sc=val(be$):gosub3110
1450 input"Auf Drucker (y/n)";a$:a=3:ifa$="y"thena=4
1460 open4,a,-7*(a=4)
1470 for z=0 to 23
1480 print#4,right$(str$(z),2)":"sc$(z)
1490 next z:close4
1500 ifa=3thenpoke198,0:wait198,1
1510 comp=0:goto700
1520 :
1530 printbe$" I can't find":goto 700
1533 :
1535 rem *************************
1540 rem ***     compiler      ***
1545 rem *************************
1548 :
1550 gosub2630:an=an+1:wo$(an)=be$
1560 ad(an)=voc:comp=1
1570 :
1580 gosub 2630
1590 for i=1 to anz
1600 if be$<>wo$(i) then next i
1610 ad=ad(i)
1615 :
1620 if be$<>"begin" then 1640
1630 st(sp)=voc:sp=sp+1:goto 1570
1635 :
1640 if be$<>"until" then 1730
1650 poke voc,32
1660 poke voc+1,180:poke voc+2,194
1670 poke voc+3,176:poke voc+4,3
1680 poke voc+5,76
1690 sp=sp-1:ad=st(sp):if sp<0 then65535
1700 poke voc+6,fn l(ad)
1710 poke voc+7,fn h(ad)
1720 voc=voc+8:goto 1570
1725 :
1730 if be$=";" then poke voc,96:voc=voc+1:comp=0:goto 700
1735 :
1740 gosub 3030
1750 if ok=0 then 1800
1760 poke voc,169:poke voc+1,fn h(xx)
1770 pokevoc+2,162:pokevoc+3,fn l(xx)
1780 poke voc+4,32:poke voc+5,42
1790 poke voc+6,192:voc=voc+7:goto 1570
1800 :
1810 if be$<>"if" then 1870
1820 poke voc,32:poke voc+1,180
1830 poke voc+2,194:poke voc+3,176
1840 poke voc+4,3:poke voc+5,76
1850 st(sp)=voc+6:sp=sp+1
1860 voc=voc+8:goto 1570
1870 :
1880 if be$<>"endif" then 1930
1890 sp=sp-1:ad=st(sp)
1900 poke ad,fn l(voc)
1910 poke ad+1,fn h(voc)
1920 goto 1570
1930 :
1940 if be$<>"else" then 2010
1950 ad=st(sp-1)
1960 st(sp-1)=voc+1
1970 poke voc,76:voc=voc+3
1980 poke ad,fn l(voc)
1990 poke ad+1,fn h(voc)
2000 goto 1570
2010 :
2020 if be$="while" then 1820
2030 :
2040 if be$<>"repeat" then 2110
2050 ad=st(sp-1):a2=st(sp-2)
2060 sp=sp-1
2070 poke voc,76
2080 poke voc+1,fn l(a2)
2090 poke voc+2,fn h(a2)
2100 voc=voc+3:goto 1980
2110 :
2120 if be$<>"."+chr$(34) then 2225
2125 a$="":ze$=mid$(ze$,2)
2130 if left$(ze$,1)<>chr$(34) then a$=a$+left$(ze$,1):ze$=mid$(ze$,2):goto2130
2135 ze$=mid$(ze$,2):a$=a$+chr$(0)
2140 ad=voc+10
2145 poke voc,169
2150 poke voc+1,fn h(ad)
2155 poke voc+2,162
2160 poke voc+3,fn l(ad)
2165 poke voc+4,32:poke voc+5,234
2170 poke voc+6,194:poke voc+7,76
2175 ad=voc+10+len(a$)
2180 poke voc+8,fn l(ad)
2185 poke voc+9,fn h(ad)
2190 voc=voc+10
2200 for i=0 to len(a$)-1
2205 poke voc+i,asc(mid$(a$,i+1,1))
2210 if left$(ze$,1)=" " then ze$=mid$(ze$,2):goto 2210
2215 next i
2220 voc=ad:goto 1570
2225 :
2230 if be$<>"text"+chr$(34) then2320
2235 a$="":ze$=mid$(ze$,2)
2240 if left$(ze$,1)<>chr$(34) then a$=a$+left$(ze$,1):ze$=mid$(ze$,2):goto2240
2245 ze$=mid$(ze$,2):a$=a$+chr$(0)
2250 ad=voc+10
2255 poke voc,169
2260 poke voc+1,fn h(ad)
2265 poke voc+2,162
2270 poke voc+3,fn l(ad)
2273 poke voc+4,32:poke voc+5,42:poke voc+6,192
2275 poke voc+7,76
2280 ad=voc+10+len(a$)
2285 poke voc+8,fn l(ad)
2290 poke voc+9,fn h(ad)
2295 voc=voc+10
2300 for i=0 to len(a$)-1
2305 poke voc+i,asc(mid$(a$,i+1,1)):next
2310 if left$(ze$,1)=" " then ze$=mid$(ze$,2):goto 2310
2315 voc=ad:goto 1570
2320 :
2330 if be$<>"do" then 2390
2340 poke voc,32
2350 poke voc+1,fn l(ad)
2360 poke voc+2,fn h(ad)
2370 voc=voc+3:st(sp)=voc
2380 sp=sp+1:goto 1570
2390 :
2400 if be$<>"loop" and be$<>"+loop" then 2500
2410 poke voc,32
2420 poke voc+1,fn l(ad)
2430 poke voc+2,fn h(ad)
2440 poke voc+3,176:poke voc+4,3
2450 sp=sp-1:ad=st(sp)
2460 poke voc+5,76
2470 poke voc+6,ad-256*int(ad/256)
2480 poke voc+7,int(ad/256)
2490 voc=voc+8:goto 1570
2500 :
2510 if be$<>"(" then 2540
2520 gosub 2630:if be$<>")" then 2520
2530 goto 1570
2540 :
2550 if be$=";s" then poke voc,96:voc=voc+1:goto 1570
2560 :
2570 if i>an then print be$" I can't find":comp=0:goto 700
2575 :
2580 poke voc,32
2590 poke voc+1,ad-256*int(ad/256)
2600 poke voc+2,int(ad/256)
2610 voc=voc+3:goto 1570
2615 :
2620 rem ************************
2630 rem ** hole befehl in be$ **
2635 rem ************************
2637 :
2640 if ze$="" then gosub 2750
2650 if left$(ze$,1)=" "then ze$=mid$(ze$,2):goto 2650
2660 be$="":for i=1 to len(ze$)
2670 if left$(ze$,1)=" " then 2710
2680 be$=be$+left$(ze$,1)
2690 ze$=mid$(ze$,2)
2700 next i
2710 return
2720 :
2730 rem *************************
2740 rem *** hole zeile in ze$ ***
2750 rem *************************
2755 :
2760 if block=1 then 2880
2770 if comp=0 then print"  ok."
2780 sys 42336
2790 ze$=""
2800 for z=512 to 600
2810 a=peek(z)
2820 if a=0 then 2850
2830 ze$=ze$+chr$(a)
2840 next z
2850 if left$(ze$,1)=" "then ze$=mid$(ze$,2):goto 2850
2860 if ze$="" then 2770
2870 return
2880 ze$=sc$(z1):print right$(str$(z1),2);":";ze$
2890 if len(ze$)<2 then ze$="(  )"
2900 z1=z1+1
2910 if z1=24 then block=0
2920 return
2980 :
2990 rem **************************
3000 rem **   wandele zahl um    **
3010 rem **        in xx         **
3020 rem **************************
3030 :
3040 ok=1:x=1
3050 if left$(be$,1)="-" and val(be$)<0 then be$=mid$(be$,2):x=-1:goto 3080
3060 if left$(be$,1)>="0" and left$(be$,1)<="9" then 3080
3070 ok=0:return
3080 xx=val(be$)*x
3090 if xx<0 then xx=(256*256)+xx
3100 return
3103 :
3105 rem *************************
3110 rem *****  lade screen  *****
3115 rem *************************
3118 :
3120 open1,8,15
3130 open 2,8,2,"scr"+str$(sc)+",s,r"
3140 input#1,a
3150 if a<>0 then close2:close1:for i=0to24:sc$(i)="":next i:return
3160 for ze=0 to 24:b$=""
3170 poke251,2:sys830
3180 for i=512 to 600:x=peek(i):if x then b$=b$+chr$(x):next i
3190 sc$(ze)=b$
3200 next ze
3210 close2:close1:return
3213 :
3215 rem **************************
3220 rem *****  save  screen  *****
3225 rem **************************
3228 :
3230 open 1,8,2,"@:scr"+str$(sc)+",s,w"
3240 for ze=0 to 24
3250 print#1,sc$(ze)
3260 next ze
3270 close1:ze$="":print"{clr}";:return
3273 :
3275 rem ***********************
3280 rem **** edit a screen ****
3285 rem ***********************
3288 :
3290 gosub 3400
3300 print"{home}";:comp=1
3310 gosub 2750
3315 if left$(ze$,1)="n" then gosub2630:gosub2630:sc=val(be$):gosub3420:goto3300
3320 if left$(ze$,1)="e" then ze$="":comp=0:goto 3220
3321 if left$(ze$,1)<>"i" then 3330
3322 gosub 2630:gosub 2630:z=val(be$):if z<0 or z>23 then gosub 3420:goto 3300
3323 gosub 2630:a=val(be$):if a<0 or a>23 then gosub 3420:goto 3300
3324 for i=22-a to z step-1:sc$(i+a)=sc$(i):sc$(i)="":next
3325 gosub 3420:goto 3300
3330 if left$(ze$,1)="s" then ze$="":print"{clr}";:comp=0:return
3331 if left$(ze$,1)<>"d" then 3337
3332 gosub 2630:gosub 2630:z=val(be$):if z<0 or z>23 then gosub3420:goto 3300
3333 gosub 2630:a=val(be$):if a<0 or a>23 then gosub 3420:goto 3300
3334 for i=z to 22-a:sc$(i)=sc$(i+a):sc$(i+a)="":next
3335 gosub 3420:goto 3300
3337 if left$(ze$,1)="l" then gosub 3420:goto 3300
3340 ze=val(ze$)
3350 ze$=mid$(ze$,3)
3360 if ze>9 then ze$=mid$(ze$,2)
3370 sc$(ze)=ze$
3380 gosub 2630:if be$="-->" then goto 3220
3390 goto 3310
3393 :
3395 rem *************************
3400 rem *****  list screen  *****
3405 rem *************************
3408 :
3410 gosub 3110
3420 print"{clr}";
3430 for ze=0 to 23
3440 print right$(str$(ze),2);":";
3450 print left$(sc$(ze),38)
3460 next ze:return
3463 :
3465 rem ***********************
3470 rem ** hole wert vom tos **
3475 rem ***********************
3480 ad=52992+peek(2)
3490 x=peek(ad-1)+256*peek(ad-2)
3500 poke 2,peek(2)-2:return
3503 :
3505 rem ***********************
3510 rem ***   save-system   ***
3515 rem ***********************
3518 :
3520 gosub 2630
3530 open1,8,15,"s:"+be$+".*":close1
3540 open2,8,2,be$+".voc,p,w"
3550 print#2,an:print#2,voc
3560 for ze=39 to an
3570 print#2,wo$(ze)
3580 print#2,ad(ze)
3590 next ze
3600 close 2:be$=be$+".code"
3610 poke 187,fn l(720):poke 188,fn h(720)
3620 for i=1 to len(be$)
3630 poke 719+i,asc(mid$(be$,i,1))
3640 next i:poke 183,len(be$)
3650 poke 186,8:poke 185,1
3660 poke 251,fn l(be):poke 252,fn h(be)
3670 poke 780,251
3680 poke 781,fn l(voc)
3690 poke 782,fn h(voc)
3700 sys 216+256*255
3710 goto 700
3713 :
3715 rem ***************************
3720 rem ****    load system    ****
3725 rem ***************************
3728 :
3730 gosub 2630
3740 open 2,8,2,be$+".voc,p,r"
3750 input#2,an,voc
3760 for ze=39 to an
3770 input#2,wo$(ze)
3780 input#2,ad(ze)
3790 next ze:close 2
3800 sys 50139,be$+".code",8
3810 goto 700
3813 :
3815 rem ***************************
3820 rem ***        data         ***
3825 rem ***************************
3828 :
3830 data166,251, 32,198,255,160,  0, 32,207,255,201, 13,240,  7,153,  0
3840 data  2,200, 76, 69,  3,169,  0,153,  0,  2, 76,204,255
3850 for i= 830to 858:read a:poke i,a:z=z+a:next i
3860 if z<>3379 then print"{rvon}Fehler in Data{rvof}":end
3870 return
Listing 1. Tiny-Forth-Compiler.
PROGRAMM : VOCABULARY     C006 C3EB
-----------------------------------
C006 : A9 93 4C D2 FF 20 3F C0   66
C00E : 85 62 86 63 A2 90 A5 62   DC
C016 : 30 09 A9 20 20 D2 FF 38   42
C01E : 4C D4 BD A9 2D 20 D2 FF   98
C026 : 18 4C D4 BD 85 FE 86 FD   B7
C02E : A6 02 A5 FE 9D 00 CF E8   09
C036 : A5 FD 9D 00 CF E8 86 02   A4
C03E : 60 A6 02 CA BD 00 CF 85   F1
C046 : FD CA BD 00 CF 85 FE 86   4A
C04E : 02 A5 FE A6 FD 60 4C 3F   4A
C056 : C0 20 3F C0 20 2A C0 4C   FD
C05E : 2E C0 20 3F C0 8D 00 C0   D6
C066 : 8E 01 C0 20 3F C0 8D 02   DD
C06E : C0 8E 03 C0 AD 00 C0 AE   89
C076 : 01 C0 20 2A C0 AD 02 C0   28
C07E : AE 03 C0 4C 2A C0 C6 02   2F
C086 : C6 02 20 3F C0 E6 02 E6   56
C08E : 02 E6 02 E6 02 4C 2A C0   0D
C096 : A6 FC CA BD 00 CE 85 FD   AD
C09E : CA BD 00 CE 85 FE 86 FC   85
C0A6 : A5 FE A6 FD 60 85 FE 86   6F
C0AE : FD A6 FC A5 FE 9D 00 CE   6D
C0B6 : E8 A5 FD 9D 00 CE E8 86   CB
C0BE : FC 60 38 AD 00 C0 ED 02   70
C0C6 : C0 8D 04 C0 AD 01 C0 ED   28
C0CE : 03 C0 8D 05 C0 60 18 AD   00
C0D6 : 00 C0 6D 02 C0 8D 04 C0   DC
C0DE : AD 01 C0 6D 03 C0 8D 05   60
C0E6 : C0 60 A9 0D 4C D2 FF 20   7E
C0EE : 3F C0 8E 00 C0 8D 01 C0   2F
C0F6 : 20 3F C0 8E 02 C0 8D 03   1A
C0FE : C0 4C C0 C0 20 ED C0 AD   FC
C106 : 04 C0 0D 05 C0 F0 06 A9   4D
C10E : 00 AA 4C 2A C0 A9 00 A2   5A
C116 : 01 4C 2A C0 20 ED C0 30   B5
C11E : 06 A9 00 AA 4C 2A C0 A9   BB
C126 : 00 A2 01 4C 2A C0 20 60   2B
C12E : C0 4C 1A C1 20 3F C0 05   DC
C136 : FD F0 06 A9 00 AA 4C 2A   3D
C13E : C0 A9 00 A2 01 4C 2A C0   C4
C146 : 20 3F C0 8E 00 C0 8D 01   46
C14E : C0 20 3F C0 8E 02 C0 8D   1D
C156 : 03 C0 60 20 46 C1 AD 00   FF
C15E : C0 2D 02 C0 85 FD AD 01   4E
C166 : C0 2D 03 C0 85 FE 4C 2E   74
C16E : C0 20 46 C1 AD 00 C0 0D   00
C176 : 02 C0 85 FD AD 01 C0 0D   F9
C17E : 03 C0 85 FE 4C 2E C0 20   9C
C186 : 46 C1 AD 00 C0 4D 02 C0   18
C18E : 85 FD AD 01 C0 4D 03 C0   A1
C196 : 85 FE 4C 2E C0 20 46 C1   1D
C19E : 20 D4 C0 AE 04 C0 AD 05   35
C1A6 : C0 4C 2A C0 20 60 C0 20   77
C1AE : 46 C1 20 C0 C0 AE 04 C0   08
C1B6 : AD 05 C0 4C 2A C0 20 46   55
C1BE : C1 A0 00 8C 04 C0 8C 05   E3
C1C6 : C0 A0 10 0E 04 C0 2E 05   A5
C1CE : C0 2E 02 C0 2E 03 C0 90   5D
C1D6 : 1D 18 AD 04 C0 6D 00 C0   E4
C1DE : 8D 04 C0 AD 05 C0 6D 01   61
C1E6 : C0 8D 05 C0 90 08 EE 02   CF
C1EE : C0 D0 03 EE 03 C0 88 D0   AF
C1F6 : D2 AE 04 C0 AD 05 C0 4C   D7
C1FE : 2A C0 20 46 C1 A0 10 A9   0E
C206 : 00 8D 04 C0 8D 05 C0 2E   46
C20E : 02 C0 2E 03 C0 2E 04 C0   6B
C216 : 2E 05 C0 38 AD 04 C0 ED   D8
C21E : 00 C0 AA AD 05 C0 ED 01   EF
C226 : C0 90 06 8D 05 C0 8E 04   FA
C22E : C0 88 D0 DB 2E 02 C0 2E   34
C236 : 03 C0 60 20 00 C2 AE 02   8A
C23E : C0 AD 03 C0 4C 2A C0 20   07
C246 : 00 C2 AE 04 C0 AD 05 C0   E2
C24E : 4C 2A C0 20 96 C0 4C 2A   D8
C256 : C0 20 3F C0 4C AB C0 20   74
C25E : 60 C0 20 57 C2 4C 57 C2   83
C266 : 20 51 C2 E6 FC E6 FC 60   78
C26E : 20 51 C2 20 57 C0 20 51   8A
C276 : C2 20 60 C0 20 ED C0 30   4D
C27E : 08 20 54 C0 20 54 C0 38   DC
C286 : 60 E6 FC E6 FC 20 9B C1   38
C28E : 20 57 C2 18 60 A9 00 A2   A6
C296 : 01 20 2A C0 4C 6E C2 20   CD
C29E : 3F C0 E6 02 E6 02 A5 FE   4A
C2A6 : 10 C6 20 51 C2 20 57 C0   58
C2AE : 20 51 C2 4C 7A C2 20 3F   6E
C2B6 : C0 05 FD F0 02 38 60 18   2A
C2BE : 60 20 3F C0 8A 4C D2 FF   6D
C2C6 : 20 87 EA E0 FF F0 04 E0   DA
C2CE : 0D B0 02 A2 00 A9 00 4C   EE
C2D6 : 2A C0 20 C6 C2 20 57 C0   4D
C2DE : 20 B4 C2 B0 06 20 54 C0   53
C2E6 : 4C D8 C2 60 86 FD 85 FE   C7
C2EE : A0 00 B1 FD F0 06 20 D2   20
C2F6 : FF C8 D0 F6 60 20 3F C0   F2
C2FE : 86 F7 20 3F C0 A0 00 B1   E4
C306 : FD 20 D2 FF C8 C4 F7 D0   FC
C30E : F6 60 20 3F C0 86 F9 20   8D
C316 : 3F C0 86 F7 85 F8 A2 00   00
C31E : A0 00 20 CF FF 91 F7 C9   C0
C326 : 0D F0 06 E8 C8 C4 F9 D0   86
C32E : F1 60 A5 02 4A AA A9 00   9A
C336 : 4C 2A C0 20 3F C0 86 F7   CF
C33E : 85 F8 20 3F C0 A0 01 91   68
C346 : F7 8A 88 91 F7 60 20 3F   58
C34E : C0 86 F7 85 F8 20 3F C0   0F
C356 : A0 00 8A 91 F7 60 20 3F   4D
C35E : C0 86 F7 85 F8 A0 00 B1   08
C366 : F7 AA C8 B1 F7 4C 2A C0   27
C36E : 20 3F C0 86 F7 85 F8 A0   FF
C376 : 00 B1 F7 AA A9 00 4C 2A   C2
C37E : C0 20 3F C0 AD 0C 03 AE   DB
C386 : 0D 03 AC 0E 03 6C FD 00   8D
C38E : 20 3F C0 A4 02 8C 00 C0   19
C396 : 8A 0A 85 02 20 3F C0 AC   1F
C39E : 00 C0 84 02 4C 2A C0 20   B9
C3A6 : 3F C0 8E 00 C0 8D 01 C0   E7
C3AE : 20 3F C0 8E 02 C0 8D 03   D2
C3B6 : C0 20 3F C0 8E 04 C0 8D   95
C3BE : 05 C0 AE 02 C0 AD 03 C0   16
C3C6 : 20 2A C0 AE 00 C0 AD 01   C0
C3CE : C0 20 2A C0 AE 04 C0 AD   AA
C3D6 : 05 C0 4C 2A C0 20 FD AE   F6
C3DE : 20 D4 E1 A9 01 85 B9 A9   8C
C3E6 : 00 4C D5 FF FF            51
Listing 2. Maschinenspracheteil von Forth
 ( *** Zusatz-Befehle 0 *** )


 ( Processor-Register )

 780 constant a-reg
 781 constant x-reg
 782 constant y-reg
 ( ---------------------- )

 ( Die folgenden Befehle  )

 ( sollen zeigen,dass es  )

 ( mit dem recht beschei- )

 ( denen Grundvokabular   )

 ( moeglich ist,doch ein  )

 ( sinnvolles,zweckmaess- )

 ( iges zu erstellen.     )
-->
Listing 3. Zusatz-Befehle, Screen 0
( *** zusatz-befehle 1 ***)


 (  2. Schleifenindex )

 : j
    r> r> r>
    dup 704 !
    >r >r >r
    704 @
 ;



 (  Verlasse Schleife )

 : leave
    r> r>
    drop dup
    >r >r
 ;


 -->
Listing 4. Zusatz-Befehle, Screen 1
 ( *** Zusatz-Befehle 2 *** )


 ( open (addr l log nr sec --) )

 : open
    185 c!   186 c! 184 c!
    183 c!   187 !
    65472 call
 ;



 ( close (log --) )

 : close
    cr 65484 call
    a-reg c!
    65475 call
 ;



 -->
Listing 5. Zusatz-Befehle, Screen 2
 ( *** Zusatz-Befehele 3 *** )


 ( Ausgabe auf File (log --) )

 : out
    x-reg c!
    65481 call
 ;



 ( Eingabe von File (log --) )

 : in
    x-reg c!
    65478 call
 ;





 -->
Listing 6. Zusatz-Befehle, Screen 3
 ( *** Zusatz-Befehle 4 *** )


 ( Ausgabe auf Drucker )

 : printer
    0 0 4 4 7 open
    4 out
    cr
 ;


 ( Ausgabe auf Display )

 : display
    cr
    4 close
 ;



 ( * ende * )


Listing 7. Zusatz-Befehle, Screen 4

;scr 5.prg  : mlen$
    2 - @
 ;
 : len$
    dup 1 -
    begin
      1 + dup
      c@
     0 =
    until
    swap -
 ;
 : input$
    dup dup mlen$
    ." :" expect
    1 -
    begin
      1 + dup c@
     13 =
    until
    0 swap c! drop
 ;
 : print$ dup len$ type ;


40 open1,8,15,"s:forth.voc":close1
50 open1,8,1,"forth.voc"
60 :
70 :
100 :           sys  9*4096
105 :           .opt oo
110 stack         =  $cf00
115 retstack      =  $ce00
120 pos           =  $0002
122 retpos        =  $00fc
125 l             =  $00fd
130 h             =  $00fe
135 hl            =  $00fd
140 print         =  $ffd2
145 :            *=  $c000
146 reg1         *=  *+2
147 reg2         *=  *+2
148 reg3         *=  *+2
150 ;----------------------
155 cls         lda  #"{clr}"
160 :           jmp  print
165 ;----------------------
170 show        jsr  pop
175 :           sta  $62
180 :           stx  $63
185 :           ldx  #$90
190 :           lda  $62
195 :           bmi  minus
200 plus        lda  #" "
205 :           jsr  print
210 :           sec
215 :           jmp  $bdd4
220 minus       lda  #"-"
225 :           jsr  print
230 :           clc
235 :           jmp  $bdd4
240 ;----------------------
245 push        sta  h
250 :           stx  l
255 push1       ldx  pos
260 :           lda  h
265 :           sta  stack,x
270 :           inx
275 :           lda  l
280 :           sta  stack,x
285 :           inx
290 :           stx  pos
295 :           rts
300 ;----------------------
305 pop         ldx  pos
310 :           dex
315 :           lda  stack,x
320 :           sta  l
325 :           dex
330 :           lda  stack,x
335 :           sta  h
340 :           stx  pos
345 :           lda  h
350 :           ldx  l
355 :           rts
360 ;----------------------
365 drop        jmp  pop
370 ;----------------------
375 dup         jsr  pop
380 :           jsr  push
385 :           jmp  push1
390 ;----------------------
395 swap        jsr  pop
400 :           sta  reg1
405 :           stx  reg1+1
410 :           jsr  pop
415 :           sta  reg2
420 :           stx  reg2+1
425 :           lda  reg1
430 :           ldx  reg1+1
435 :           jsr  push
440 :           lda  reg2
445 :           ldx  reg2+1
450 :           jmp  push
455 ;----------------------
460 over        dec  pos
465 :           dec  pos
470 :           jsr  pop
475 :           inc  pos
480 :           inc  pos
485 :           inc  pos
490 :           inc  pos
495 :           jmp  push
500 ;----------------------
505 retpop      ldx  retpos
510 :           dex
515 :           lda  retstack,x
520 :           sta  l
525 :           dex
530 :           lda  retstack,x
535 :           sta  h
540 :           stx  retpos
545 :           lda  h
550 :           ldx  l
555 :           rts
560 ;----------------------
565 retpush     sta  h
570 :           stx  l
575 retpush1    ldx  retpos
580 :           lda  h
585 :           sta  retstack,x
590 :           inx
595 :           lda  l
600 :           sta  retstack,x
605 :           inx
610 :           stx  retpos
615 :           rts
620 ;-----------------------
625 subtraktion sec
630 :           lda  reg1
635 :           sbc  reg2
640 :           sta  reg3
645 :           lda  reg1+1
650 :           sbc  reg2+1
655 :           sta  reg3+1
660 :           rts
665 ;-----------------------
670 addition    clc
675 :           lda  reg1
680 :           adc  reg2
685 :           sta  reg3
690 :           lda  reg1+1
695 :           adc  reg2+1
700 :           sta  reg3+1
705 :           rts
710 ;-----------------------
715 cr          lda  #13
720 :           jmp  print
725 ;-----------------------
730 vergleich   jsr  pop
735 :           stx  reg1
740 :           sta  reg1+1
745 :           jsr  pop
750 :           stx  reg2
755 :           sta  reg2+1
760 :           jmp  subtraktion
765 ;-----------------------
770 gleich      jsr  vergleich
771 :           lda  reg3
772 :           ora  reg3+1
775 :           beq  wahr1
780 falsch1     lda  #0
785 :           tax
790 :           jmp  push
795 wahr1       lda  #0
800 :           ldx  #1
805 :           jmp  push
810 ;-----------------------
815 groesser    jsr  vergleich
820 :           bcc  wahr2
825 falsch2     lda  #0
830 :           tax
835 :           jmp  push
840 wahr2       lda  #0
845 :           ldx  #1
850 :           jmp  push
855 ;-----------------------
860 kleiner     jsr  swap
865 :           jmp  groesser
870 ;-----------------------
875 nicht       jsr  pop
880 :           ora  l
885 :           beq  wahr3
890 falsch3     lda  #0
895 :           tax
900 :           jmp  push
905 wahr3       lda  #0
910 :           ldx  #1
915 :           jmp  push
920 ;-----------------------
925 hole        jsr  pop
930 :           stx  reg1
935 :           sta  reg1+1
940 :           jsr  pop
945 :           stx  reg2
950 :           sta  reg2+1
955 :           rts
960 ;-----------------------
965 und         jsr  hole
970 :           lda  reg1
975 :           and  reg2
980 :           sta  l
985 :           lda  reg1+1
990 :           and  reg2+1
995 :           sta  h
1000 :           jmp  push1
1005 ;-----------------------
1010 oder        jsr  hole
1015 :           lda  reg1
1020 :           ora  reg2
1025 :           sta  l
1030 :           lda  reg1+1
1035 :           ora  reg2+1
1040 :           sta  h
1045 :           jmp  push1
1050 ;-----------------------
1055 exoder      jsr  hole
1060 :           lda  reg1
1065 :           eor  reg2
1070 :           sta  l
1075 :           lda  reg1+1
1080 :           eor  reg2+1
1085 :           sta  h
1090 :           jmp  push1
1095 ;-----------------------
1100 add         jsr  hole
1105 :           jsr  addition
1110 :           ldx  reg3
1115 :           lda  reg3+1
1120 :           jmp  push
1125 ;-----------------------
1130 sub         jsr  swap
1135 :           jsr  hole
1140 :           jsr  subtraktion
1145 :           ldx  reg3
1150 :           lda  reg3+1
1155 :           jmp  push
1160 ;-----------------------
1165 mul         jsr  hole
1170 :           ldy  #0
1175 :           sty  reg3
1180 :           sty  reg3+1
1185 :           ldy  #16
1190 loop16      asl  reg3
1195 :           rol  reg3+1
1200 :           rol  reg2
1205 :           rol  reg2+1
1210 :           bcc  lab2
1215 :           clc
1220 :           lda  reg3
1225 :           adc  reg1
1230 :           sta  reg3
1235 :           lda  reg3+1
1240 :           adc  reg1+1
1245 :           sta  reg3+1
1250 :           bcc  lab2
1255 :           inc  reg2
1260 :           bne  lab2
1265 :           inc  reg2+1
1270 lab2        dey
1275 :           bne  loop16
1280 :           ldx  reg3
1285 :           lda  reg3+1
1290 :           jmp  push
1295 ;-----------------------
1300 division    jsr  hole
1305 :           ldy  #16
1310 :           lda  #0
1315 :           sta  reg3
1320 :           sta  reg3+1
1325 loop17      rol  reg2
1330 :           rol  reg2+1
1335 :           rol  reg3
1340 :           rol  reg3+1
1345 :           sec
1350 :           lda  reg3
1355 :           sbc  reg1
1360 :           tax
1365 :           lda  reg3+1
1370 :           sbc  reg1+1
1375 :           bcc  lab4
1380 :           sta  reg3+1
1385 :           stx  reg3
1390 lab4        dey
1395 :           bne  loop17
1400 :           rol  reg2
1405 :           rol  reg2+1
1410 :           rts
1415 ;-----------------------
1420 div         jsr  division
1425 :           ldx  reg2
1430 :           lda  reg2+1
1435 :           jmp  push
1440 ;-----------------------
1445 mod         jsr  division
1450 :           ldx  reg3
1455 :           lda  reg3+1
1460 :           jmp  push
1465 ;-----------------------
1470 trs         jsr  retpop
1475 :           jmp  push
1480 ;-----------------------
1485 tsr         jsr  pop
1490 :           jmp  retpush
1495 ;-----------------------
1500 do          jsr  swap
1505 :           jsr  tsr
1510 :           jmp  tsr
1515 ;-----------------------
1520 ind         jsr  trs
1525 :           inc  retpos
1530 :           inc  retpos
1535 :           rts
1540 ;-----------------------
1545 loop1       jsr  trs
1550 :           jsr  dup
1555 :           jsr  trs
1560 :           jsr  swap
1565 vergl       jsr  vergleich
1570 :           bcc  wahr4
1571 falsch4     jsr  drop
1575 :           jsr  drop
1579 :           sec
1580 :           rts
1585 wahr4       inc  retpos
1590 :           inc  retpos
1595 :           jsr  add
1600 :           jsr  tsr
1605 :           clc
1610 :           rts
1615 ;-----------------------
1620 loop        lda  #0
1625 :           ldx  #1
1630 :           jsr  push
1635 :           jmp  loop1
1640 ;-----------------------
1645 loopplus    jsr  pop
1650 :           inc  pos
1655 :           inc  pos
1660 :           lda  h
1665 :           bpl  loop1
1670 :           jsr  trs
1675 :           jsr  dup
1680 :           jsr  trs
1685 :           jmp  vergl
1690 ;-----------------------
1695 if          jsr  pop
1700 :           ora  l
1705 :           beq  nein
1710 ja          sec
1715 :           rts
1720 nein        clc
1725 :           rts
1730 ;-----------------------
1735 emit        jsr  pop
1740 :           txa
1745 :           jmp  print
1750 ;-----------------------
1755 get         jsr  $ea87
1760 :           cpx  #255
1765 :           beq  null
1766 :           cpx  #13
1767 :           bcs  nonull
1770 null        ldx  #$00
1775 nonull      lda  #$00
1780 :           jmp  push
1785 ;-----------------------
1790 key         jsr  get
1795 :           jsr  dup
1800 :           jsr  if
1805 :           bcs  next5
1810 :           jsr  drop
1815 :           jmp  key
1820 next5       rts
1825 ;-----------------------
1830 putzeile    stx  l
1835 :           sta  h
1840 :           ldy  #0
1845 loopput     lda  (hl),y
1850 :           beq  endput
1855 :           jsr  print
1860 :           iny
1865 :           bne  loopput
1870 endput      rts
1875 ;-----------------------
1880 type        jsr  pop
1885 :           stx  $f7
1890 :           jsr  pop
1895 :           ldy  #0
1900 looptype    lda  (hl),y
1905 :           jsr  print
1910 :           iny
1915 :           cpy  $f7
1920 :           bne  looptype
1925 :           rts
1930 ;-----------------------
1935 expect      jsr  pop
1940 :           stx  $f9
1945 :           jsr  pop
1950 :           stx  $f7
1955 :           sta  $f8
1960 :           ldx  #0
1965 :           ldy  #0
1970 loopex      jsr  $ffcf
1975 :           sta  ($f7),y
1980 :           cmp  #13
1985 :           beq  endex
1990 :           inx
1995 :           iny
2000 :           cpy  $f9
2005 :           bne  loopex
2010 endex       rts
2015 ;-----------------------
2020 depth       lda  pos
2025 :           lsr  a
2030 :           tax
2035 :           lda  #0
2040 :           jmp  push
2045 ;-----------------------
2050 dpoke       jsr  pop
2055 :           stx  $f7
2060 :           sta  $f8
2065 :           jsr  pop
2070 :           ldy  #1
2075 :           sta  ($f7),y
2080 :           txa
2085 :           dey
2090 :           sta  ($f7),y
2095 :           rts
2100 ;----------------------
2105 poke        jsr  pop
2110 :           stx  $f7
2115 :           sta  $f8
2120 :           jsr  pop
2125 :           ldy  #0
2130 :           txa
2135 :           sta  ($f7),y
2140 :           rts
2145 ;----------------------
2150 dpeek       jsr  pop
2155 :           stx  $f7
2160 :           sta  $f8
2165 :           ldy  #0
2170 :           lda  ($f7),y
2175 :           tax
2180 :           iny
2185 :           lda  ($f7),y
2190 :           jmp  push
2195 ;----------------------
2200 peek        jsr  pop
2205 :           stx  $f7
2210 :           sta  $f8
2215 :           ldy  #0
2220 :           lda  ($f7),y
2225 :           tax
2230 :           lda  #0
2235 :           jmp  push
2240 ;----------------------
2245 call        jsr  pop
2246 :           lda  780
2247 :           ldx  781
2248 :           ldy  782
2250 :           jmp  (hl)
2255 ;----------------------
2260 pick        jsr  pop
2265 :           ldy  pos
2270 :           sty  reg1
2275 :           txa
2280 :           asl  a
2285 :           sta  pos
2290 :           jsr  pop
2300 :           ldy  reg1
2305 :           sty  pos
2312 :           jmp  push
2313 ;----------------------
2315 rot         jsr  pop
2320 :           stx  reg1
2325 :           sta  reg1+1
2330 :           jsr  pop
2335 :           stx  reg2
2340 :           sta  reg2+1
2345 :           jsr  pop
2350 :           stx  reg3
2355 :           sta  reg3+1
2360 :           ldx  reg2
2365 :           lda  reg2+1
2370 :           jsr  push
2375 :           ldx  reg1
2380 :           lda  reg1+1
2385 :           jsr  push
2390 :           ldx  reg3
2395 :           lda  reg3+1
2400 :           jmp  push
2405 ;----------------------
2410 load        jsr  $aefd
2415 :           jsr  $e1d4
2420 :           lda  #1
2425 :           sta  $b9
2430 :           lda  #0
2435 :           jmp  $ffd5
2440 ;----------------------
9600 :           .sst 8,2,"@:label,s,w"
9610 :           .end
vocabulary.sorce
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →