VolksForth/doc/msdos/vf-msdos-381-manual-de.sidecar.txt

13105 lines
348 KiB
Plaintext
Raw Normal View History

FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Handbuch zum PC-volksFORTH83 rev. 3.81
Die Autoren haben sich in diesem Handbuch um eine vollständige und akkurate
Darstellung bemüht. Die im Handbuch enthaltenen Informationen dienen jedoch
allein der Produktbeschreibung und sind nicht als zugesicherte Eigenschaften im
Rechtssinne aufzufassen. Etwaige Schadensersatzansprüche gegen die Autoren gleich
aus welchem Rechtsgrund, sind ausgeschlossen. Es wird keine Gewähr übernommen,
daß die angegebenen Verfahren frei von Schutzrechten Dritter sind.
Alle Rechte vorbehalten. Ein Nachdruck, auch auszugsweise, ist nur zulässig mit
Einwilligung der Autoren und genauer Quellenangabe sowie Einsendung eines Beleg-
exemplars an die Autoren.
(c) 1985,1986 Bernd Pennemann, Georg Rehfeld, Dietrich Weineck
(c) 1988,1989 Klaus Schleisiek, Jörg Staben, Klaus Kohl
- Mitglieder der FORTH Gesellschaft e.V. -
Unser Dank gilt der gesamten FORTH-Gemeinschaft,
insbesondere Charles Moore, Michael Perry und Henry Laxen
1. Auflage Mai 1989
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Inhaltsverzeichnis
1.1 Interpreter und Compiler
1.2 Warum stellen wir dieses System frei zur Verfügung ?rereeeeneenesnsnnenesennnnnennnen 9
1.3 Warum soll man in volksFORTH83 programmieren ?
1.4 Hinweise des Lektors
2.„Einstieg ins. VOIRSKORTHL........0042 200200 deennn sans aan em ene ee anne sense Tnngt oe speed Reaasen 12
2E1 3DIEISVSTEMAISKELDE eur veransen kann scene nase rerre en ersatz ana Fiese sera este 12
22 "DIE. Oberflächerens. aussen nenn urn ee Mengen ae rear 14
2.3 Arbeiten mit Programm- und Datenfiles........csessesensensensunsnnnnnennnnnnnnnnnnsnnenen 15
2.4 Der Editor
2.4.3 Tastenbelegung. des. BAItORS ....0rsccauocnnenunenc Aifeihnen reset er haree hecharnsen
32:4,4 BEISDIEISOES)..veeneaseeee sone anessennaareneshannesu taten ne ee
2:4,5 Compilieren im. Editor. ciesseressunnene re Tree ee
2.5 Erstellen einer Applikation ......eeessseeenneenennene Se.
2.6 Das Erstellen eines eigenen FORTH-Systems ...e.eenseneneennennsnnnnnensennnnnnnensnnsnnen
257 Ausdrucken VON SCIHEENS!esnuerucnenueasernaenennn scene ET FE nee
2.8 Druckeranpassung ....nennenncen: Re ET ER E 26
3.2 Arithmetische Funktionen ... 5
3:3 Logik-und Vergleiche... une te er ee ee
9.4, 92Bit=Wörtenesensssessunnassnens een een hear are Tele ran Hebandsae Türe tEr ea ige
3.5 Stack-Operationen ....unseneeeeeener Ar
8:8.1,2Datenstack=0peratlonen .......crenseneennenanenenenen en ee
3.5.2 Returnstack-Operationen
4. Kontrollstrukturen
4.1 Programm-Strukturen .............
4.2 Worte zur Fehlerbehandlung
4.3, Eallunterscheidung.inRORTH. u. MEER ee ,
4.3.1. Strukturierung mit IE ELSE - THENY/#ENDIEN....Aelenernssneoensensnoenenee 47
4.9.2. Behandlung einer. CASE --Sittuatlonmeimi.M.. Tee ersetehee hend leben 5ß
4.3,2.1.Strukturelles. CASE... EEE NTR A EEEN es 50
4.3:2.27Bositionelles-CASE rn. ve ee ee Ale 54
4,.3,2.3 Bingatzmöglichkelten ungen en nsnrk 57
AFASREKULSTONL. 2 0naceunn ser seen ee ae Tee rn Ehe alone nenne een nen nie ne none een 59
Inhaltsverzeichnis Zn 2]
FORTH-G
esellschaft e.V. PC-volksFORTH83 rev. 3.81
5. Ein / Ausgabe im. VoOlkSEORTH. auneean
5.1
5.2
5.3
5.4
5.5
5.6
5.7
Ein- / Ausgabebefehle im volksFORTH
Ein» / Ausgaben über Ternmina) een
Drucker-Ausgaben ..............-
Ein- / Ausgabe von Zahlen
Bin= / Ausgabe über einen Port au — 67
Eingabe von Zeichen...
Ausgabe von Zeichen... neu nenn en
6: Strings ne een
6.1
6.2
6.3
6.4
7. Umgan
7.1
UR
7.3
7.4
7.5
7.6
7.7
7.8
7.9
8. Speich
81
8.2
BERIRE EIS TIER nen eat een
Suche nach Strings .....
6.2.1 In normalem Fließtext
8:2.2, IN DIensonar
®-terminated Strings ....enererensnensnnnnensnnnnnnenensnnnnnnsnnsnsensenenssntnonssssnsunsnssenrnenne
Konyvertlerungen: Strings -—— Zahlen eo ann 8
6.4.1 String in Zahlen wandeln... ni
64.2 Zahlen. in Strineswandeln a... Dane
e mit Datelen au ara neun kan Kuss
Pfad-Unterstützung „een teen es nee era thehi ee tnnture
DOS-Befehle
Block-orientierte Dateien
Verwaltung: der-Block=Puffer.. u... 0 dene aan 97
Index-, Verschiebe- und Kopierfunktionen für Block-Files ........cnereen 99
PEBsörlentierte Dateien. run una RT es erele
HANDLE-orientierte Dateien .... 2
Direkt=Zugriff uf Diskatien an
Eehlerbenandlunge..eerssien era ans een ee
eroperationen...nn anni est ehe ranlasi rasieren 187
Speicheroperationen im 16-Bit-Adressraum.... i
Segmentierte :Speicheröperatlonen seinen un ı1l
9. Datentypen ame u urn 113
9.1
9.2
Ein- ünd.zweidimensionale; Belder.. „tn nenne 118
Methoden der objektorientierte Programmierung ......eresenessesseeeneneenennnensnn en 121
18. Manipulieren des Systemverhalten..................zuscsssssesssnonensesnenenennennneenensnenennenanee
19.1
10.2
19.3
19.4
18.5
10.6
Pätchen von EORTH-Befehlen....... Minen sn
Verwendung von DEFER-Wörtern u
Neudefinition von. Befehlen... Anke ARE nase
Vektoren im volksFORTH83 . ar
GIOSSAT nannten nen ee een Ersenenshainelleneiee
Inhaltsverzeichnis
FORTH-Gesellschaft e.V, PC-volksFORTH83 rev. 3.81
11-2Vokabular=Struktüf .....cssnessconcsen nenn ars a rennen nahen anne de
11.1 Die Suchreihenfolge
11.2 Glossar
12. Dietionary-Strüktür .....uesseesonsswsanesesneenn een nun nern Irre ann engen dee TRERBE RER Bnsnanene nen 136
12.1 AUfdau cn nn nee ee rin Tee EEE 136
12.2 OS. una een a er 1408
13.,Der_ HRAP...... u. ceneswasnussnnssiensesscsiassreegteg age enssgnna sera get eeee sinne 144
14. Die Ausführung von FORTH-Worten.i......0..00.0-s00220sreBeeraesse sonne sneenasssnessaennessssen nen 146
14.1 Der. Aufbau des Adressinterprneters.........ernsenenenesanaseesnenitennnte nennen 146
14.2 Die Funktion des Adressinterpreters ....reeesesenssenenennenensnnnnnsnnnnnnnennnunsn sun nee 146
14,3. VEerBchiadene IMMEINATE = WOLTE enteo ing se rnen een serehre na sn unernene 148
14454. DieDoes>=struktun. an ersten ee Er erunnenessesantineerennnonenenens 149
14.5 Glossar
15. Der Assembler
VENIMReEISTErDEICRUN GM een erg ennenee teens
15.2 Registeroperationen
15.3 Besonderheiten im volksFORTH83
TOTANGIOSSATIN N nee ee ee EEE ent lenscnses arattene
15.5 Kontrollstrukturen im Assembler
15.6 Beispiele aus dem VolKSFORTH..........2022ecrs0ueonnnnenansseenesssnesenennsnersenundanennnne
16. DerXMultitasker. .............. nen ee area nun dee een tens teuer here 165
16.1 Implementatlon. er. ne en een meer iginennanenenn nee 166
236.2.Semaphore UNd-LOcCK"....:. 6 EEE anne 167
16.3 Glossar
17..Debugging-Töchniken... .zaszeseeszessessuscsugassnsssenganngssanessehea teren keikderkennesannen 174
IKUNMDER BRACH euere ne nannten nein nee ere een 174
17.2 Debüp... 2 IE RE N ee LITT 178
172.2>16Beispiel:!" EXAMPEE.2n.. MIR a ee ent: 178
17.2.2 NEST und UNNEST
17:37Stacksichemneilll....... uses se ea een
17.4 Aufrufgeschichte
IT DU en nn en ER NIRERETTETE
17.6 Dekompiler
17.7 Glossar
118., BEPTITKE..... ncenseeeeuge need seen a aan ea renne no gene nee innen abe enernsen nee ee
18.1 Entscheidungskriterien
18.2 Definition der Begriffe
Indexverzeichnis
Inhaltsverzeichnis = Su
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
1. Prolog
volksFORTH83 ist eine Sprache, die in verschiedener Hinsicht ungewöhnlich ist.
Denn FORTH selbst ist nicht nur eine Sprache, sondern ein im Prinzip grenzenloses
Programmiersystem. Eines der Hauptmerkmale des Programmiersystems FORTH ist
seine Modularität. Diese Modularität wird durch die kleinste Einheit eines FORTH-
Systems, das WORT, gewährleistet.
In FORTH werden die Begriffe Prozedur, Routine, Programm, Definition und Befehl
alle gleichbedeutend mit Wort gebraucht. FORTH besteht also, wie jede andere na-
türliche Sprache auch, aus Wörtern.
Diese FORTH-Worte kann man als bereits kompilierte Module betrachten, wobei
immer ein Kern aus einigen hundert Worten durch eigene Worte erweitert wird.
Diese Worte des Kerns sind in einem FORTH83-Standard festgelegt und stellen
sicher, daß Standard-Programme ohne Änderungen auf dem jeweiligen FORTH-System
lauffähig sind. -
Ungewöhnlich ist, daß der Programmtext des Kerns selbst ein FORTH-Programm ist,
im Gegensatz zu anderen Programmiersprachen, denen ein Maschinensprach-Pro-
gramm zugrunde liegt. Aus diesem Kern wird durch ein besonderes FORTH-Programm,
den MetaCompiler, das lauffähige KERNEL.COM erzeugt:
MetaCompiler
| Kernel.scr ===) | Kernel.com
Wie fügt man nun diesem lauffähigen Kern eigene Worte hinzu?
Das Kompilieren der Worte wird in FORTH mit COLON ":" eingeleitet und mit
SEMICOLON ";" abgeschlossen:
erwartet bei der Ausführung einen Namen und ordnet diesem Namen
alle nachfolgenden Wörter zu.
beendet diese Zuweisung von Wörtern an den Namen und stellt das
neue Wort unter diesem Namen für Aufrufe bereit.
1.1 Interpreter und Compiler
Ein klassisches FORTH-System stellt immer sowohl einen Interpreter als auch einen
Compiler zur Verfügung. Nach der Einschaltmeldung oder einem Druck auf die <CR>-
Taste wartet der FORTH-Interpreter mit dem FORTH-typischen "ok" auf Ihre Ein-
rm Prolog
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
gabe. Sie können ein oder mehrere Befehlswörter in eine Zeile schreiben. volks-
FORTH beginnt erst nach einem Druck auf die RETURN-Taste <CR> mit seiner Ar-
beit, indem es der Reihe nach jeden Befehl in der Eingabezeile abarbeitet. Dabei
werden Befehlsworte durch Leerzeichen begrenzt. Der Delimiter (Begrenzer) für
FORTH-Prozeduren ist also das Leerzeichen, womit auch schon die Syntax der
Sprache FORTH beschrieben wäre.
Der Compiler eines FORTH-Systems ist also Teil der Interpreteroberfläche. Es gibt
daher keinen Compiler-Lauf zur Erstellen des Programmtextes wie in anderen Com-
piler-Sprachen, sondern der Interpreter wird mit allen zur Problemlösung notwen-
digen Worten als Anwenderprogramm abgespeichert.
Auch : (COLON) und ; (SEMICOLON) sind kompilierte Worte, die aber für das Sys-
tem den Compiler ein- und ausschalten. Da sogar die Worte, die den Compiler
steuern, "normale" FORTH-Worte sind, fehlen in FORTH die in anderen Sprachen
üblichen Compiler-Optionen oder Compiler-Schalter. Der FORTH-Compiler wird mit
FORTH-Worten gesteuert.
Der Aufruf eines FORTH-Wortes erfolgt über seinen Namen ohne ein explizites CALL
oder GOSUB. Dies führt zum FORTH-typischen Aussehen der Wortdefinitionen:
: <name)
<wort1) <wort2) <wort3) ... ;
Die Standard-Systemantwort in FORTH ist das berühmte "ok". Ein Anforderungszei-
chen wie 'A>' bei DOS oder ']' beim guten APPLE II gibt es nicht! Das kann dazu
führen, daß nach einer erfolgreichen Aktion der Bildschirm völlig leer bleibt; getreu
der Devise:
Keine Nachrichten sind immer gute Nachrichten !
Und - ungewöhnlicherweise - benutzt FORTH die sogenannte Postfix notation (UPN)
vergleichbar den HP-Taschenrechnern, die in machen Kreisen sehr beliebt sind. Das
bedeutet, FORTH erwartet immer erst die Argumente, dann die Aktion. Statt
3+2 und (5 +5) * 10
heißt es 23% und 9537719 %
Da die Ausdrücke von links nach rechts ausgewertet werden, gibt es in FORTH
keine Klammern.
Stack
Ebenso ungewöhnlich ist, daß FORTH nur ausdrücklich angeforderte Aktionen aus-
führt: Das Ergebnis Ihrer Berechnungen bleibt solange in einem speziellen Spei-
cherbereich, dem Stack, bis es mit einem Ausgabebefehl (meist . ) auf den Bild-
schirm oder dem Drucker ausgegeben wird.
Da die FORTH-Worte den Unterprogrammen und Funktionen anderer Programmier-
sprachen entsprechen, benötigen sie gleichfalls die Möglichkeit, Daten zur Verar-
beitung zu übernehmen und das Ergebnis abzulegen. Diese Funktion übernimmt der
Prolog = 70
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
STACK. In FORTH werden Parameter für Prozeduren selten in Variablen abgelegt,
sondern meist über den Stack übergeben.
Assembler
Innerhalb einer FORTH-Umgebung kann man sofort in der Maschinensprache des
Prozessors programmieren, ohne den Interpreter verlassen zu müssen. Assembler-
Definitionen sind den FORTH-Programmen gleichwertige FORTH-Worte.
Vokabular-Konzept
Das volksFORTH verfügt über eine erweiterte Vokabular-Struktur, die von W. Rags-
dale vorgeschlagen wurde. Dieses Vokabular-Konzept erlaubt das Einordnen der
FORTH-Worte in logische Gruppen.
Damit können Sie notwendige Befehle bei Bedarf zuschalten und nach Gebrauch
wieder wegschalten. Darüberhinaus ermöglichen die Vokabulare den Gebrauch glei-
cher Namen für verschiedene Worte, ohne in einen Namenskonflikt zu kommen. Eine
im Ansatz ähnliche Vorgehensweise bietet das UNIT-Konzept moderner PASCAL-
oder MODULA-Compiler.
FORTH-Dateien
FORTH verwendet oftmals besondere Dateien für seine Programme. Dies ist his-
torisch begründet und das Erbe einer Zeit, als FORTH noch sehr oft Aufgaben des
Betriebssystems übernahm. Da gab es ausschließlich FORTH-Systeme, die den
Massenspeicher vollständig selbst ohne ein DOS verwalteten und dafür ihre eigenen
Dateistrukturen benutzten.
Diese Dateien sind sogenannte Blockfiles und bestehen aus einer Aneinanderreihung
von 1824 Byte großen Blöcken. Ein solcher Block, der gerne SCREEN genannt wird,
ist die Grundlage der Quelltext-Bearbeitung in FORTH.
Allerdings können mit dem volks4TH auch Dateien bearbeitet werden, die im Datei-
format des MS-DOS vorliegen, sog. "Stream Files".
Generell steht hinter jeder Sprache ein bestimmtes Konzept, und nur mit Kenntnis
dieses Konzeptes ist möglich, eine Sprache effizient einzusetzen. Das Sprachkonzept
von FORTH wird beschrieben in dem Buch "In FORTH denken" von Leo Brodie
(Hanser Verlag).
Einen ersten Eindruck vom volksFORTH83 und von unserem Stolz darüber soll
dieser Prolog vermitteln. volksFORTH83 ist ein "Public-Domain"-System, bei dessen
Leistungsfähigkeit sich die Frage stellt:
- 4 Prolog
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
1.2 Warum stellen wir dieses System frei zur Verfügung ?
Die Verbreitung, die die Sprache FORTH gefunden hat, war wesentlich an. die
Existenz von figFORTH geknüpft. Auch figFORTH ist ein public domain Programm,
d.h. es darf weitergegeben und kopiert werden. Trotzdem haben sich bedauerlicher-
weise verschiedene Anbieter die einfache Adaption des figFORTH an verschiedene
Rechner sehr teuer bezahlen lassen.
Das im Jahr 1979 erschienene figFORTH ist heute nicht mehr so aktuell, weil mit
der weiteren Verbreitung von Forth eine Fülle von eleganten Konzepten entstanden
sind, die z.T. in den Forth83-Standard Eingang gefunden haben. Daraufhin wurde
von Laxen und Perry das F83 geschrieben und als Public Domain verbreitet. Dieses
freie 83er-Standard-FORTH mit seinen zahlreichen Utilities ist recht komplex und
wird auch nicht mit Handbuch geliefert.
Wir haben ein neues Forth für verschiedene Rechner entwickelt. Das Ergebnis ist
das volksFORTH83, eines der besten Forth-Systeme, die es gibt. Das volksFORTH
soll an die Tradition der oben genannten Systeme, insbesondere des F83, anknüpfen
und die Verbreitung der Sprache FORTH fördern.
volksFORTH wurde unter dem Namen ultraFORTH zunächst für den C64 geschrieben.
Nach Erscheinen der Rechner der Atari ST-Serie entschlossen wir uns, auch für sie
ein volksFORTH83 zu entwickeln. Die erste ausgelieferte Version 3.7 war, was
Editor und Massenspeicher betraf, noch stark an den C64 angelehnt. Sie enthielt
jedoch schon einen verbesserten Tracer, die GEM-Bibliothek und die anderen Tools
für den ST. Der nächste Schritt bestand in der Einbindung der Betriebssystem-
Files. Nun konnten Quelltexte auch vom Desktop und mit anderen Utilities verar-
beitet werden. Die dritte Adaption des volksFORTH entstand für die CP/M-Rechner
(80880-Prozessoren), wobei speziell für den Schneider CPC auch die Grafikfähigkeit
unterstützt wird. Zuletzt wurde das volksFORTH für die weitverbreiteten Rechner
der IBM PC-Serie angepaßt. Mit der jetzt ausgelieferten Version 3.81 ist das
volksFORTH vollständig.
1.3 Warum soll man in volksFORTH83 programmieren ?
Das volksFORTH83 ist ein ausgesprochen leistungsfähiges und kompaktes Werkzeug.
Durch residente Runtime-library, Compiler, Editor und Debugger sind die ermüden-
den ECLG-Zyklen ("Edit, Compile, Link and Go") überflüssig. Der Code wird Modul
für Modul entwickelt, kompiliert und getestet.
Der integrierte Debugger ist die perfekte Testumgebung für Worte. Es gibt keine
riesigen Hexdumps oder Assemblerlistings, die kaum Ähnlichkeit mit dem Quelltext
haben.
Ein anderer wichtiger Aspekt ist das Multitasking. So wie man ein Programm in
einzelne, unabhängige Module oder Worte aufteilt, so sollte man es auch in ein-
Prolog 9
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
zelne, unabhängige Prozesse aufteilen können. Das ist in den meisten Sprachen
nicht möglich. Das volksFORTH83 besitzt einen einfachen, aber leistungsfähigen
Multitasker.
Schließlich besitzt das volksFORTH83 noch eine Fülle von Details, über die andere
FORTH-Systeme nicht verfügen:
aa Es benutzt an vielen Stellen Vektoren und sog. deferred Worte, die
eine einfache Umgestaltung des Systems für verschiedene Gerätekon-
figurationen ermöglichen.
Es besitzt einen Heap für "namenlose" Worte oder für Code, der nur
zeitweilig benötigt wird.
- Der Blockmechanismus ist so schnell, daß er auch sinnvoll für die
Bearbeitung großer Datenmengen, die in Files vorliegen, eingesetzt
werden kann.
= Das System umfaßt Tracer, Decompiler, Multitasker, Assembler,
Editor, Printer-interface ...
Das volksFORTH83 erzeugt, verglichen mit anderen FORTH-Systemen, relativ
schnellen Code, der aber langsamer als der anderer Compilersprachen ist.
Mit diesem Handbuch soll die Unterstützung des volksFORTH83 noch nicht Zuende
sein. Die FORTH Gesellschaft e.V., ein gemeinnütziger Verein, bietet dafür die
Plattform. Sie gibt die Vereins-FORTH-Zeitschrift "VIERTE DIMENSION" heraus und
betreibt den FORTH-Tree, eine ungewöhnliche, aber sehr leistungsfähige Mailbox.
Die im Frühsommer 1989 aktuelle Adressen:
FORTH-Büro:
FORTH Gesellschaft e.V.
Postfach 1116
8944 Unterschleißheim
Tel. 0889/3173784
volksFORTH-Vertrieb:
Michael & Klaus Kohl
Pestalozzistr. 69
8985 Mering
Tel. 88233/30524
-10 - Prolog
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
1.4 Hinweise des Lektors
Diesem Handbuch zum PC-volksFORTH83 ist sowohl als Nachschlagewerk als auch
als Lehrbuch für FORTH (speziell volksFORTH) gedacht. Deshalb handelt es sich
nicht, wie bei den anderen volksFORTH-Handbücher, um eine Auflistung des Voka-
bulars. Statt dessen wird mit ausführlichen Beschreibungen und Programmbeispielen
in vielen Kapiteln die Möglichkeiten des FORTH-Systems erklärt. Ergänzt werden
die einzelnen Kapitel jeweils um Wortbeschreibungen der darin vorkommenden Be-
fehle (Glossar). Sollten bestimmte Befehle gesucht werden, so ist die Seitennummer
aus dem ausführlichen Index zu entnehmen.
Zur Unterscheidung von Beschreibung, FORTH-Worten, Programm-Eingaben und
__-ausgaben wird mit unterschriftlichen Schrifttypen gearbeitet:
seschreibungen erfolgen in Proportionalschrift mit Randausgleich.
FORTH-Befehle werden im Text durch Fettschrift hervorgehoben.
Eingaben und
Programnlistings verwenden die nichtproportionale Schriftart Courier.
Ausgaben des FORTH-Interpreter/Compiler sind unterstrichen.
Prolog en
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
2. Einstieg ins volksFORTH
Damit Sie sofort beginnen können, wird in diesem Kapitel beschrieben,
- wie man das System startet
- wie man sich im System zurechtfindet
- wie man ein fertiges Anwendungsprogramm erstellt
- wie man ein eigenes Arbeitssystem zusammenstellt
2.1 Die Systemdiskette
Zu Ihrem Handbuch haben Sie eine Diskette erhalten. Fertigen Sie auf jeden Fall
mit dem DOS-Befehl diskcopy eine Sicherheitskopie dieser Diskette an. Die Gefahr
eines Datenverlustes ist groß, da FORTH Ihnen in jeder Hinsicht freie Hand läßt -
auch beim versehentlichen Löschen Ihrer Systemdisketten !!
Die Diskette, auf der Ihr volKsFORTH-System ausgeliefert wird, enthält folgende
Dateien:
INSTALL BAT ist ein Installationsprogramm, das volks4TH auf einem
angegebenen Laufwerk einrichtet.
PKXARC COM ist ein Dienstprogramm zum Komprimieren und De-
komprimieren von Dateien.
KERNEL COM
MINIMAL COM
VOLKS4TH COM diese drei COM-Files sind drei volksFORTH-Systeme
in verschiedenen Ausbaustufen.
FORTHI ARC
FORTH2 ARC diese beiden ARC-Dateien enthalten die Quelltexte
des gesamten FORTH-Systems, müssen aber erst von
PKXARC entpackt werden.
VOLKS4TH DOC ist eine ergänzende Dokumentation, die Nachträge
enthält.
READ ME enthält zusätzliche wichtige Hinweise.
Wenn Sie Ihr System, wie in der Datei READ.ME auf der Diskette beschrieben,
idealerweise auf einer Festplatte installiert haben, finden Sie deutlich mehr Files
-.12.= Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
vor. Ein Zeichen für die Platzersparnis durch das Datei-Kompressionsprogramm
PKARC.
VOLKS4TH COM als Ihr komplettes Arbeitsssystem enthält resident
das Fileinterface, den Editor, den Assembler und von
Ihnen eingefügte Werkzeuge (tools).
MINIMAL COM ist eine Grundversion, die oft benötigte Systemteile
enthält. Diese ist notwendig, da FORTH-Systeme all-
gemein nicht über einen Linker verfügen, sondern
ausgehend vom Systemkern die zur Problemlösung
notwendigen Einzelprogramme schrittweise hinzukompi-
liert werden.
KERNEL COM ist eine Grundversion, die nur den Sprachkern ent-
hält. Damit können Sie eigene FORTH-Versionen mit
z.B. einem veränderten Editor zusammenstellen und
dann mit SAVESYSTEM <name> als fertiges System
abspeichern. In der gleichen Art können Sie auch fer-
tige Applikationen herstellen, denen man ihre FORTH-
Abstammung nicht mehr ansieht.
KERNEL SCR enthält die Quelltexte des Sprachkerns. Eben dieser
Quelltext ist mit einem Target-Compiler kompiliert
worden und entspricht exakt dem KERNEL.COM. Sie
können sich also den Compiler ansehen, wenn Sie
wissen wollen, wie das volksFORTH83 funktioniert !
VOLKS4TH Sys enthält einen Ladeblock (Block 1), der alle Teile
kompiliert, die zu Ihrem Arbeitssystem gehören. Mit
diesem Loadscreen ist aus KERNEL.COM das File
VOLKS4TH.COM zusammengestellt worden.
EXTEND SCR enthält Erweiterungen des Systems. Hier tragen Sie
auch persönliche Erweiterungen ein.
CED SCR enthält den Quelltext des Kommandozeilen Editors, mit
dem die Kommandozeile des Interpreters editiert
werden kann. Soll dieser CED ins System eingefügt
werden, so ist diese Datei mit
include ced.scr
savesystem volks4TH.com
ins volksFORTH einzukompilieren.
HISTORY wird von CED angelegt und enthält die zuletzt einge-
gebenen Kommandos.
STREAM SCR enthält zwei oft gewünschte Dienstprogramme:
Die Umwandlung von Text-Dateien (stream files) in
Block-Dateien (block files) und zurück.
Einstieg ins volksFORTH er 138-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
DISASM SCR enthält den Dis-Assembler, der - wie beim CED be-
schrieben - ins System eingebaut werden kann.
2.2 Die Oberfläche
Wenn Sie VOLKS4TH von der DOS-Ebene starten, meldet sich volksFORTH83 mit
einer Einschaltmeldung, die die Versionsnummer rev. <xxxx> enthält.
Was Sie nun von vVolksFORTH sehen, ist die Oberfläche des Interpreters. FORTH-
Systeme und damit auch volksFORTH sind fast immer interaktive Systeme, in denen
Sie einen gerade entwickelten Gedankengang sofort überprüfen und verwirklichen
können. Das Auffälligste an der volksFORTH-Oberfläche ist die inverse Statuszeile
in der unteren Bildschirmzeile, die sich mit status off aus- und mit status on
wieder einschalten läßt.
Diese Statuszeile zeigt von links nach rechts folgende Informationen, wobei ! für
"oder" steht:
<218110116> die zur Zeit gültige Zahlenbasis (dezimal)
Ss xx) nennt die Anzahl der Zahlenwerte, die zum Verarbei-
ten bereitliegen "
Die <xxxx> nennt den freien Speicherplatz
Ser <xx> ist die Nummer des aktuellen Quelltextblocks
A:lC: gibt das aktuelle Laufwerk an
<name>.<ext> zeigt den Namen der Date, die gerade bearbeitet wird.
Dateien haben im MSDOS sowohl einen Namen <name>
als auch eine dreibuchstabige Kennung, die Extension
<ext>, wobei auch Dateien ohne Extension angelegt
werden können.
FORTH FORTH FORTH zeigt die aktuelle Suchreihenfolge gemäß dem Voka-
bularkonzept.
Ein Beispiel dafür sind die Assembler-Befehle:
Diese befinden sich in einem Vokabular namens
ASSEMBLER und assenmbler words zeigt Ihnen den
Befehlsvorrat des Assemblers an. Achten Sie bitte auf
die rechte Seite der Statuszeile, wo jetzt
assembler forth forth
zu sehen ist. Da Sie aber jetzt - noch - keine
Assembler-Befehle einsetzen wollen, schalten Sie bitte
mit _ forth die Suchlaufpriorität wieder um. Die
Statuszeile zeigt wieder das gewohnte
forth forth forth.
= 144- Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Zur Orientierung im Arbeitssystem stellt das volksFORTH einige standardkonforme
Wörter zur Verfügung:
words zeigt Ihnen die Befehlsliste von FORTH, die verfügbaren Wörter.
Diese Liste stoppt bei einem Tastendruck mit der Ausgabe oder
bricht bei einem <ESC> ab.
files zeigt alle im System angelegten logischen Datei-Variablen, die zuge-
hörigen handle Nummern, Datum und Uhrzeit des letzten Zugriffs
und ihre entsprechenden physikalischen DOS-Dateien. Eine solche
FORTH-Datei wird allein durch die Nennung ihres Namens angemel-
det. Die MSDOS-Dateien im Directory werden mit dir angezeigt.
path informiert über eine vollständige Pfadunterstützung nach dem
MSDOS-Prinzip, allerdings vollkommen unabhängig davon.
Ist kein Suchpfad gesetzt, so gibt path nichts aus.
order beschreibt die Suchreihenfolge in den Befehlsverzeichnissen (Voka-
bular).
vocs nennt alle diese Unterverzeichnisse (vocabularies).
2.3 Arbeiten mit Programm- und Datenfiles
Um überhaupt Programmtexte (Quelltexte) schreiben zu können, brauchen Sie eine
Datei, die diese Programmtexte aufnimmt. Diese Datei muß zur Bearbeitung ange-
meldet werden.
volksFORTH geht nach dem Systemstart erst einmal von der Datei VOLKS4TH.SYS als
aktueller Datei aus. VOLKS4TH.SYS ist aber die Steuerdatei, aus der Ihr FORTH-
System aufgebaut wurde; deshalb deklarieren Sie die Datei, die Sie bearbeiten
wollen, mit dieser Befehlsfolge:
use (name).<(ext>
Als Beispiel wird die Datei test.scr mit use test.scr angemeldet.
Möchten Sie allerdings eine vollkommen neue Datei für Ihre Programme benutzen, so
überlegen Sie sich einen Namen <name>, eine Kennung <extension> und eine ver-
nünftige Größe in KByte. Anschließend geben Sie ein:
makefile (name).<ext) <«Größenangabe) more
Daraufhin wird die Datei auf dem Laufwerk angelegt und zum Bearbeiten ange-
meldet. Ein use ist danach nicht mehr notwendig.
Einstieg ins volksFORTH ZelloR =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
2.4 Der Editor
Zum Bearbeiten von Quelltext-Blöcken enthalten ältere FORTH-Systeme meist Edi-
toren, die diesen Namen höchstens zu einer Zeit verdient haben, als man noch die
Bits einzeln mit Lochzange und Streifenleser an die Hardware übermitteln mußte.
Demgegenüber bot ein Editor, mit dem man jeweils eine ganze Zeile bearbeiten
kann, sicher schon einigen Komfort. Da man jedoch mit solch einem Zeileneditor
heute keinen Staat mehr machen und erst recht nicht mit anderen Sprachen kon-
kurrieren kann, können Sie im volksFORTH selbstverständlich mit einem komfortab-
len Fuliscreen-Editor arbeiten.
In diesem Editor kann man zwei Dateien gleichzeitig bearbeiten:
Eine Vordergrund-Datei, das aktuelle isfille und ein Hintergrundfile fromfile . Da-
her werden im Editor zwei Dateinamen angezeigt. Das Wort use meldet eine Datei
automatisch sowohl als isfile als auch als fromfile an, so daß sich Verschiebe-
und Kopieroperationen nur auf diese eine Datei beziehen.
Im Editor wird immer ein FORTH-Screen - also 1824 Bytes - in der üblichen Auf-
teilung in 16 Zeilen mit je 64 Spalten dargestellt.
Es gibt einen Zeichen- und einen Zeilenspeicher. Damit lassen sich Zeichen bzw.
Zeilen innerhalb eines Screens oder auch zwischen zwei Screens bewegen oder ko-
pieren. Dabei wird verhindert, daß versehentlich Text verloren geht, indem Funk-
tionen nicht ausgeführt werden, wenn dadurch Zeichen nach unten oder zur Seite
aus dem Bildschirm geschoben würden.
2.4.1 HELP und VIEW
Der Editor unterstützt das 'Shadow-Konzept'. Zu jedem Quelltext-Screen gibt es
einen Kommentar-Screen. Dieser erhöht die Lesbarkeit von FORTH-Programmen er-
heblich, Sie wissen ja, guter FORTH-Stil ist selbstdokumentierend ! Auf den
Tastendruck CRTL-F9 stellt der Editor den Kommentar-Screen zur Verfügung. So
können Kommentare 'deckungsgleich' zu den Quelltexten angefertigt werden. Dieses
shadow Konzept wird auch bei dem Wort help ausgenutzt, das zu einem Wort einen
erklärenden Text ausgibt. Dieses Wort wird so eingesetzt:
help (name)
HELP zeigt natürlich nur dann korrekt eine Erklärung an, wenn ein entsprechen-
der Text auf einem shadow screen vorhanden ist.
Häufig möchte man sich auch die Definition eines Wortes ansehen, um z.B. den
Stackkommentar oder die genaue Arbeitsweise nachzulesen. Dafür gibt es das
Kommando
view (name)
Damit wird der Screen - und natürlich auch das File - aufgerufen, auf dem
<name> definiert wurde. Dieses Verfahren ersetzt (fast) einen Decompiler, weil es
- 16, - Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
natürlich sehr viel bequemer ist und Ihnen ja auch sämtliche Quelltexte des Sys-
tems zur Verfügung stehen.
Werfen Sie doch bitte mit view u? einen Blick auf das Wort, das Ihnen den Inhalt
einer Variablen ausgibt. Benutzen Sie
fix (name)
( engl. = reparieren), so wird zugleich der Editor zugeschaltet, so daß Sie sofort
gezielt Änderungen im Quelltext vornehmen können. Im Editor werden Sie zuerst
nach einer Eingabe gefragt "Enter your id:*, die Sie einfach mit dem Druck auf die
<cr>-Taste beantworten.
Dann befinden Sie sich im Editor, mit dem man die Quelltextblöcke bearbeitet. Der
Cursor steht hinter dem gefundenen Wort u? . Nun können Sie mit PgUp oder
PgDn in den Screens blättern oder mit <ESC> aus dem Editor zum FORTH zurück-
kehren.
Natürlich müssen für view , fix und help die entsprechenden Files auf den
Laufwerken 'griffbereit' sein, sonst erscheint eine Fehlermeldung. Die VIEW-Funk-
tion steht auch innerhalb des Editors zur Verfügung, man kann dann mit dem Tas-
tendruck CTRL-F das rechts vom Cursor stehende Wort anfordern. Dies ist insbe-
sondere nützlich, wenn man eine Definition aus einem anderen File übernehmen
möchte oder nicht mehr sicher ist, wie der Stackkommentar eines Wortes lautet.
2.4.2 Öffnen und Editieren eines Files
Nun aber zum Erstellen und Ändern von Quelltexten für Programme - eine schöne
Definition von Editieren. Sie haben sich bestimmt eine Datei test.scr wie oben
beschrieben mit
makefile test.scr 6 more
angelegt. Damit haben Sie ein File namens TEST.SCR mit einer Länge von 6 Blöcken
(6144 Byte = 6KB), bestehend aus den Screens @ bis 5 ; davon sind die Nummern
® bis 2 für Quelltexte, die anderen für Kommentare bestimmt.
Um in den Editor zu gelangen gibt es drei Möglichkeiten:
screen#) edit
oder <scer#) 1
ruft den Screen mit der Nummer <scr#> auf. Hat man bereits editiert, ruft
v
den zuletzt bearbeiteten Screen wieder auf. Dies ist der zuletzt editierte oder aber,
und das ist sehr hilfreich, derjenige, der einen Abbruch beim Kompilieren verur-
sacht hat. volksFORTH bricht - wie die meisten modernen Systeme -— bei einem
Programmfehler während des Kompilierens ab und markiert die Stelle, wo der Fehler
auftrat. Dann brauchen Sie nur v einzugeben. Der fehlerhafte Screen wird in den
Editor geladen und der Cursor steht hinter dem Wort, das den Abbruch des Kom-
pilierens verursachte.
Einstieg ins volksFORTH =-käi-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Als Beispiel soll der Block #1 editiert werden:
1 edit
Sie werden nach der Eingabe des dreibuchstabigen Kürzels gefragt. Dieses Kürzel
wird dann rechts oben in den Screen eingetragen und gibt die programmer's id
wieder. Wenn Sie nichts eingeben möchten, drücken Sie bitte nur <cr?). Zum Be-
nutzen dieser Blöcke gibt es noch einige Vereinbarungen, von denen ich hier zwei
nennen möchte:
1. wird der Block Nr.@ nie !! für Programmtexte benutzt - dort finden
sich meist Erklärungen und Hinweise zum Programm und zum Autor.
2. In die Zeile © eines Blockes wird immer ein Kommentar eingetragen,
der mit \ (skip line) eingeleitet wird. Dieser Backslash sorgt
dafür, daß die nachfolgende Zeile als Kommentar überlesen wird. In
diese Zeile ® schreibt man oft die Namen der Wörter, die im Block
definiert werden.
2.4.3 Tastenbelegung des Editors
Beim Editieren stehen Ihnen folgende Funktionen zur Verfügung:
Fi gibt Hilfestellung für den Editor
ESC verläßt den Editor mit dem sofortigen Abspeichern der Änderungen.
CTRL-U (undo) macht alle Änderungen rückgängig, die noch nicht auf Disk
zurückgeschrieben wurden.
CTRL-E verläßt den Editor ohne sofortiges Abspeichern.
CTRL-F (fix) sucht das Wort rechts vom Cursor, ohne den Editor zu ver-
lassen.
CTRL-L (showload) lädt den Screen ab Cursorposition.
CTRL-N fügt an Cursorposition eine neue Zeile ein.
CTRL-PgDn splittet innerhalb einer Zeile diese Zeile.
CTRL-S (Scr#) legt die Nummer des gerade editierten Screens auf dem Stack
ab; z.B. für ein folgendes load oder plist.
CTRL=-Y löscht die Zeile an Cursorposition
CTRL-PgUp fügt innerhalb einer Zeile den rechten Teil der unteren Zeile an die
obere Zeile (join).
TAB bewegt den Cursor einen großen TABulator vor.
SHIFT TAB bewegt den Cursor einen kleinen TABulator zurück.
F2 (suchen/ersetzen) erwartet eine Zeichenkette, die gesucht werden
soll und eine Zeichenkette, die statt dessen eingefügt werden soll.
Wird eine Übereinstimmung gefunden, kann man
mit _R (replace) die gefundene Zeichenkette ersetzen,
mit <er? den Suchvorgang abbrechen
oder mit jeder anderen Taste die nächste Übereinstimmung suchen.
= 18.- Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
F3
F5
E7.
F4
F6
F8
F9
SHIFT F9
F18
Auf diese Weise kann man die Quelltexte auch nach einer Zeichen-
kette durchsuchen lassen. Als Ersatz-String wird dann <CR> einge-
geben.
bringt eine Zeile in den Zeilenpuffer und löscht sie im Screen.
bringt die Kopie einer Zeile in den Zeilenpuffer.
fügt die Zeile aus dem Zeilenpuffer in den Screen ein.
wie F3, nur für ein einzelnes Zeichen.
wie F5, jedoch für ein einzelnes Zeichen.
entspricht F7, bezogen auf ein Zeichen.
vertauscht die aktuelle Datei (isfile) mit der Hintergrunddatei
(fromfile). Erneutes F9-Drücken vertauscht erneut und stellt damit
den alten Zustand wieder her. Diese Funktion ist dann sinnvoll,
wenn Sie eine Datei bearbeiten, sich zwischendurch aber mit CRTL-
F ein Wort anzeigen lassen. Dann stellt F9 (=fswap) die alte Datei-
verteilung wieder her, die sich durch das fix geändert hat.
schaltet auf die Kommentartexte (shadowscreens) um und beim
nächsten Drücken wieder zurück.
legt den aktuellen Screen kurz beiseite, um ihn dann mit einem
Druck auf F9 wieder bearbeiten zu können. Sollte Ihnen das volks-
FORTH eine der Kopierfunktionen copy oder convey mit der Mel-
dung TARGET BLOCK NOT EMPTY verweigern, weil isfile und fromfile
unterschiedlich sind, so sorgt F1@ wieder für klare Verhältnisse.
Noch ein Hinweis zum Editor:
Der Editor unterstützt nur das Kopieren von Zeilen. Man kann auf diese Art auch
Screens kopieren, aber beim gelegentlich erforderlichen Einfügen von Screens in der
Mitte eines Files ist das etwas mühselig. Zum Kopieren ganzer Screens innerhalb
eines Files oder von einem File in ein anderes werden im volksFORTH83 die Worte
COPY und CONVEY verwendet.
2.4.4 Beispiel: CLS
.ür Ihr erstes Programm tragen Sie nun bitte den folgenden Quelltext in Screen 1
ein:
\ CLS löscht den gesanten Bildschirm
. cls
(--) £ull page ;
Nun drücken Sie SHIFT-F9 und tragen einen Kommentar in diesen Screen ein, wobei
die Erklärung zu CLS in der gleichen Zeile, wie die Definition des Quelltextes, z.B.:
\\ CLs
CLS löscht den gesamten Bildschirm, indem es auf die Worte
full (Bildschirmfenster auf volle Größe) und PAGE (Bild
schirmfenster löschen) zurückgreift.
Einstieg ins volksFORTH 95
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Ein nochmaliges SHIFT-F9 bringt Sie wieder zum Quelltext (source code) zurück..
Damit bekommen Sie diesen erklärenden Text nach dem Kompilieren mit help cls
angezeigt.
Wenn Sie einen Block vollgeschrieben haben, blättern Sie nur mit PgUp vor oder
mit PgDn zurück zum nächsten Block. Sind Sie mit Ihrem Programm zufrieden, so
drücken Sie ESC ; dann wird der geänderte Screen sofort abgespeichert.
Danach werden Sie wieder etwas bemerken: Der Bildschirm arbeitet nicht mehr
korrekt, es bleiben oben Zeilen stehen, die nicht scrollen.
Das ist richtig, damit der zuletzt bearbeitete Quelltext nicht nach oben wegscrollt.
Um nicht weitere zwei Zeilen des Bildschirms zu verlieren, hat das Fenster, in dem
Sie gerade arbeiten, keinen Rahmen. Wie man mit Rahmen und Fenstern arbeitet,
wird im Editor vorgeführt, der wie alle anderen Systemteile im Quelltext vorliegt.
Um sich in Zukunft schnell aus der mißlichen Lage mit der reduzierten
Bildschirmgröße zu befreien, benutzen Sie Ihr erstes selbstgeschriebenes Programm
cls . Denn die Eingabe von full stellt Ihnen wieder die gesamten Bildschirmfläche
zur Verfügung, wogegen page nur das aktuelle Fenster löscht.
In volks4TH wird das Kompilieren - wie in den meisten FORTH-Systemen - über
<ser#> load durchgeführt:
1 load
kompiliert Ihr Wort CLS mit für 'C'- oder Pascal-Programmierer unvorstellbarer
Geschwindigkeit ins FORTH. Damit steht Ihr Mini-Programm jetzt zur Ausführung
bereit. Zugleich erhalten Sie die Meldung, daß ein Wort namens CLS bereits be-
steht: "CLS exists" . Dies hat nur die Konsequenz, daß nach einer Redefinition das
alte Wort gleichen Namens nicht mehr zugegriffen werden kann. Eine Möglichkeit,
diese Namensgleichheit mit einem bereits existierenden Wort zu vermeiden, wäre der
Einsatz eines Vokabulares.
Geben Sie einmal words ein, dann werden Sie feststellen, daß Ihr neues Wort CLS
ganz oben im Dictionary steht (drücken Sie die <ESC>-Taste, um die Ausgabe von
words abzubrechen oder irgendeine andere Taste, um sie anzuhalten).
Um das Ergebnis Ihres ersten Programmierversuchs zu überprüfen, geben Sie nun
ein:
cls
Und siehe da, der gesamte Bildschirm wird dunkel. Schöner wäre es allerdings,
wenn Ihr Programm seine Arbeit mit einer Meldung beenden würde Um dies zu
ändern, werfen Sie bitte erst einmal das alte Wort CLS weg:
forget cls
Bitte kontrollieren Sie mit words ,ob CLS wirklich vergessen wurde. Rufen Sie
dann erneut den Editor mit v auf. Nun benutzen Sie das Wort für den Beginn
einer Zeichenkette ." , das Wort für ihr Ende " und das Wort für einen Zeilen-
vorschub cr. Ihr Screen 1 sieht dann so aus :!
\ CLS löscht den Bildschirm mit Meldung
= Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Decks Au== )
full page
." Bildschirm ordnungsgemäß gelöscht!" cr ;
Nach dem ." muß ein Leerzeichen stehen. Denn FORTH benutzt standardmäßig das
Leerzeichen als Trennzeichen zwischen einzelnen Worten, so daß dies Leerzeichen
nicht mit zur Zeichenkette (string) zählt. Dann verlassen Sie den Editor und
kompilieren Sie Ihr Programm wie gehabt und starten es. Die Änderung erweist sich
als erfolgreich, und Sie haben gelernt, wie einfach in FORTH das Schreiben, Aus-
testen und Ändern von Programmteilen ist.
Eine große Hilfe sowohl für den Programmierer als auch für den späteren Benutzer
sind Informationen darüber, was gerade geladen wird und was schon kompiliert
wurde. Fügt man
er .( Funktion installiert )
ein, so werden während des Ladens diese Meldungen ausgegeben. Das Wort .( leitet
einen Kommentar im Interpreter ein, die schließende Klammer ) beendet ihn und cr
ist natürlich für den Zeilenvorschub, das carriage return, verantwortlich.
2.4.5 Compilieren im Editor - Showload
Eine Besonderheit von volksFORTH ist, daß selbst im Editor Funktionen des Inter-
preters/Compilers zur Verfügung stehen. Dieses Interpretieren und Kompilieren im
Editor nennt sich Showload.
CTRL-F (fix) sucht und zeigt das Wort rechts vom Cursor, ohne den Editor
zu verlassen.
CTRL-L (showload) lädt den Screen ab Cursorposition.
Um zu sehen, was diese Showload-Funktion leistet, geben Sie nun bitte folgenden
Screen ein:
\ Ein Test für das showload
:sinetiiHt;
2.den..I2.%
\\
15 ine .
15 inc dec .
15 15 + 2 spaces .
Dieser Screen soll jetzt im Editor kompiliert und interpretiert werden !!
Dazu setzen Sie bitte den Cursor durch die Taste CTRL-home in die erste Zeile auf
das Zeichen \ (skip line). Drücken Sie nun CTRL-L zum Laden des Screens.
volksFORTH kompiliert nun bis zu der Zeile, die mit \\ (skip screen) beginnt. Die
Wörter inc und dec sind dem System jetzt bekannt und können benutzt werden.
Anschließend bewegen Sie den Cursor hinter das \\ und drücken CTRL-L zum
weiteren Interpretieren im Editor. Sofort sehen Sie die Ausgaben an der entspre-
chenden Stelle im Editor erscheinen. Dabei bleibt der Inhalt des Screens selbst-
Einstieg ins volksFORTH Sr
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
verständlich unversehrt - verlassen Sie den Editor mit ESC und sehen Sie sich den
Inhalt den Screens mit <scr#> list an; Sie sehen nur die Anweisungen, aber
nicht mehr die Ausgaben vor sich.
Eine typische Anwendung dieses showload wäre das Neukompilieren eines Wortes
nach einer kleinen Änderung oder das interaktive Hinzufügen von Wörtern, die man
gerade mal braucht.
2.5 Erstellen einer Applikation
Sie wollen Ihr 'Programm' nun als eigenständige Anwendung abspeichern. Dazu
erweitern Sie es zunächst ein klein wenig (Editor mit v aufrufen.) FÜgen Sie nun
noch folgende Definition in einer neuen Zeile hinzu:
: runalone cls bye ;
RUNALONE führt zuerst CLS aus und kehrt dann zum Betriebssystem zurück. Kompi-
lieren Sie nun erneut, wobei Sie die Meldung erhalten "CLS exists". Sie führen
RUNALONE aber nicht aus, sonst würden Sie FORTH ja verlassen (bye).
Das Problem besteht vielmehr darin, das System so abzuspeichern, daß es gleich
nach dem Laden RUNALONE ausführt und sonst gar nichts. volksFORTH83 ist an
zwei Stellen für solche Zwecke vorbereitet. In den Worten COLD und RESTART be-
finden sich zwei 'deferred words' namens 'COLD bzw. 'RESTART , die im Normalfall
nichts tun, vom Anwender aber nachträglich verändert werden können.
Sie benutzen hier 'COLD, um auch schon die Startmeldung zu unterbinden. Geben
Sie also ein
" runalone Is 'cold
und speichern Sie das Ganze mit
savesystem cls.com
auf Disk zurück. Sie haben Ihre erste Applikation erstellt, die Sie von MSDOS-
Ebene aus mit CLS aufrufen können !
Etwas enttäuschend ist es aber schon. Das angeblich so kompakte FORTH benötigt
über 26KByte, um eine so lächerliche Funktion auszuführen ?? Da stimmt doch
etwas nicht. Natürlich, es wurden ja eine Reihe von Systemteilen mit abgespeichert,
vom Fileinterface über den Assembler, den Editor usw., die für unser Programm
überhaupt nicht benötigt werden.
Um dieses und ähnliche Probleme zu lösen, gibt es das File KERNEL.COM. Dieses
Programm enthält nur den Systemkern und das Fileinterface und entspricht damit
der Laufzeit-Bilbliothek (runtime library) anderer Sprachen.
2 Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Anwendung.com
volksFORTH.com
Minimal.com
Kernel.com
+ Basisfunktionen
+ Editor, Debugger etc.
+ Anwendungsprogramm
Laden Sie also KERNEL.COM und kompilieren Sie Ihre Applikation mit
include multi.vid
include test.scr
Das vorherige Laden von MULTI.VID ist nötig, weil FORTH-Systeme selten über
Linker verfügen; wird MULTI.VID nicht vorher geladen, so ist dem FORTH-System
das Wort full unbekannt. Dann wie gehabt RUNALONE in 'COLD eintragen und
das System auf Disk zurückspeichern. Von der MS-DOS Ebene aus läßt sich diese
Programmerstellung mit
kernel include mulit.vid include test.scr
durchführen, wobei diese beiden Zeilen
runalone Is 'cold
savesystem dark.con
die letzten Anweisungen auf Ihrem Screen sind. Damit wird der FORTH-Interpreter
angewiesen, die fertige Anwendung DARK.com auf Disk zu speichern.
Sie haben jetzt eine verhältnismäßig kompakte Version vorliegen. Natürlich ließe
sich auch diese noch erheblich kürzen, aber dafür bräuchten Sie einen Target-
Compiler, mit dem Sie nur noch die wirklich benötigten Systemteile selektiv aus
dem Quelltext zusammenstellen könnten. Mit der beschriebenen Methode lassen sich
aber auch größere Programme kompilieren und als Stand-alone-Applikationen ab-
speichern.
2.6 Das Erstellen eines eigenen FORTH-Systems
Das File VOLKS4TH.COM ist als Arbeitsversion gedacht.
Es enthält alle wichtigen Systemteile wie Editor, Printer-Interface, Tools, Decom-
piler, Tracer usw. Sollte Ihnen die Zusammenstellung nicht gefallen, können Sie
sich jederzeit ein Ihren speziellen Wünschen angepaßtes System zusammenstellen.
Einstieg ins volksFORTH - 20.»
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Schlüssel dazu ist der Loadscreen des Files VOLKS4TH.SYS . Sie können dort
Systemteile, die Sie nicht benötigen, mit dem Backslash \ wegkommentieren oder
die entsprechenden Zeilen ganz löschen. Ebenso können Sie natürlich dem Load-
screen eigene Files hinzufügen. Entspricht der Loadscreen Ihren Wünschen, spei-
chern Sie ihn mit <ESC> zurück, und verlassen Sie das System mit BYE. Laden Sie
nun das File KERNEL.COM . Geben Sie dann ein:
include volks4TH.sys
Ist das System fertig kompiliert, schreibt die Anweisung
savesystem volks4TH.com
des Load-Screens eine neue Version von volks4TH.com auf Disk. Damit wird Ihr
altes File überschrieben (Sicherheitskopie !!!), sodaß Sie beim nächsten Laden von
volks4TH.com Ihr eigenes System erhalten.
Natürlich können Sie 'Ihr' System auch unter einem anderen Namen abspeichern.
Ebenso können Sie Systemvoreinstellungen ändern. Unsere Arbeitsversion arbeitet
- voreingestellt - neuerdings im dezimalen Zahlensystem. Natürlich können Sie
mit hex auf Hexadezimalsystem umstellen; wir halten das für sehr viel sinn-
voller, weil vor allem Speicheradressen im Dezimalsystem kaum etwas aussagen
(oder wissen Sie, ob Speicherstelle 978584 im Bildschirmspeicher liegt oder nicht ?).
Wollen Sie bereits unmittelbar nach dem Laden im Hexadezimalsystem arbeiten,
können Sie sich dies mit SAVESYSTEM abspeichern, indem Sie von der FORTH-
Kommandozeile aus savesystem volks4TH.com eingeben.
Im Übrigen empfehlen wir bei allen Zahlen über 9 dringend die Benutzung der so-
genannten Präfixe:
$ für Hexadezimal-,
& für Dezimal- und
% für Binärzahlen,
Man vermeidet so, daß irgendwelche Files nicht - oder noch schlimmer, falsch -
kompiliert werden, weil man gerade im anderen Zahlensystem ist. Außerdem ist es
“möglich, hexadezimale und dezimale Zahlen beliebig zu kombinieren, je nachdem,
was gerade sinnvoller ist. In den Quelltexten finden Sie genug entsprechende Bei-
spiele.
Besonders schnell und komfortabel arbeitet volksFORTH natürlich, wenn alle Teile
des Systems auf einer Festplatte abgelegt sind. Sie sollten dafür ein eigenes
Directory einrichten und PATH und DIR entsprechend einstellen.
Auch die Arbeit mit einer RAM-Disk ist prinzipiell möglich, allerdings nicht sehr zu
empfehlen. FORTH ist sehr maschinennah und Systemabstürze daher vor allem zu
Anfang nicht so ganz auszuschließen.
Das Ausdrucken der Quelltexte des Systems ist sicher sinnvoll, um Beispiele für
den Umgang mit volksFORTH83 zu sehen. So stellen z.B. der Screen-Editor und der
Kommando-Editor vollständige Anwendungen dar, die im Quelltext vorliegen.
Welche Files sich im Einzelnen auf Ihren Disketten befinden und ob sie Kommen-
= DA = Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
tarscreens enthalten, steht im File README.DOC. Zunächst müssen Sie das Printer-
Interface hinzuladen, falls es nicht schon vorhanden ist. Reagiert Ihr volksFORTH83
auf die Eingabe von PRINTER mit einem ? „so ist das Printerinterface nicht vor-
handen.
2.7 Ausdrucken von Screens
Sollte in Ihrem System kein Druckerinterface vorhanden sein, so laden Sie es von
der FORTH-Kommandozeile aus mit
include <Druckername).prn
nach. Sollte Ihr Drucker in der Liste nicht erscheinen, so benutzen Sie statt
dessen graphic.prn oder epson.prn . Die meisten Drucker können als IBM-Graphic-
Printer oder als EPSON FX/LX-Drucker arbeiten.
Im Printer-Interface sind einige Worte zur Ausgabe eines formatierten Listings
enthalten. PTHRU druckt einen Bereich von Screens, jeweils 6 Screens auf einer DIN
A4 Seite in komprimierter Schrift. Ganz ähnlich arbeitet das Wort DOCUMENT „,
jedoch wird bei diesem Wort neben einen Quelltextscreen der zugehörige
Shadowscreen gedruckt. LISTING druckt ein ganzes File so aus, man erhält so ein
übersichtliches Listing eines Files mit ausführlichen Kommentaren.
Glossar
pthru ( von bis -- )
druckt die angegebenen Blöcke immer zu sechst auf einer Seite aus.
document ( von bis -- )
arbeitet wie pthru , druckt aber jeweils drei Quelltextblöcke und drei
Kommentarblöcke auf einer Seite aus.
listing (--)
erstellt ein Listing der gesamten Datei, indem jeweils drei Quelltext-
Blöcke und drei Kommentar-Blöcke auf einer Seite ausgedruckt werden.
plist (scr# -- )
druckt einen angegebenen Block auf dem Drucker aus.
ser ( -- addr )
ist eine Variable, die die Nummer des gerade editierten Screens enthält.
Vergl. r# , list, (error
Einstieg ins volksFORTH 2er
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
r# ( -- addr )
ist eine Variable, die den Abstand des gerade editierten Zeichens von
Anfang des gerade editierten Screens enthält.
2.8 Druckeranpassung
Die Druckeranpassung das Arbeitssystems wird im File VOLKS4TH.SYS durch die
Zeile
include <printer).prn
vorgenommen. In dieser Anpassung sind - zusätzlich zu den reinen Ausgaberou-
tinen - eine Reihe nützlicher Worte enthalten, mit denen die Druckersteuerung
sehr komfortabel vorgenommen werden kann.
Im Arbeitssystem ist das Printerinterface bereits enthalten. Müssen Sie Änderungen
vornehmen, können Sie mit dem Editor den Loadscreen von VOLKS4TH.SYS ändern
und sich ein neues Arbeitssystem zusammenstellen mit:
kernel include volks4TH.sys
Sie können natürlich auch den Loadscreen in seiner jetzigen Fassung benutzen und
das Printer-Interface jedesmal 'von Hand' mit
include <printer>.prn
nachladen.
Leider sind im Moment im volksFORTH noch deutsche und englische Fehlermeldungen
gemischt und die help Funktion zeigt Ihnen einen erklärenden Text nur, wenn
dieser vorhanden ist.
Die wichtigsten Befehle noch einmal im Überblick:
status steuert die Status-Zeile
words zeigt die gerade verfügbaren Befehle an
files zeigt die angemeldeten Dateien
path verändert oder nennt den Datei-Suchpfad
order listet die Suchreihenfolge der Befehlsgruppen auf
vocs nennt alle verfügbaren Befehlsgruppen
view zeigt und
fix editiert den Quelltext eines bestimmten Wortes
help zeigt - wenn vorhanden - den Kommentartext eines Wort
full schaltet das Bildschirmfenster auf die volle Größe
page löscht das aktuelle Fenster
index - nicht resident - zeigt den Inhalt einer Block-Datei
list zeigt den Inhalt eines Screens.
— BL - Einstieg ins volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
include lädt eine ganze Befehlsgruppe oder einen Programteil
Nun sollten Sie bereits zu einem begleitenden Buch zu greifen. Denn volksFORTH
ist ein komplexes multitaskingfähiges Entwicklungssystem, das man nicht von heute
auf morgen beherrscht.
[1] Leo Brodie Programmieren in FORTH
( Hanser Verlag )
[2) Leo Brodie In FORTH denken
( Hanser Verlag )
[3J) R. Zech FORTH 83
( Franzis Verlag )
[4] H.-W. Beilstein Wie man in FORTH programmiert
( Chip Wissen )
Einstieg ins volksFORTH 327.
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
3. Arithmetik
3.1 Stacknotation
Im foigenden werden hauptsächlich Worte in ihrer Einzelfunktion beschrieben. In
dieser Form der Beschreibung, die Sie bereits kennengelernt haben, wird die Wir-
kung eines Wortes auf den Stack in Klammern angegeben und zwar in folgender
Form:
( vorher -- nachher )
vorher : Werte auf dem Stack vor Ausführung des Wortes
nachher : Werte auf dem Stack nach Ausführung des Wortes
In dieser Notation wird das oberste Element des Stacks (tos) immer ganz rechts
geschrieben. Sofern nicht anders angegeben, beziehen sich alle Stacknotationen auf
die spätere Ausführung des Wortes. Bei immediate Worten wird auch die Auswirkung
des Wortes auf den Stack während der Kompilierung angegeben. Worte werden ferner
durch folgende Symbole gekennzeichnet:
c Dieses Wort kann nur während der Kompilation einer :-Definition
benutzt werden.
I Dieses Wort ist ein immediate Wort, das auch im kompilierenden Zu-
stand ausgeführt wird.
83 Dieses Wort wird im 83-Standard definiert und muß auf allen
Standardsystemen äquivalent funktionieren.
U Kennzeichnet eine Uservariable.
Weicht die Aussprache eines Wortes von der natürlichen englischen Aussprache ab,
so wird sie in Anführungszeichen angegeben. Gelegentlich folgt auch eine deutsche
Übersetzung.
Die Namen der Stackparameter folgen, sofern nicht suggestive Bezeichnungen ge-
wählt wurden, dem nachstehendem Schema. Die Bezeichnungen können mit einer
nachfolgenden Ziffer versehen sein.
Stack- Zahlentyp Wertebereich minimale
notation in Dezimal Feldbreite
flag logischer Wert ö=falsch, sonst=true 16 Bit
true (tf) logischer Wert -1 (als Ergebnis) 16 Bit
false (ff) logischer Wert ® 16 Bit
b Bit 8..1 1 Bit
char Zeichen 0..127 (8..256) 7(8Bit)
28 = z Arithmetik
FORTH-Gesellschaft e.V.
PC-volksFORTH83 rev. 3.81
8b
8 beliebige Bits nicht anwendbar 8
16b 16 beliebige Bits nicht anwendbar 16
n Zahl,bewertete Bits -32768..32767 16
+n positive Zahl 0..32767 16
u vorzeichenlose Zahl B..65535 16
w Zahl, n oder u -32768..65535 16
addr Adresse, wie u 8..65535 16
32b 32 beliebige Bits nicht anwendbar 32
d doppelt genaue Zahl -2,147,483,648... 32
2,147,483,647
+d pos. doppelte Zahl 08..2,147,483,647 32
ud vorzeichenlose 08..4,294,967,295 32
doppelt genaue Zahl
Sys systemabhängige Werte nicht anwendbar nicht anwendbar
3.2 Arithmetische Funktionen
-1 >= -1)
8 (--8)
1 (--1)
2 ))
3 (-- 3)
4 (--4)
Oft benutzte Zahlenwerte wurden zu Konstanten gemacht. Definiert in der
Form :
n Constant n
Dadurch wird Speicherplatz eingespart und die Ausführungszeit ver-
kürzt.
1+ (w1 --w2) 83 "one-plus"
w2 ist das Ergebnis von Eins plus wi. Die Operation 1 + wirkt genauso.
1= (w1l1--w2) 83 "one-minus"
w2 ist das Ergebnis von wi minus Eins. Die Operation 1 - wirkt genauso.
2+ (w1--w2) 83 "two-plus"
w2 ist das Ergebnis von wi plus Zwei. Die Operation 2 + wirkt genauso.
2- (w1l--w2) 83 "two-minus"
w2 ist das Ergebnis von wl minus Zwei. Die Operation 2 - wirkt genauso.
Arithmetik “2s-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
2% (wl --w2) ; "two-times"
wl wird um ein Bit nach links geschoben und das ergibt w2. In das nie-
derwertigste Bit wird eine Null geschrieben. Die Operation 2 * wirkt ge-
nauso.
2/ t NE --In2®) 83 "two-divide"
nl wird um ein Bit nach rechts verschoben und das ergibt n2. Das Vor-
zeichen wird berücksichtigt und bleibt unverändert. Die Operation 2 /
wirkt genauso.
3+ (w1 --w2) "three-plus"
w2 ist das Ergebnis von wıi plus Drei. Die Operation 3 + wirkt genauso.
abs (n--u) 83 "absolute"
u ist der Betrag von n. Wenn n gleich -32768 ist, hat u denselben Wert
wie n. Vergleiche auch Zweierkomplement.
not (w1--w2) 83
Jedes Bit von wi wird einzeln invertiert und das ergibt w2.
negate (nl --n2) 83
n2 hat den gleichen Betrag, aber das umgekehrte Vorzeichen von nl. n2
ist gleich der Differenz von Null minus nl.
even (ul -- 2)
ist im 8886-FORTH ein noop-Befehl ohne Funktion.
max (nin2--n3) 83 "maximum"
n3 ist die Größere der beiden Werte nl und n2. Benutzt die Operation
> . Die größte Zahl für ni oder n2 ist 32767.
min (nın2--n3) 83 "minimum"
n3 ist die Kleinere der beiden Werte nl und n2. Benutzt die Operation
< . Die kleinste Zahl für nl oder n2 ist -32768.
+ (wlw2 -- w3) 83 "plus"
wl und w2 addiert ergibt w3.
- (wlw2 -- w3) 83 "minus"
w2 von w1l subtrahiert ergibt w3.
- 30 - Arithmetik
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
mod
/mod
*/mod
u/mod
(wlw2 --w3) 83 "times"
Der Wert wi wird mit w2 multipliziert. w3 sind die niederwertigen
16 Bits des Produktes. Ein Überlauf wird nicht angezeigt.
(nın2--n3) 83 "divide"
n3 ist der Quotient aus der Division von ni durch den Divisor n2. Eine
Fehlerbedingung besteht, wenn der Divisor Null ist oder der Quotient
außerhalb des Intervalls (-32768...32767) liegt.
(nin2--n3) 83 "mod"
n3 ist der Rest der Division von nl durch den Divisor n2. n3 hat daßelbe
Vorzeichen wie n2 oder ist Null. Eine Fehlerbedingung besteht, wenn der
Divisor Null ist oder der Quotient außerhalb des Intervalls (-
32768..32767) liegt.
(nin2 --n3n4a) 83 "divide-mod"
n3 ist der Rest und n4 der Quotient aus der Division von ni durch den
Divisor n2. n3 hat dasselbe Vorzeichen wie n2 oder ist Null. Eine
Fehlerbedingung besteht, wenn der Divisor Null ist oder der Quotient
außerhalb des Intervalls (-32768..32767) liegt.
(nin2n3--nA) 83 "times-divide"
Zuerst wird nl mit n2 multipliziert und ein 32-bit Zwischenergebnis er-
zeugt. n4 ist der Quotient aus dem 32-bit Zwischenergebnis und dem
Divisior n3. Das Produkt von nl mal n2 wird als 32-bit Zwischenergebnis
dargestellt, um eine größere Genauigkeit gegenüber dem sonst gleichwer-
tigen Ausdruck ni n2 * n3 / zu erhalten. Eine Fehlerbedingung besteht,
wenn der Divisor Null ist, oder der Quotient außerhalb des Intervalls (-
32768.. 32767) liegt.
(nin2n3--n4an5) 83 "times-divide-mod"
Zuerst wird nl mit n2 multipliziert und ein 32-bit Zwischenergebnis er-
zeugt. n4 ist der Rest und n5 der Quotient aus dem 32-bit-Zwischener-
gebnis und dem Divisor n3. n4 hat das gleiche Vorzeichen wie n3 oder
ist Null. Das Produkt von ni mal n2 wird als 32-bit Zwischenergebnis
dargestellt, um eine größere Genauigkeit gegenüber dem sonst gleichwer-
tigen Ausdruck nl n2 * n3 /mod zu erhalten. Eine Fehlerbedingung be-
steht, falls der Divisor Null ist oder der Quotient außerhalb des Inter-
valls (-32768...32767) liegt.
(ul u2 -- u3u4) "u-divide-mod"
u3 ist der Rest und u4 der Quotient aus der Division von ul durch den
Divisor u2. Die Zahlen u sind vorzeichenlose 16-Bit Werte (unsigned
integer). Eine Fehlerbedingung besteht, wenn der Divisor Null ist.
Arithmetik 4, =
FORTH-Gesellschaft e.V.
PC-volksFOR
TH83 rev. 3.81
umax
umin
true
false
Bo
D<
0
(ulu2 --u3)
u3 ist der Größere der beiden Werte ul und u2. Benutzt
tion. Die größte Zahl für ul oder u2 ist 65535.
(ulu2 -- u3)
u3 ist der Kleinere der beiden Werte ul und u2. Benutzt
tion. Die kleinste Zahl für ul oder u2 ist Null.
3.3 Logik und Vergleiche
(===)
hinterläßt -1 als Zeichen für logisch wahr auf dem Stack.
(==9)
"u-maximum"
die U> Opera-
"u-minimum"
die U< Opera-
Hinterläßt Null als Zeichen für logisch-falsch auf dem Stack.
(w-- flag)
Wenn w gleich Null ist, ist flag wahr.
Un-- flag)
83
Wenn n verschieden von Null ist, ist flag wahr.
(n-- flag)
83
Wenn n kleiner als Null (negativ) ist,
dann der Fall, wenn das höchstwertige Bit von n gesetzt ist. Deswegen
kann dieser Operator zum Testen dieses Bits benutzt werden.
(n-- flag)
83
Wenn n größer als Null ist, ist flag wahr.
ist flag wahr.
(wi w2 -- flag ) 83
Wenn wi gleich w2 ist, ist flag wahr.
(nin2--flag) 83
wenn nl kleiner als n2 ist, ist flag wahr. z.B. -32768
wahr. -32768 6 <£ ist wahr.
{nm -- flag) 83.
Wenn nl größer als n2 ist, ist flag wahr.z.B. -32768 3276
32768 8
>»:
ist falsch.
"zero-equals"
"zero-less"
Dies ist immer
"Zero-greater"
"equals"
"less-than"
32767 &£ ist
"greater-than"
7 > ist falsch.
Arithmetik
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
u<
u)
and
or
xor
uwithin
case?
extend
(ul u2 -- flag ) 83 "u-less-than"
Wenn ul kleiner als u2 ist, ist flag wahr. Die Zahlen u sind vorzeichen-
lose 16-Bit Werte. Wenn Adressen verglichen werden sollen, muß U< be-
nutzt werden, sonst passieren oberhalb von 32K seltsame Dinge !
(ul u2 -- flag ) 3 "u-greater-than"
Wenn ul größer als u2 ist, ist flag wahr. Ansonsten gilt das gleiche wie
für UX.
(wl1w2 --w3) 83
wl wird mit w2 bitweise logisch UND verknüpft und das ergibt w3.
(w1w2 --w3) 83
w1 wird mit w2 logisch ODER verknüpft und das ergibt w3.
(w1w2 --w3) 83 X70Or"
wl wird mit w2 bitweise logisch EXKLUSIV ODER verknüpft und das ergibt
w3.
(uulu2 -- flag)
Wenn ul kleiner oder gleich u und u kleiner u2 ist (ul<=u<u2), ist flag
wahr. Benutzt die U< Operation. "
( 16b1 16b2 -- 16b1l false j true: ) "case-question"
Vergleicht die beiden Werte 16bl und 16b2 miteinander. Sind sie gleich,
verbleibt TRUE auf dem Stack. Sind sie verschieden, verbleibt FALSE und
der darunterliegende Wert 16bl auf dem Stack. Wird z.B. in der folgenden
Form benutzt :
key :
Ascii a case? IF ... exit THEN
Ascii b case? IF ... exit THEN
drop n
Entspricht dem Ausdruck over = dup IF nip THEN .
3.4 32Bit-Worte
(n-=-%0)
Der Wert n wird auf den doppelt genauen Wert d vorzeichenrichtig er-
weitert. Benutze für das in der Literatur oft auftretende s>d
“ extend Alias s)d
Arithmetik = gr =
FORTH-Geseilschaft e.V. PC-volksFORTH83 rev. 3.81
dabs (d-- ud) 83 "d-absolut"
ud ist der Betrag von d. Wenn d gleich -2.147.483.648 ist, hat ud den
selben Wert wie d.
dnegate (d1ı--(d2) 83 "d-negate"
d2 hat den gleichen Betrag aber ein anderes Vorzeichen als dl.
d+ (d1d2 -- d3) 83 "d-plus"
dl und d2 addiert ergibt d3.
d- {di d2 -= d3) "d-minus"
d2 minus di ergibt d3.
d* ( Ada" 49)) "d-times"
di multipliziert mit d2 ergibt d93.
d= (di d2 -- flag ) "d-equal"
Wenn dl gleich d2 ist, ist flag wahr.
d< (dıd2 -- flag ) 83 "d-less-than"
Wenn di kleiner als d2 ist, ist flag wahr.
deß= (d -- flag) 83 "d-zero-equals"
Wenn d gleich Null ist, ist flag wahr.
m* (nin2--d) "m-times"
Der Wert von nl wird mit n2 multiplizert und d ist das doppelt genaue
Produkt.
um* (ulu2 -- ud) 83 "u-m-times"
Die Werte ul und u2 werden mulitpliziert und das ergibt das doppelt ge-
naue Produkt ud. UM* ist die anderen multiplizierenden Worten zugrunde-
liegende Routine.
m/mod (dnl--n2n3) "m-divide-mod"
n2 ist der Rest und n3 der Quotient aus der Division der doppelt ge-
nauen Zahl d durch den Divisor nl. Der Rest n2 hat dasselbe Vorzeichen
wie nl oder ist Null. Eine Fehlerbedingung besteht, wenn der Divisor Null
ist oder der Quotient außerhalb des Intervalls (-32768..32767) liegt.
= 84. Arithmetik
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ud/mod (udl ul -- u2 ud2 ) "u-d-divide-mod"
u2 ist der Rest und ud2 der doppelt genaue Quotient aus der Divison der
doppelt genauen Zahl udl durch den Divisor ul. Die Zahlen u sind vor-
zeichenlose 16-Bit Werte (unsigned integer). Eine Fehlerbedingung be-
steht, wenn der Divisor Null ist.
um/mod (udul -- 2 u) 83 "u-m-divide-mod"
u2 ist der Rest und u3 der Quotient aus der Division von ud durch den
Divisor ul. Die Zahlen u sind vorzeichenlose Zahlen. Eine Fehlerbe-
dingung besteht, wenn der Divisor Null ist oder der Quotient außerhalb
des Intervalls (8..65535) liegt.
3.5 Stack-Operationen
Herkömmliche Programmiersprachen enthalten mehr oder weniger ausgeprägt das
Konzept der PROZEDUREN:
Für bestimmte Programmfunktionen notwendige Operatoren werden in benannten
Programmteilen zusammengefaßt, um diese Programmfunktionen an mehreren Stellen
innerhalb eines Programmes über ihren Namen aktivieren zu können. Da FORTH
ohne jede Einschränkung prozedural ist, macht FORTH auch keinen Unterschied
zwischen Prozeduren und Funktionen oder seinen Operatoren. Alles wird als ein
WORT bezeichnet.
FORTH als Programmier-SPRACHE besteht also aus Wörtern.
Somit können FORTH-Wörter sein:
1. Datenbereiche
2. Algorithmen (Befehle)
3. Programme
Um Prozeduren sinnvoll benutzen zu können, kennen die meisten Sprachen auch
PARAMETER:
Dies sind Daten, die einer Prozedur bei ihrem Aufruf zur Bearbeitung übergeben
werden. Daten, die ausschließlich innerhalb einer Prozedur benötigt werden, heißen
LOKAL zu dieser Prozedur; im Gegensatz dazu nennt man Daten, die außerhalb von
bestimmten Prozeduren zur Verfügung stehen und auf die von allen Prozeduren aus
mit allen Operatoren zugegriffen werden kann, GLOBAL.
Die erste Möglichkeit der Parameterübergabe zwischen Prozeduren ist die Verein-
barung von benannten GLOBALEN Variablen. Diese globalen Variablen sind für die
gesamte Laufzeit des Programmes statisch existent und können von allen Proze-
duren manipuliert werden.
Eine andere Möglichkeit der Parameterübergabe besteht im Einrichten eines Spei-
cherbereiches, in dem während das Aufrufes eines Wortes namentlich benannte
Parameter dynamisch verwaltetet werden.
Diesen Mechanismus für benannte lokale Variable stellt Standard-FORTH nicht zur
Arithmetik =rgBbr-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Verfügung, weil die Organisation dieser lokalen Variablen mit einem Verlust sowohl
der lokalen Daten nach der Ausführung des Wortes als auch einem Verlust in der
Ausführungsgeschwindigkeit des Wortes verbunden sind. Für das volks4TH wurde in
der VD 1/88 eine Implementierung benannter lokaler Variabler vorgestellt.
FORTH benutzt zur gegenseitigen Übergabe von Parametern an Wörter hauptsächlich
den STACK, einen bestimmten Speicherbereich, in dem die Wörter ihre Parameter er-
warten. Diese Parameter erhalten keine Namen, sondern ihre Interpretation ergibt
sich aus der Position innerhalb des Stack-Speicherbereiches. Daraus resultiert die
vielzahl von Operatoren zur Änderung der Stack-Position eines Wertes, für die
FORTH berühmt/berüchtigt ist.
Damit deutlich wird, welche und wieviele Parameter ein Wort benötigt, werden all- 5
gemein STACK-KOMMENTARE verwendet:
Der öffnenden runden Klammer folgt eine Aufzählung der Parameter. Dabei steht
der Parameter, der als oberstes Stack-Element erwartet wird, ganz rechts. Dann
folgt ein " -- ", das die Ausführung des Wortes symbolisieren soll. Anschließend
wird der Zustand des Stacks nach der Ausführung des Wortes dargestellt, wobei das
oberste Stackelement wieder ganz rechts steht. Die schließende. runde Klammer
beendet den Stack-Kommentar.
Ein Wort SQRT, das die Quadratwurzel einer Integerzahl liefert, würde in FORTH so
benannt und beschrieben:
sqrt (number -- sart )
Wird dieses neue Wort aufgerufen, so werden alle darin enthaltenen Wörter
ausgeführt, eventuell bereitgestellte Parameter bearbeitet und daraus resultierende
Ergebnisse auf dem Stack übergeben.
Der Aufruf von Prozeduren erfolgt in FORTH implizit durch die Nennung des
Namens, ebenso wie auch die Datenübergabe zwischen Wörtern meist implizit erfolgt.
3.5.1 Datenstack-Operationen
drop ( 16b --) 83
Der Wert 16b wird vom Stack entfernt.
2drop 82h #=+ ) 83 "two-drop"
Der Wert 32b wird vom Stack entfernt.
dup ( 16b -- 16b i6b ) 83
Der Wert 16b wird dupliziert.
gon® Arithmetik
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
?dup
2dup
swap
2swap
nip
over
2over
under
rot
-rot
roll
roll
( 16b -- 16b 16b ! 8) 83 "question-dup"
Nur wenn der Wert 16b von Null verschieden ist, wird er verdoppelt.
( 32b -- 32b 32b ) 83 "two-dup"
Der Wert 32b wird dupliziert.
{ 16b1 16b2 -- 16b2 16bl ) 83
Die beiden obersten 16-Bit Werte werden vertauscht.
( 32b1 32b2 -- 32b2 32b1 ) 83 "two-swap"
Die beiden obersten 32-Bit Werte 32b1l und 32b2 werden vertauscht.
{ 16bl 1652 -- 16b2:)
Der Wert 16bl, der unter 16b2 auf dem Stack liegt, wird vom Stack
entfernt.
( 16b1 16b2 -- 16b1l 16b2 16b1 ) 83
Der Wert 16b1l wird über 16b2 herüberkopiert.
( 32b1 32b2 -- 32b1l 32b2 31bl ) "two-over"
Der Wert 32b1 wird über den Wert 32b2 herüber kopiert.
( 16b1 16b2 -- 16b2 16b1 16b2 )
Eine Kopie des obersten Wertes auf dem Stack wird unter dem zweiten
Wert eingefügt.
( 16b1 16b2 16b3 -- 16b2 16b3 16bl1 ) 83
Die drei obersten Werte auf dem Stack werden rotiert, sodaß der unterste
zum obersten wird.
( 16b1 16b2 16b3 -- 16b3 16bl 16b2 ) "minus-rot"
Die drei obersten 16b Werte werden rotiert, sodaß der oberste Wert zum
Untersten wird. Hebt rot auf.
( 16bn 16bm..16b@ +n -- 16bm..16bd 16bn ) 83
Das +n-te Glied einer Kette von n Werten wird nach oben auf den Stack
gerollt. Dabei wird +n selbst nicht mitgezählt.
( 16bn .. 16bl 16b® +n -- 16b8 16bn .. 16bl )
Das oberste Glied einer Kette von +n Werten wird an die n-te Position
gerollt. Dabei wird +n selbst nicht mitgezählt.
2 -roll wirkt wie -rot ,„ ® -roll verändert nichts.
Arithmetik u
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
pick { 16bn..16b8 +n -- 16bn..16b® 16bn ) 83
Der +n-te Wert auf dem Stack wird nach oben auf den Stack kopiert.
Dabei wird +n selbst nicht mitgezählt.
8 pick wirkt wie dup , 1 pick wie over.
.S (--) "dot-s"
Gibt alle Werte, die auf dem Stack liegen aus, ohne den Stack zu ver-
ändern. Oft benutzt, um neue Worte auszutesten. Die Ausgabe der Werte
erfolgt von links nach rechts, der oberste Stackwert zuerst, so daß der
top of stack (tos) ganz links steht!
clearstack Goa ==)
Löscht den Datenstack. Alle Werte, die sich vorher auf dem Stack befan-
den, sind verloren,
depth ("-n)
n ist die Anzahl der Werte, die auf dem Stack lagen, bevor DEPTH ausge-
führt wurde.
sd ( -- addr ) "s-zero"
addr ist die Adresse einer Uservariablen, in der. die Startadresse des
Stacks steht. Der Ausdruck s® @ sp! wirkt wie clearstack und leert
den Stack.
sp! ( addr -- ) "s-p-store"
Setzt den Stackzeiger (stack pointer) auf die Adresse addr. Der oberste
Wert auf dem Stack ist dann der, welcher in der Adresse addr steht.
sp@® ( -- addr ) "s-p-fetch"
Holt die Adresse addr aus dem Stackzeiger. Der oberste Wert im Stack
stand in der Speicherstelle bei addr, bevor sp@ ausgeführt wurde.
3.5.2 Returnstack-Operationen
rdepth (--n) "r-depth"
n ist die Anzahl der Werte, die auf dem Returnstack liegen.
»r (16b --) c,83 "to=r"
Der Wert 16b wird auf den Returnstack gelegt. Siehe auch RD.
r> C--166) 0,83 "r-from"
Der Wert 16b wird vom Returnstack geholt. Vergleiche R>.
= 38 - Arithmetik
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
rdrop
ro
— rp®
rp!
push
( -- 16b ) c,83 "r-fetch"
Der Wert 16b ist eine Kopie des obersten Wertes auf dem Returnstack.
==) © "r-drop"
Der oberste Wert wird vom Returnstack entfernt. Der Datenstack wird
nicht verändert. Entspricht der Operation r> drop.
( -- addr ) U "r-zero"
addr ist die Adresse einer Uservariablen, in der die Startadresse des
Returnstacks steht.
( ==eiaddr ) "r-p-fetch"
Holt die Adresse addr aus dem Returnstackzeiger. Der oberste Wert im
Returnstack steht in der Speicherstelle bei addr.
(addr. ==) "r-p-store"
Setzt den Returnstackzeiger (return stack pointer) auf die Adresse addr.
Der oberste Wert im Returnstack ist nun der, welcher in der Speicher-
stelle bei addr steht.
( addr -- )
Der Inhalt aus der Adresse addr wird bis zum nächsten EXIT oder
auf dem Returnstack verwahrt und sodann nach addr zurückgeschrieben.
Dies ermöglicht die lokale Verwendung von Variablen innerhalb einer
:-Definition. Wird z.B. benutzt in der Form :
: hex. (n--) base push hex.;
Hier wird innerhalb von HEX. in der Zahlenbasis HEX gearbeitet, um
eine Zahl auszugeben. Nachdem HEX. ausgeführt worden ist, besteht die
gleiche Zahlenbasis wie vorher, durch HEX wird sie also nur innerhalb
von HEX. verändert.
Arithmetik =99--
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
4. Kontrollstrukturen
4.1 Programm-Strukturen
wil Baden, auf den Sie in der englischsprachigen Literatur oft stoßen, hat in
seinem Beitrag ESCAPING FORTH folgendes dargelegt:
Es gibt vier Arten von Steueranweisungen :
- die Abfolge von Anweisungen,
- die Auswahl von Programmteilen,
- die Wiederholung von Anweisungen und Programmteilen
- den Abbruch.
Die ersten drei Möglichkeiten sind zwingend notwendig und in den älteren Sprachen
wie PASCAL ausschließlich vorhanden. Entsprechend steht im volksFORTH eine
Anweisung für die Auswahl von Programmteilen zur Verfügung, wobei die
Ausführung vom Resultat eines logischen Ausdrucks abhängig gemacht wird:
flag IF <Anweisungen)> THEN
flag IF <Anweisungen)> ELSE <Anweisungen> THEN
Soll dagegen im Programm ein Rücksprung erfolgen, um Anweisungen wiederholt
auszuführen, wird bei einer gegebenen Anzahl von Durchläufen diese Anweisung
eingesetzt, wobei der aktuelle Index über I und J zur Verfügung steht:
“Grenzen? DO / ?DO <Anweisungen) LOOP
“Grenzen? DO / ?DO <Anweisungen)> (Schrittweite) +LOOP
Wenn eine Wiederholung von Anweisungen ausgeführt werden soll, ohne daß die
Anzahl der Durchläufe bekannt ist, so ist eine Indexvariable mitzuführen oder
sonstwie zum Resultat eines logischen Ausdrucks zu kommen. Die folgende Kon-
struktion ermöglicht eine Endlos-Schleife;
BEGIN <Anweisungen)> REPEAT
Die Wiederholungsanweisungen sind insoweit symmetrisch, daß eine Anweisung so-
lange (while) ausgeführt wird, wie ein Ausdruck wahr ist, oder eine Anweisung
wiederholt wird, bis (until) ein Ausdruck wahr wird.
BEGIN <Anweisungen> flag UNTIL
BEGIN (Anweisungen) flag WHILE (Anweisungen) REPEAT
Beide Möglichkeiten lassen sich in volksFORTH auch kombinieren, wobei auch
mehrere (multiple) WHILE in einer Steueranweisung auftreten dürfen.
BEGIN “Anweisungen? flag WHILE (Anweisungen) flag UNTIL
Nun tritt in Anwendungen häufig der Fall auf, daß eine Steueranweisung verlassen
werden sol), weil sich etwas ereignet hat.
=.40.= Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Dann ist die vierte Situation, der Abbruch, gegeben. C stellt dafür die Funktionen:
break, continue, return und exit zur Verfügung; volksFORTH bietet hier exit
leave endloop quit abort abort" und abort( an.
In FORTH wird EXIT dazu benutzt, um die Definition zu verlassen, in der es er-
scheint; LEAVE dagegen verläßt die kleinste umschließende DO...LOOP-Schleife.
Glossar
Ab der Version 3.81.3 verfügt volksFORTH über eine zusätzliche Steueranweisung
für den Compiler, die bedingte Kompilierung in der Form:
have <word) not .IF <actioni) .ELSE <action2) „THEN
Diese Worte werden außerhalb von Colon-Definitionen eingesetzt und ersetzen das
\needs früherer Versionen.
have ( -- flag )
prüft, ob ein Wort im Wörterbuch in der Suchreihenfolge existiert und
hinterläßt ein entsprechendes Flag. In der Literatur und in Quelltexten
findet man auch exists? als Synonym.
exit (--)
ist ein Synonym für unnest .
Dieses wird von ";" (Semicolon) als Abschluß einer Colondefinition compi-
liert. Ebenso dient EXIT als Austritt aus einem Wort, wobei das Programm
in der aufrufenden Ebene fortgesetzt wird (return to caller).
Ein EXIT ist innerhalb von DO..LOOP-Strukturen nicht ohne weiteres
möglich (siehe endloop).
Diese Steueranweisung ist nicht umkehrbar, der Sprung in eine hier-
archisch niedrigere Ebene ist nicht erlaubt.
Typisch: flag IF exit THEN
?exit {flag --) "question-exit"
führt EXIT aus, falls das Flag wahr ist. Ist das Flag falsch, so ge-
schieht nichts. Hierbei soll daran erinnert werden, daß jede Zahl ungleich
NULL als wahr interpretiert wird.
Entspricht: true IF exit THEN
ö=exit tag —) "zero-equals-exit"
führt EXIT aus, falls das Flag falsch ist. Ist das Flag wahr, so geschieht
nichts. Es entspricht 0= IF exit THEN und wird typisch so eingesetzt:
key #cr - O=exit
Kontrollstrukturen = GR -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
IE (flag --) 83,1,C
(--sys) compiling
wird in der folgenden Art benutzt;
flag IF ... ELSE ... THEN
oder: flag IF ... THEN
Ist das Flag wahr, so werden die Worte zwischen IF und ELSE ausgeführt
und die Worte zwischen ELSE und THEN ignoriert.
Der ELSE-Teil ist optional. Ist das Flag falsch, so werden die Worte
zwischen IF und ELSE (bzw. zwischen IF und THEN , falls ELSE nicht
vorhanden ist) ignoriert.
Je ist das IF für den Interpretermodus.
THEN (==) 83,1,C
(sys --) compiling
wird in der folgenden Art benutzt:
IF (...ELSE) ... THEN
Hinter THEN ist die Programmverzweigung zuende. .
Weil viele FORTH-Freunde die "alte" Schreibweise vor der Festlegung des
83er Standards besser und deutlicher finden, sei hier die Definition von
ENDIF gezeigt:
' THEN Alias ENDIF immediate restrict
.THEN ist das THEN für den Interpretermodus.
ELSE (--) 83,1,C
( sysi -- sys2 ) compiling
wird in der foigenden Art benutzt:
flag IF ... ELSE ... THEN
ELSE wird unmittelbar nach dem Wahr-Teil, der auf IF folgt, ausge-
führt. ELSE setzt die Ausführung unmittelbar hinter THEN fort.
ELSE ist das ELSE für den Interpretermodus.
DO (ww--) 83,1,C
(sys --) compiling
beginnt eine Schleife und entspricht somit ?DO , jedoch wird der
Schleifenrumpf mindestens einmal durchlaufen. Der Schleifenindex beginnt
mit w2, Grenze ist wl..
Ist wl1=w2 , so wird der Schleifenrumpf 65536-mal durchlaufen.
I
En
D
!
Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
?DO
LOOP
+LOOP
leave
(wlw2 --) 83,1,C "question-do"
(--sys ) compiling
wird in der folgenden Art benutzt:
?DO ... LOOP bzw. ?DO ... +LOOP
Beginnt eine Schleife. Der Schleifenindex beginnt mit w2, Limit ist wl. .
Ist w2=wl, so wird der Schleifenrumpf überhaupt nicht durchlaufen.
Für Details über die Beendigung von Schleifen siehe +LOOP
(==) 83,1,C
( --sys ) compiling
entspricht +LOOP, jedoch mit einer festen Schrittweite von 1.
(n--) 83,1,C "plus-loop"
(sys--) compiling
Die Schrittweite n wird zum Loopindex addiert. Falls durch die Addition
die Grenze zwischen limit-1 und limit überschritten wurde, so wird die
Schleife beendet und die Loop-Parameter werden entfernt. Wurde die
Schleife nicht beendet, so wird sie hinter dem korrespondierenden DO
bzw. ?DO fortgesetzt.
(--w) 83,C
wird zwischen DO und LOOP benutzt, um eine Kopie .des Schleifenindex
auf den Stack zu holen.
(--w) 83,C
wird in zwei geschachtelten DO...LOOP-Schleifen zwischen DO .. DO und
LOOP .. LOOP benutzt, um eine Kopie des Schleifenindex der äusseren
Schleife auf den Stack zu holen.
(=) 83,C
beendet die zugehörige Schleife und setzt die Ausführung des Programmes
hinter dem nächsten LOOP oder +LOOP fort. Mehr als ein LEAVE pro
Schleife ist möglich, ferner kann LEAVE zwischen anderen Kontroll-
strukturen auftreten. Der FORTH83-Standard schreibt abweichend vom
volksFORTH vor, daß LEAVE ein immediate Wort ist.
Kontrollstrukturen - 48 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
endloop ( ==
ermöglicht ein EXIT innerhalb einer DO...LOOP. Es wird so eingesetzt:
(Grenzen)DO "
“Anweisungen)
flag IF endloop exit THEN
LOOP
Damit kann exit auch in einer DO...LOOP-Schleife verwendet werden,
vorausgesetzt, Sie halten sich an zwei Regeln:
1. Sie dürfen das System nicht mit Returnstack-Manipulatio-
nen aus dem Gleichgewicht gebracht haben.
2, Bei geschachtelten DO...LOOP-Schleife muß für jede Schlei-
fenebene ein endloop dem abbrechenden exit vorangehen.
In der Literatur findet man auch UNDO als Synonym für ENDLOOP.
bounds ( start count -- limit start )
dient dazu, ein Intervall, das durch Anfangswert und Länge gegeben ist,
in ein Intervall umzurechnen, das durch Anfangswert und Endwert+i1
beschrieben wird. Beispiel:
106 3 bounds DO...LOOP
führt dazu, das I die Werte 18 11 12 annimmt.
BEGIN (==) 4 83,1,C
(sys --- ) compiling
wird in der folgenden Art benutzt:
BEGIN ( ...£lag WHILE ) ... flag UNTIL
oder: BEGIN ( ...£flag WHILE ) ... REPEAT
BEGIN markiert den Anfang einer Schleife. Der ()-Ausdruck ist optional
und kann beliebig oft auftreten. Die Schleife wird wiederholt, bis das
Flag vor UNTIL wahr oder oder das Flag vor WHILE falsch ist. REPEAT
setzt die Schleife immer fort.
Die Schleife BEGIN <Anweisungen) flag UNTIL wird immer mindestens
einmal durchlaufen, da die Abbruchbedingung erst nach dem ersten
Durchlauf geprüft wird.
Um dazu vollständige Symmetrie zu erreichen, kann im Ausdruck
BEGIN <action)> flag WHILE.<action) REPEAT
der Anweisungsteil vor WHILE entfallen:
BEGIN flag WHILE <Anweisungen)? REPEAT
prüft die Abbruchbedingung vor dem Eintritt in die Schleife.
= 44 = Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
REPEAT
UNTIL
WHILE
execute
perform
case?
==) 83,1,C
(--sys) compiling
wird in der folgenden Form benutzt:
BEGIN (.. WHILE) .. REFEAT
REPEAT setzt die Ausführung der Schleife unmittelbar hinter BEGIN fort.
Der ()-Ausdruck ist optional und kann beliebig oft auftreten. Deshalb
gibt es kein AGAIN , benutzen Sie statt dessen REPEAT oder
definieren: ' REPEAT Alias AGAIN immediate restrict
(flag -- ) 83,1,C
(sys -- ) compiling
wird in der folgenden Art benutzt:
BEGIN (... flag WHILE) ... flag UNTIL
Markiert das Ende einer Schleife, deren Abbruch durch flag herbeigeführt
wird. Ist das Flag vor UNTIL wahr, so wird die Schleife beendet, ist es
falsch, so wird die Schleife unmittelbar hinter BEGIN fortgesetzt.
(flag --) 83,1,C
( sysl -- sys2 ) compiling
wird in der folgenden Art benutzt:
BEGIN .. flag WHILE .. REPEAT
oder: BEGIN .. flag WHILE .. flag UNTIL
Ist das Flag vor WHILE wahr, so wird die Ausführung der Schleife bis
UNTIL oder REPEAT fortgesetzt, ist es falsch, so wird die Schleife be-
endet und das Programm hinter UNTIL bzw. REPEAT fortgesetzt. Es kön-
nen mehrere WHILE in einer Schleife verwendet werden.
( addr -- ) 83
Das Wort, dessen Kompilationsadresse addr ist, wird ausgeführt.
( addr -- )
addr ist eine Adresse, unter der sich ein Zeiger auf die Kompilations-
adresse eines Wortes befindet. Dieses Wort wird ausgeführt. Entspricht
der Sequenz @ execute .
( 16bl 16b2 -- 16b1 false ! true ) "case-question"
vergleicht die beiden Werte 16bl und 16b2 miteinander.
Sind sie gleich, verbleibt TRUE auf dem Stack. Sind sie verschieden, ver-
bleibt FALSE und der darunterliegende Wert 16bl auf dem Stack.
Wird z.B. in der folgenden Form benutzt :
key
Ascii a case? IF ... exit THEN
Ascii b case? IF ... exit THEN
drop
Kontrollstrukturen u a
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
stop?
(-- flag ) "stop-question"
ist ein komfortables Wort, das es dem Benutzer gestattet, einen Pro-
grammablauf anzuhalten oder zu beenden,
Steht vom Eingabegerät ein Zeichen zur Verfügung, so wird es eingelesen.
Ist es #ESC oder CTRL-C , so ist flag TRUE, sonst wird auf das nächste
Zeichen gewartet. Ist dieses jetzt #ESC oder CTRL-C , so wird STOP? mit
TRUE verlassen, sonst mit FALSE.
Steht kein Zeichen zur Verfügung, so ist das Flag FALSE . STOP? prüft
also einen Tastendruck auf #ESC oder CTRL-C .
4.2 Worte zur Fehlerbehandlung
Diese arbeiten auch wie Steueranweisungen, wie die Definitionen von ARGUMENTS
und IS-DEPTH zeigen:
is-depth (n--)
depth 1- - abort" falsche Parameterzahl!" ;
IS-DEPTH überprüft den Stack auf eine gegebene Anzahl Stackelemente (depth) hin.
abort (=>n 83,1
leert den Stack, führt END-TRACE 'ABORT STANDARDI/O und QUIT
aus.
'abort (==) "tick-abort"
ist ein deferred Wort, das mit NOOP vorbesetzt ist. Es wird in ABORT
ausgeführt, bevor QUIT aufgerufen wird.
abort" ( flag ) 83,1,C "abort-quote"
(==) compiling
wird in der folgenden Form benutzt:
flag Abort" ccc"
Wird ABORT" später ausgeführt, so geschieht nichts, "wenn: das Flag
falsch ist. Ist das Flag wahr, so wird der Stack geleert und der Inhalt
von ERRORHANDLER ausgeführt. Beachten Sie bitte, daß im Gegensatz zu
ABORT kein END-TRACE ausgeführt wird.
error" ( flag ) L,C "error-quote"
(=) compiling
Dieses Wort entspricht ABORT" , jedoch mit dem Unterschied, daß der
Stack nicht geleert wird.
- 46 - Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
errorhandler € -- addr )
addr ist die Adresse einer Uservariablen, deren Inhalt die Kompilations-
adresse eines Wortes ist. Dieses Wort wird ausgeführt, wenn das Flag, das
ABORT" bzw. ERROR" verbrauchen, wahr ist. Der Inhalt von
ERRORHANDEER ist normalerweise (ERROR.
(error ( string -- ) "paren-error"
Dieses Wort steht normalerweise in der Variablen ERRORHANDLER und
wird daher bei ABORT" und ERROR" ausgeführt. string ist dann die
Adresse des auf ABORT" bzw. ERROR" folgenden Strings. (ERROR gibt das
letzte Wort des Quelltextes gefolgt von dem String auf dem Bildschirm
aus. Die Position des letzten Wortes im Quelltext, bei dem der Fehler
auftrat, wird in SCR und R# abgelegt.
T# ( -- addr ) "r-sharp"
addr ist die Adresse einer Variablen, die den Abstand des gerade edi-
tierten Zeichens vom Anfang des gerade editierten Screens enthält.
Vergleiche (ERROR und SCR .
ser ( -- addr ) 83 "s-c-r"
addr ist die Adresse einer Variablen, die die Nummer des gerade
editierten Screens enthält.
Vergleiche R# ,„ (ERROR und LIST.
quit (==) "quit"
entleert den Returnstack und schaltet den interpretierenden Zustand ein.
?pairs (nin2 --) "question-pairs"
Ist nl <> n2 ,„ so wird die Fehlermeldung "unstructured" ausgegeben.
Dieses Wort wird benutzt, um die korrekte Schachtelung der Kontroll-
strukturen zu überprüfen.
4.3 Fallunterscheidung in FORTH
4.3.1 Strukturierung mit IF ELSE THEN / ENDIF
An dieser Stelle soll kurz die vielfältigen Möglichkeiten gezeigt werden, mit denen
eine Fallunterscheidung in FORTH getroffen werden kann. Kennzeichnend für eine
solche Programmsituation ist, daß von verschiedenen Möglichkeiten des Programm-
flusses genau eine ausgesucht werden soll.
Kontrollstrukturen - 47 -
FORTH-Gesellschaft e.V. PC-voliksFORTH83 rev. 3.81
Ausgehend von einer übersichtlichen Problemstellung, einem Spiel, werden die not-
wendigen Grundlagendefinitionen und die Entwicklung der oben beschriebenen
Kontrollstruktur beschrieben.
Als Beispiel dient ein Spiel mit einfachen Regeln:
Bei diesem Trinkspiel, das nach [1] auch CRAPS genannt wird, geht es darum, einen
Vorrat von gefüllten Gläsern unter den Mitspielern mit Hilfe des Würfels zu ver-
teilen und leerzutrinken:
- Bei einer EINS wurde ein Glas aus dem Vorrat in der Tischmitte ge-
nommen und vor sich gestellt.
_ Bei einer ZWEI oder einer DREI bekam der Nachbar/ die Nachbarin
links ein Glas des eigenen Vorrates zugeschoben.
Bei einer VIER oder einer FÜNF wurde dem Nachbarn/ der Nachbarin
rechts ein Glas des eigenen Vorrates vorgesetzt.
- Bei einer SECHS wurden alle Gläser, die der Spieler/ die Spielerin
vor sich stehen hatte, leergetrunken.
Zuordnung ist also: I=nehmen, 2/3=links, 4/5=rechts, 6=trinken und entsprechend
der Augenzahl des Würfels soll eine der 6 möglichen Aktionen ausgeführt werden.
Das Programm soll sich darauf beschränken, das Ergebnis dieses Würfelns einzu-
lesen und auszuwerten. Daraufhin wird eine Meldung ausgegeben, welche der sechs
Handlungen auszuführen ist.
Für ein solches Programm ist eine Zahleneingabe notwendig. Diese wurde hier mit
dem Wort F83-NUMBER? realisiert:
: F83-number? ( string --d£f)
number? ?dup
IF
0< IF extend THEN
true exit
THEN
drop 08 false ;
: input# ( <string® -- n)
pad c/1l 1- >expect
pad F83-number? 2drop ;
Die Definition der Wörter, die sechs oben genannten Aktionen symbolisch aus-
führen sollen, richtet sich nach den Spielregeln. die für jedes Würfelergebis genau
eine Handlung vorschreiben:
\ nehmen trinken links rechts schieben
: nehmen bright .” ein Glas nehmen” normal 2 spaces ;
ı trinken bright ." alle Gläser austrinken" normal 2 spaces ;
: links bright ." ein Glas nach LINKS" normal 2 spaces ;
: rechts bright ." ein Glas nach RECHTS" normal 2 spaces ;
: schieben
- 48 - Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
SCHIEBEN ist eine Dummyprozedur, ein Füllsel, dessen Notwendigkeit sich erst sehr
spät ergibt.
Für den Dialog mit dem Anwender wird definiert:
: Anfrage er ." Sollen Sie nehmen, trinken oder schieben? "
er ." Bitte Ihre Augenzahl und (cr) : " ,
: Glückwunsch cr ." Viel Glück beim nächsten Wurf ... " ;
Das Wort AUSWERTUNG soll entsprechend einem Selektor genau eine von 6 mög-
lichen Prozeduren ausführen. Also wird man prüfen, ob diese oder diese oder ... der
Möglichkeiten in Frage kommt. Hinzu kommt noch die Prüfung, ob der übergebene
Parameter zwischen (between) 1 und 6 lag.
Die Definition von BETWEEN ist volksFORTH-gemäß recht kurz:
Wert Untergrenze Obergrenze -- false oder )
(
( -- true wenn Untergrenze<Wert<sObergrenze )
: between 1+ wwithin ;
: Auswertung.i ( Wurfergebnis -- )
dup 1 = IF nehmen ELSE
dup 2 = IF links schieben ELSE
dup 3 = IF links schieben ELSE
dup 4 = IF rechts schieben ELSE
dup 5 = IF rechts schieben ELSE
dup 6 = IF trinken THEN
THEN
THEN
THEN
THEN
THEN
1 6 between not IF invers ." Betrug!" normal THEN ;
Ein Verzicht auf den ELSE-Teil führt schon zu einer übersichtlicheren Form:
: Auswertung.2 ( Wurfergebnis --)
dup 1 = IF nehnen THEN
dup 2 = IF links schieben THEN
dup 3 = IF links schieben THEN
dup 4 = IF rechts schieben THEN
dup 5 = IF rechts schieben THEN
dup 6 = IF trinken THEN
1 6 between not IF inverse ." Betrug!" normal THEN ;
Da eine solche Prüfung auf Gleichheit in der Programmierpraxis oft vorkommt, stellt
das volks4TH dafür das Wort case? zur Verfügung. case? vergleicht die obersten
beiden Stackwerte miteinander. Bei Ungleichheit bleibt der Testwert (Selektor)
erhalten, so daß die Worte DUP und = dadurch ersetzt werden.
: Auswertung.3 { Wurfergebnis -- }
case? IF nehmen exit THEN
case? IF links schieben exit THEN
case? IF links schieben exit THEN
case? IF rechts schieben exit THEN
case? IF rechts schieben exit THEN
bmw
Kontrollstrukturen - 49 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.31
6 case? IF trinken exit THEN
drop invers ." Betrug!" normal v
Bei dieser Auswertung wird aus dem Quelltext zu wenig deutlich, daß bei ZWEI
und DREI dieselbe Handlung ausgeführt wird, wie auch VIER und FÜNF die glei-
chen Aktionen zur Folge haben.
=OR prüft deshalb einen Testwert n2 auf Gleichheit mit einer unter einem Flag fl
liegenden Zahl n2. Das Ergebnis dieses Tests wird mit dem bereits vorliegenden
Flag OR-verknüpft. Dieses neue Flag f2 und der Testwert nl werden übergeben:
code =or {nl fin2 --n1£2)
AD xchg D pop
SWnov
W)Acmp
= ?[ -1 #Dnov )?
next
end-code
\:=or (nl fin2--ni f2) 2pick=or ;
Dieses Wortes bringt im Quelltext eine deutliche Verbesserung:
: Auswertung.4 ( Wurfergebnis --)
dup
1 6 between IF
dup 1 = IF nehnen THEN
dup 2 = 3 =or IF links schieben THEN
dup 4 = 5 =or IF rechts schieben THEN
dup 6 = IF trinken THEN
ELSE
invers ." Betrug!" nornal
THEN
drop :
Damit wurde ohne eine CASE-Anweisung eine sehr übersichtliche Steuerung des
Programm-Flusses geschaffen. :
Die Plausibilitätsprüfung, ob die eingegeben Zahl zwischen 1 und 6 lag, ist hier an
den Anfang gerückt und wird in einem einzigen ELSE-Zweig abgearbeitet.
4.3.2 Behandlung einer CASE - Situation
4.3.2.1 Strukturelles CASE
Viele Programmiersprachen eine CASE-Anweisung zur Verfügung, die wie in PASCAL
mit Hilfe eines Fall-Indices eine Liste von Fall-Konstanten auswertet und eine
entsprechende Anweisung ausführt. |
Obwohl ein solches CASE-Konstrukt - wie oben gezeigt - nicht notwendig ist,
macht es Programme besser lesbar und liegt bei Problemstellungen wie der Auswer-
- BR Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
tung eines gegebenen Index eigentlich näher.
Dies ist in [1] ausführlich diskutiert worden, wobei aber der ältere Eaker-CASE f2}
von Dr. Charles Eaker sicherlich der bekanntere ist, der auch in der Literatur und
in Quelltexten häufig Erwähnung und Verwendung findet.
Herr H. Schnitter hat diesen Eaker-CASE für das volks4TH implementiert und dabei-
Veränderungen in der Struktur und Verbesserungen in der Anwendung vorgenommen.
\ caselist initlist »marklist »resolvelist
t variable caselist
I : initlist ( list -- addr )
dup @ swap off
.
t : >narklist (list -- )
here over @ , swap !
t : >resolvelist ( addr list -- )
BEGIN dup @
WHILE dup dup @ dup @ rot ! )resolve
REPEAT !
\ case elsecase endcase
CASE caselist initlist 4
imnediate restrict
.
ELSECASE A ?pairs
compile drop 6
immediate restrict
>
ENDCASE dup 4 =
IF drop compile drop
ELSE 6 ?pairs
THEN caselist >resolvelist
; immediate restrict
\ o£ endof
: OF 4 ?pairs
compile over
conpile =
compile ?branch
»mark compile drop 5
immediate restrict
Er
: ENDOF 5 ?pairs
compile branch
caselist >marklist
Yresolve 4
; immediate restrict
Kontrollstrukturen -üm-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Diese Implementierung des Eaker-CASE stellt eine Verbesserung gegenüber dem
Original dar, indem Herr Schnitter die Kontrollstruktur um ELSECASE erweitert hat.
Selbstverständlich ist die neue Version vollkommen aufwärtskompatibel mit der
Original-version.
Verbesserung:
In der Originalversion der CASE-Struktur ist es nicht möglich, zwischen dem
letzten ENDOF und ENDCASE einen Wert oder ein Flag auf den Stapel zu legen, da
ENDCASE grundsätzlich den "Top of Stack" entfernte. :
In der verbesserten Version bereinigt ELSECASE den Stapel. ELSECASE muß jedoch
nicht aufgerufen werden; in diesem Fall kompiliert ENDCASE wie bisher ein DROP.
Es ist jetzt möglich, zwischen den Worten ELSECASE und ENDCASE - wie auch
zwischen OF und ENDOF - einen Wert auf den Stapel zu legen und diesen außer-
halb der CASE-Kontrollstruktur zu verwenden.
Änderung:
Die Vorwärtsreferenzen werden nicht über den Stack aufgelöst, sondern über eine
verkettete Liste.
Die Variable caselist enthält die Startadresse für noch nicht bekannte Sprung-
adressen. Die Schachtelungstiefe mehrerer CASE-Konstruktionen ist beliebig und
wird durch initlist gelöst. >marklist füllt zur Kompilierzeit die Liste der Vorwärts-
referenzen und >resolvelist löst sie wieder auf.
Anwendungshinweis:
Wenn diese Definitionen außerhalb der Zusammenstellung des Arbeitssystems zuge-
laden werden, sollten nach dem Compilieren die Namen der mit ! als headerless
markierten Worte mit clear entfernt werden.
Das Beispiel einer Tastatuabfrage auf CTRL-Tasten zeigt , wie dieses CASE-Kon-
strukt einzusetzen ist. Wichtig ist hierbei, daß das OF selbst die Gleichheit der
beiden vorliegenden Werte prüft und in diesem Fall die Anweisungen zwischen OF
und ENDOF ausführt.
: Control bl word 1+ c@ SBF and state @
IF [compile] Literal THEN
; immediate
: Tastaturabfrage
." exit mit ctrl x" cr
BEGIN key
CASE control A OF ." action "a " cr false ENDOF
eontrol B OF ." action "b " cr false ENDOF
control C OF ." action "ce " cr false ENDOF
control D OF ." action "d " cr false ENDOF
control X OF ." exit " true ENDOF
ELSECASE °
." befehl unbekannt " cr false
ENDCASE
UNTIL
nl Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Mit dieser CASE-Anweisung läßt sich die Zuordnung der sechs Möglichkeiten zu den
sechs Anweisungen ähnlich wie in PASCAL schreiben, lediglich Bereiche wie 9..255
als Fall-Konstanten sind nicht erlaubt.
: Auswertung.5 ( Augenzahl -- )
CASE
1 OF nehnen ENDOF
2 OF links schieben ENDOF
3 OF links schieben ENDOF
4 OF rechts schieben ENDOF
5 OF rechts schieben ENDOF
6 OF trinken ENDOF
ELSECASE
invers ." Betrug!" normal
ENDCASE
Das vollständige Programm kann so geschrieben werden, wobei die typische Drei-
teilung Eingabe-Verarbeitung-Ausgabe deutlich wird:
: craps (--)
cr Anfrage cr
input#
Auswertung
cr Glückwunsch
Wil Baden hat in [1} ausgeführt, das eine CASE-Anweisung nur syntaktischer
Zucker für ein Programm ist und letztendlich nichts weiter ist, als das Compilieren
einer verschachtelten IF... THEN-Anweisung.
Eine solche Implemetierung für das volksFORTH83 wurde von Herrn K. Schleisiek-
Kern geschrieben:
\ CASE OF ENDOF ENDCASE BREAK
2 CASE (nl --nint) dup;
: oF (conmpile] IF compile drop ; immediate restrict
: ENDOF [compile) ELSE 4+ ; immediate restrict
: ENDCASE compile drop
BEGIN
3 case?
WHILE
>resolve
REPEAT ; immediate restrict
Wil Badens Implementierung hält sich sehr eng an die logischen Grundlagen, wobei
der Unterschied zum EAKER-CASE hauptsächlich darin besteht, daß hier jedes
TRUE-Flag den Anweisungsteil zwischen OF und ENDOF ausführt; das OF nimmt
keine Prüfung auf Gleichheit vor, sondern beliebige Ausdrücke können zu einem
Flag führen, das dann von OF ausgewertet wird. So ist das Auswerten des Fall-
Index variabler als beim EAKER-CASE:
Kontrollstrukturen =1893.>
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
: Auswertung.6 ( Augenzahl -- )
up
1 6 between not
IF invers ." Betrug!” normal drop exit THEN
CASE 1 = OF nehmen ENDOF
CASE 6 = OF trinken ENDOF
CASE 4 € OF links schieben -ENDOF
CASE 3 > OF rechts schieben ENDOF
ENDCASE ;
Hier bei dieser Konstruktion steht die Plausibilitätsprüfung ganz vorn, um den
ELSECASE-Fall durch ein EXIT aus dem Wort zu erreichen. Wird keines der Worte
aus der Auswahl-Liste ausgeführt, läßt sich mit BREAK eine andere Lösung
erreichen: .
: BREAK compile exit
[compile] THEN ; immediate restrict
Dadurch, daß BREAK ein EXIT aus dem Wort darstellt, wird ein (implizites)
ELSECASE erreichen, indem man die Anweisungen der Auswahl-Liste mit OF und
BREAK klammert und die Anweisungen für den ELSE-Fall nach ENDCASE aufführt:
: Auswertung.? { Augenzahl -- )
CASE 1 = OF nehmen BREAK
CASE 2 = 3 =or OF links schieben BREAK
CASE 4 = 5 =or OF rechts schieben BREAK
CASE 6 = OF trinken BREAK
ENDCASE
invers ." Betrug!" normal ;
4.3.2.2 Positionelles CASE
Eine ganz anderen Lösungsansatz bietet ein positioneller CASE Konstrukt, .bei dem
die Fallunterscheidung durch den Fall-Index tabellarisch vorgenommen wird.
Bei den bisherigen Lösungen wurden immer eine Reihe von Vergleichen zwischen
einem Fall-index und einer Liste von Fall-Konstanten vorgenommen; nun wird der
Fall-Index selbst benutzt, die gewünschte Prozedur auszuwählen. Die Verwendung
des Fall-Index als Selektor: bringt auch Vorteile in der Laufzeit, da die Vergleiche
entfallen.
Wenn FORTH-Worte in Tabellen abgelegt werden sollen, stellt sich das Problem, daß
ein FORTH-Wort bei seinem Aufruf normalerweise die eincompilierten Worte aus-
führt. ,
Bei einer Tabelle ist das nicht erwünscht; dort ist sinnvollerweise gefordert, daß
die Startadresse der Tabelle übergeben wird, um der Fall-Index als Offset in diese
Tabelle zu nutzen.
Dies läßt sich in volksFORTH entweder auf die traditionelle Weise mit |] und [
oder dem volksFORTH-spezifischen Create: lösen: j
l
an
be
!
Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Create Glas
] nehmen links schieben
rechts schieben trinken [
Create: Glas
nehmen
links schieben
rechts schieben
trinken ;
Diese Tabelle Glas macht auch deutlich, welche Funktion das Dummy-Wort
schieben außer einer besseren Lesbarkeit noch hat: Es löst die Schwierigkeit, daß
6 möglichen Wurfergebnissen nur 4 mögliche Aktionen gegenüberstehen.
Die Art und Weise des Zugriffs in BEWEGEN entspricht dem Zugriff auf eine Zahl
“Sin einem eindimensionalen Feld, einem Vektor:
: bewegen ( addr n -- cfa )
2%* + perform ;
se richtig (n -- O<k=n<=3)
swap
1 max 6 min
3 case? IF 2 1- exit THEN
5 case? IF 4 1- exit THEN
12.5
Dieses Wort RICHTIG läßt zwar Werte kleiner als 1 und größer als 6 zu, justiert
sie aber auf den Bereich zwischen 1 und 6 . Auch hier müßte eine Möglichkeit ge-
schaffen werden, ein Wurfergebnis außerhalb der 6 Möglichkeiten als Betrugsversuch-.
zurückzuweisen !
Die Verbindung von Tabelle und Zugriffsprozedur wird von dem Wort :Does> vor-
genommen:
\ :Does) für Create <name) :Does)> (action) ; ks 25 aug 88
I 2 (does) here >r [compile) Does) ;
:Does) last @ 0= Abort" without reference"
(does) current @ context ! hide 0 ] ;
En Dieses Wort :DOES> weist dem letzten über Create definierten Wort einen
Laufzeit-Teil zu. Dieses Wort wurde von Herrn K. Schleisiek-Kern programmiert ;
auch hier gilt der Hinweis, nach dem Compilieren das mit ! als headerless
deklarierte Wort durch clear zu löschen.
Create: Auswertung.8
nehnen
links schieben
rechts schieben
trinken ;
:Does)
richtig bewegen ;
Kontrollstrukturen =TBBr-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Ohne :DOES> sind die Tabelle und die Zugriffsprozeduren voneinander unabhängi-
ge Worte:
2 CRAPSI
cr Anfrage cr
input#
Glas richtig bewegen
er Glückwunsch ;
Entschließt man sich dagegen, sowohl Tabelle als auch Zugriffsprozedur in einem
Wort zu definieren, so ergibt sich das gewohnte Erscheinungsbild:
: CRAPS
cr Anfrage cr
input#
Auswertung
er Glückwunsch ;
Bei häufigerem Einsatz solcher Tabellen bietet sich der Einsatz von positional
CASE defining words an. Auch hier wiederum zuerst die volks4TH-gemäße Lösung
danach die traditionelle Variante:
ı Case: (-)
Create: Does) ( pfa -- ) swap 2* + perform ;
\ alternative Definition für CASE:
: Case:
: Does) ( pfa -- ) swap 2* + perform ;
Eine sehr elegante Möglichkeit, die Fehlerbehandlung im Falle eines unglaubwürdi-
gen Fall-Indexes zu handhaben, bietet das Wort Associative: .
Dieses Wort Associative: durchsucht eine Tabelle nach einer Übereinstimmung
zwischen einem Zahlenwert auf dem Stack und den Zahlenwerten in der Tabelle
und liefert den Index der gefundenen Zahl (match) zurück. Im Falle eines Mißer-
folgs (mismatch) wird der größtmögliche Index +1 (out of range = maxIndex +1)
übergeben:
: Associative: (n--)
Constant Does) {n - index )
dup @ -rot
dup @ ®
DO 2+ 2dup @ = :
IF 2drop drop I 9 © LEAVE THEN
LOOP 2ärop ;
6 Associative: Auswerten
i
vw
4,
6,
ww»
Case: Handeln \ besteht aus :
nehmen
= 664° Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
links links
rechts rechts
trinken
schinpfen ;
Statt der Primitivabsicherung über MIN und MAX wird eine out of range Fehlerbe-
handlung namens schimpfen an der Tabellenposition maxIndex +1 durchgeführt.
4.3.2.3 Einsatzmöglichkeiten
Dieser letzte Teil der Ausführungen über die Möglichkeiten, eine CASE-Situation zu
handhaben, greift Anregungen aus der Literatur [5],[6] auf.
Dazu werden zwei Worte definiert:
CLS löscht den gesamten Bildschirm und
CELLS macht die Berechnung des Tabellenzugriffs deutlicher:
: cls full page ;
ı cells 2” ;
Das Inhaltliche und die tabellarische Struktur bleiben unverändert, lediglich die
Behandlung einer out of range Situation wird diesmal mit min und max und zwei-
maligem Eintragen der Fehler-Routine schimpfen verwirklicht.
Create: Handlung
schinpfen nehmen links links
rechts rechts trinken schimpfen ;
\ Die Ausführung einer Liste nach Floegel 7/86
: auswählen ( addr n -- *cfa ) 2 arguments
swap ® max \ out of range MIN
7 nin \ out of range MAX
cells + ;
: auswerten (n-- ) 1 arguments
Handlung auswählen perform ;
_.ald (—-)
806 DO cr I dup . auswerten 2 spaces LOOP ;
AUSWÄHLEN übergibt bei gegebenem Vektor und gegebenem Index einen Zeiger auf
die code field address des entsprechenden Wortes. AUSWERTEN führt das so
ausgewählte Wort aus und .ALL diente nur zur Kontrolle. Solch ein Wort, das ange-
legte Datenstrukturen auf dem Bildschirm darstellt, sollte in der Entwicklungs-
phasen eines Programmes immer dabei sein.
Eine weitere Möglichkeit, Werte in einen Vektor einzutragen, hat Herr Floegel in
seinem Buch [4] dargestellt:
Create Tabelle 8 cells allot
:Does> ( i -- addr ) swap cells +;
' schimpfen ® Tabelle !
nehmen 1 Tabelle !
Kontrollstrukturen = Bi -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
' links dup 2 Tabelle
3 Tabelle
' rechts dup 4 Tabelle
5 Tabelle
trinken 6 Tabelle
' schimpfen 7 Tabelle
: auswerten (i --) GO max 7 min Tabelle perform ;
: „action (i=®)
Tabelle @ »>name bright .nane normal ;
ı „Tabelle (--) cr 890DO cr I .action LOOP ;
Hier besteht mit .ACTION und .TABELLE die Möglichkeit, sich den Vektor darstellen
zu lassen. In ähnlicher Weise werden auch im Kommandozeilen-Editor CED die
neuen Aktionen in die Eingabe-Vektoren eingetragen.
Eine geringfügige Modifikation von [5] soll die Verknüpfung eines Vektors von Wor-
ten und einer Menü-Option zeigen:
Create function
] noop noop noop noop
noop noop noop noop [
:Does> ( i -- addr )
swap ® max 7 min cells + ;
function ist ein execution vector , der mit NOOP vorbesetzt ist. Zur Laufzeit lie-
fert er die Adresse des indizierten Elementes zurück.
: „action ( i addr -- }
@ >name bright .name normal ;
.WORD gibt den Namen eines Wortes aus, dessen CFA in eine Adresse eingetragen
wurde.
: option (i--)
: r>
dup 2+ >r \i *tw.adädr
@ \iw.addr
stash swap function ! \i w.addr i adär
function .action ; \i addr
option holt die Adresse des auf option folgenden Wortes. Das Wort soll nicht
ausgeführt werden, sondern das nachfolgende. Nur der Pointer auf das Wort soll
ausgewertet werden. Nach dem übergebenen Index wird der Pointer in function
eingetragen. Der Name des so eingetragenen Wortes wird angezeigt !
\ Menü jrg 66feb89
: Menü
6 option schimpfen
1 option nehmen
option links
option links
option rechts
option rechts
option trinken
7 option schirpfen ;
an wm
- 88 - Kontrollstrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Wenn das Wort MENÜ aufgerufen wird, werden nicht nur die Optionen in die Tabelle
eingetragen, sondern auch namentlich auf dem Bildschirm dargestellt. Diese Technik
bietet sich für eine Menüzeile an fester Bildschirmposition an, ähnlich der
Statuszeile des volksFORTH. Zum Ändern solcher Menüpunkte bieten sich die
Funktionstasten an:
: fkey ke)
key &58 + abs function perform ;
FKEY liefert beim Druck einer Funktionstaste einen Wert von -59 bis -68 zu-
rück. Dieser wird für 18 Funktionstasten in den Bereich von -1 bis -18 skaliert
und der Absolutwert gebildet.
{1} Wil Baden Ultimate CASE-Statement
(vVD2/87 S.48 ff.)
[2) Dr. Charles Eaker Just in CASE
(FORTH DIM 11/3)
[3] R. Zech FORTH 83
(S.98ff/S.318f.)
[4] E. Floegel FORTH Handbuch
(S.189)
[5] W. Wejgaard Menus in FORTH
Elektroniker 9/88 (S.189 ff.)
4.4 Rekursion
Bevor die Technik der Rekursion für das volks4TH dargestellt wird, soll ein
anderes Wort .LASTNAME zeigen, daß das Wort LAST mit dem in der Literatur
oft anzutreffenden LATEST identisch ist:
Beide Worte liefern die name field address des zuletzt definierten Wortes im
CURRENT-Vokabular. Das Wort LAST' dagegen liefert die cfa des zuletzt definier-
ten Wortes.
: .lastname last @ .nane ;
Die Rekursion ist eine Technik, bei der ein Wort sich immer wieder selbst aufruft.
Eines der bekannten Beispiele dafür ist die Berechnung der Fakultät einer posi-
tiven ganzen Zahl. Hierbei ergibt sich n! aus dem Produkt aller ihrer Vorgänger.
Im volks4TH ist der Selbstaufruf eines Wortes durch RECURSIVE gekennzeichnet,
so daß sich ein Programm zur Fakultätsberechnung wie folgt präsentiert:
: fakultät (+n --n!)
recursive
dup 6®< IF drop ." keine negativen Argumente! " exit
THEN
?dup 0= IF 1 \ Spezialfall: ®
ELSE dup 1- fakultät *
Kontrollstrukturen - BI -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
THEN ;
er 4 fakultät .
er 5 fakultät .
er 6 fakultät .
Allerdings findet sich - vor allem in der figFORTH-Literatur - ein Wort MYSELF
. das mit dem in FORTH83-Umgebungen anzutreffenden RECURSE identisch ist.
Da auch diese Konstruktion, bei der MYSELF/RECURSE als Platzhalter für den
Wortnamen dienen, gerne eingesetzt wird, werden die möglichen Definitionen und
eine weitere Form von FAKULTÄT gezeigt:
. nyself last @ name) ,„ : immediate
: myself last' ,„ : immediate
recurse [compile] myself ; immediate
nyself Alias recurse immediate
: £fakultät (*+n--n!)
dup 6< IF ." keine negativen Argumente erlaubt!
ELSE ?dup 6= IF 1
ELSE dup 1- myself *
THEN
THEN ; .
Bei der Verwendung von RECURSE wird lediglich MYSELF dadurch ersetzt:
...
?dup 0= IF 1 \ Spezialfall: ®
ELSE dup 1- recurse *
THEN
= 69: = Kontrolistrukturen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
5. Ein- / Ausgabe im volksFORTH
5.1 Ein- / Ausgabebefehle im volksFORTH
Alle Eingabe- und Ausgabeworte (KEY EXPECT EMIT TYPE etc.) sind im volks-
FORTH vektorisiert, d.h. bei ihrem Aufruf wird die Codefeldadresse des zugehörigen
Befehls aus einer Tabelle entnommen und ausgeführt. So ist im System eine Tabelle
mit Namen DISPLAY enthalten, die für die Ausgabe auf dem Bildschirmterminal
sorgt.
Dieses Verfahren der Vektorisierung bietet entscheidende Vorteile:
= Mit der Input-Vektorisierung kann man z.B. mit einem Schlag die
Eingabe von der Tastatur auf ein Modem umschalten.
= Durch die Output-Vektorisierung können mit einer neuen Tabelle
alle Ausgaben auf ein anderes Gerät (z.B. einenDrucker) geleitet
werden, ohne die Ausgabebefehle selbst ändern zu müssen.
Mit einem Wort (DISPLAY, PRINT) kann das gesamte Ausgabeverhalten
geändert werden. Gibt man z.B. ein:
print 1 list display
wird Screen 1 auf einen Drucker ausgegeben und anschließend wieder
auf den Bildschirm zurückgeschaltet. Man braucht also kein neues
Wort, etwa PRINTERLIST, zu definieren.
Eine neue Tabelle wird mit dem Wort OUTPUT: erzeugt. Die Definition können Sie
mit view output: nachsehen. OUTPUT: erwartet eine Liste von Ausgabeworten,
die mit ; abgeschlossen werden muß.
Beispiel: Output: >PRINTER
pemit pcr ptype pdel ppage pat pat? ;
Damit wird eine neue Tabelle mit dem Namen >PRINTER angelegt. Beim späteren
Aufruf von >PRINTER wird die Adresse dieser Tabelle in die Uservariable OUTPUT
geschrieben. Ab sofort führt EMIT ein PEMIT aus, TYPE ein PTYPE usw.
Die Reihenfolge der Worte nach OUTPUT:
userEMIT userCR userTYPE userDEL userPAGE userAT userAT?
muß unbedingt eingehalten werden.
Entsprechend wird die Input-Vektorisierung gehandhabt.
Ein- ; Ausgabe im volksFORTH ao
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
5.2 Ein- / Ausgaben über Terminal
Das volks4th verfügt über eine Reihe von Konstanten, die der besseren Lesbarkeit
dienen:
c/row ( -- Anzahl )
ist die Konstante, die die Anzahl der Zeichen pro Zeile (&8®) angibt.
e/col ( -- Anzahl )
ist die Konstante, die die Anzahl der Zeichen pro Spalte (&25) angibt.
e/dis ( -- Anzahl.Cells )
ist die Konstante, die die Größe des Speichers für einen Ausgabeschirm
angibt.
e/l (-- +#n) "characters-per-line"
+n ist die Anzahl der Zeichen pro Screenzeile. Aus historischen Gründen
ist dieser Wert &64 bzw. $40 .
Vs ( -- +n) "lines-per-screen"
+n ist die Anzahl der Zeilen pro Screen.
bl (--n "5
n ist der ASCII-Wert für ein Leerzeichen.
#esc ( #=in) "number-escape"
n ist der ASCII-Wert für Escape.
#er (--n "number-c-r
n ist der Wert, den man durch KEY erhält, wenn die Return-Taste <cr>
gedrückt wird.
#lf ( Sei) "number-linefeed"
n ist der ASCII-Wert für Linefeed.
#bel (--n)
n ist der ASCII-Wert für BELL.
#bs (== pn) "number-b-s"
n ist der Wert, den man durch KEY erhält, wenn die Backspace-Taste ge-
drückt wird.
u Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
standardi/o (==) "standard-i-0"
inputkol
area
areakol
terminal
window
full
curat?
cur!
setpage
video@
stellt sicher, daß die beim letzten save bestimmten Ein- und Ausgabe-
geräte wieder eingestellt sind.
und outputkol
sind beides definierende Wörter, die eine festgelegte Anzahl von Zeigern
auf Prozeduren erwarten.
( -- addr )
ist eine Uservariable und zeigt auf den Zustandsvektor des aktiven Win-
dows.
ist ein definierendes Wort, das zur Erzeugung eines Windows benutzt
wird.
ist ein Window, das sich von Zeile @ - 23 erstreckt für das Terminal
Output Window.
( topline bottomline -- )
setzt die oberste und unterste Zeile des aktuellen Windows neu.
(=)
setzt das aktuelle Window über den ganzen Bildschirm von der obersten
bis zur untersten Zeile. Somit entspricht
: cla full page ;
dem Befehl, der den gesamten Bildschirm löscht.
( -- row col )
liefert die aktuelle Cursorposition im aktiven Fenster.
(a)
setzt den Cursor in das Window, auf das AREA zeigt.
(R--)
setzt aktive Bildschirmseite.
(--seg)
liefert das Segment zurück, in dem der Speicher der Videokarte liegt.
Ein- / Ausgabe im volksFORTH - 63 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
savevideo (--segı ff)
rettet den Speicherbereich der Videoausgabe; wird bei dem Wort MSDOS
eingesetzt.
restorevideo (seg -- )
restauriert die Bildschirmausgabe auf dem angegebenen Segment; wird bei
dem Wort MSDOS eingesetzt.
catt ( -- addr )
ist eine Variable, die das Attribut zur Zeichendarstellung enthält, z.B.
das Zeichenattribut INVERS
list (u) 83
zeigt den Inhalt des Screens u auf dem aktuellen Ausgabegerät an. SCR
wird auf u gesetzt.
Siehe BLOCK
(page ) "(page"
löscht den Bildschirm und positioniert den Cursor in die linke obere Ecke.
Vergleiche PAGE i
page ==)
bewirkt, daß der Cursor des Ausgabegerätes auf eine leere neue Seite
bewegt wird. Eines der OUTPUT-Worte.
(del (==) "(del"
löscht ein Zeichen links vom Cursor.
Vergleiche DEL
del (--)
löscht das zuletzt ausgegebene Zeichen. Bei Druckern ist die korrekte
Funktion nicht immer garantiert. Eines der OUTPUT-Worte
(er (ea) "(e-r"
setzt den Cursor in die erste Spalte der nächsten Zeile. Ein PAUSE
wird ausgeführt.
er . (==) 83 u
bewirkt, daß die Schreibstelle des Ausgabegerätes an den Anfang der
nächsten Zeile verlegt wird. Eines der OUTPUT-Worte.
“64 » Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
?er
(at
(at?
at
j.at?
col
Tow
curoff
curon
curshape
(u) "question-c-r"
prüft, ob in der aktuellen Zeile mehr als C/L Zeichen ausgegeben
wurden und führt in diesem Fall CR aus.
( row col -- ) "at"
setzt die aktuelle Cursorposition. (AT positioniert den Cursor in der Zeile
row und der Spalte col . Ein Fehler liegt vor, wenn row > $18 (&24) oder
col > $56 (&80) ist. Die fehlerhafte Ausgabe wird nicht unterdrückt!
Vergleiche AT
( -- row col ) "(at-question"
liefert die aktuelle Cursorposition. row ist die aktuelle Zeilennummer des
Cursors, col die aktuelle Spaltennummer.
Vergleiche AT?
( row col -- )
positioniert die Schreibstelle des Ausgabegerätes in die Zeile row und
die Spalte col. AT ist eines der über OUTPUT vektorisierten Worte.
Siehe AT?
( -- row col ) "at-question”
ermittelt die aktuelle Position der Schreibstelle des Ausgabegerätes und
legt Zeilen- und Spaltennummer auf den Stack. Eines der OUTPUT-Worte.
( -- #col ) "col"
#col ist die Spalte, in der sich die Schreibstelle des Ausgabegerätes
gerade befindet.
Vergleiche ROW und AT?
( -- #row ) "row"
#row ist die Zeile, in der sich die Schreibstelle des Ausgabegerätes be-
findet.die Benutzung beschreiben-
Vergleiche COL und AT?.
==)
schaltet den Cursor aus.
)
schaltet den Cursor ein.
( topline bottomline -- )
bestimmt das Aussehen des Cursors.
Ein- / Ausgabe im volksFORTH 65 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
printer
print
+print
lst!
5.3 Drucker-Ausgaben
(=)
ist das Vokabular mit den Worten zur Druckersteuerung.
(==
schaltet die Ausgabe auf den Drucker um
(--)
schaltet den Drucker zusätzlich zu.
(8b--)
gibt ein Byte zum Drucker aus.
5.4 Ein- / Ausgabe von Zahlen
Die Eingabe von Zahlen erfolgt im interpretativen Modus über die Tastatur, wobei
grundlegend Eingabeworte mit number number? und den verwandten Worten
definiert werden.
Bei der Ausgabe von Zahlen ist wieder die fehlende Typisierung von FORTH zu be-
achten - für ein bestimmtes Datenformat (integer, unsigned, double) ist jeweils der
geeignete Operator auszuwählen.
(n--)
gibt den obersten Stack-Werte als Zahl (integer) aus.
Soll die Ausgabe des nachfolgenden Leerzeichens unterdrückt werden, so
sind die Befehle für rechtsbündige Zahlenausgabe .r u.r d.r mit einer
Feldlänge von ® zu benutzen.
(u--)
gibt den obersten Stack-Wert als vorzeichenlose 16Bit-Zahl (unsigned)
aus.
(d--)
gibt die obersten beiden Stack-Werte als 32Bit-Zahl (double) aus.
(n Feldlänge -- )
druckt eine 16Bit-Zahl in einem Feld mit angegebener Länge rechtsbündig
aus.
- 66 -
Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ur ( u Feidlänge -- )
gibt den obersten Stack-Wert als vorzeichenlose 16Bit-Zahl in einem Feld
rechtsbündig aus.
d.r ( d Feldlänge -- )
gibt eine 32Bit-Zahl in einem Feld rechtsbündig aus.
5.5 Ein- / Ausgabe über einen Port
pc® ( port.addr -- 8b )
holt ein Byte von port.addr aus einem Peripheriebaustein des 8986-
Systems auf den Stack.
pe! ( 8b port.addr -- )
speichert ein Byte in einen Peripheriebaustein des 8886-Systems bei
port.addr.
5.6 Eingabe von Zeichen
In FORTH wird man immer einen Speicherbereich benennen, in dem Zeichen und
Zeichenketten verarbeitet werden. Hierfür verwendet man meistens einen kleinen,
88 Zeichen langen Speicherbereich namens PAD . Dieser Notizblock - so die
deutsche Übersetzung von pad - belegt keinen festen Speicherbereich und steht
sowohl dem FORTH-System als auch dem zur Verfügung.
Dann möchte ich Ihnen mit dem Texteingabe-Puffer tib einen weiteren wichtigen
Speicherbereich vorstellen,der den vernünftigen Umgang mit den angeschlossenen
Geräten sicherstellt. Weil die Texteingabe über die Tastatur relativ langsam vor
sichgeht, werden die Zeichen hier erst in einem freien Speicherbereich, dem
Pufferspeicher tib , gesammelt und dann abgearbeitet.
tib ( -- addr ) 83
liefert die Adresse des Text-Eingabe-Puffers. Hier wird die Eingabe-Be-
fehlszeile des aktuellen Eingabegerätes (meist KEYBOARD) gespeichert.
Siehe >TIB
#tib ( -- addr ) 83 "number-t-i-b"
addr ist die Adresse einer Variablen, die die Länge des aktuellen Textes
(die Anzahl der Zeichen) im Text-Eingabe-Puffer enthält.
Vergleiche TIB
Ein- / Ausgabe im volksFORTH =bm =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
»tib ( -- addr ) "to-tib"
addr ist die Adresse eines Zeigers auf den Text-Eingabe-Puffer.
Siehe TIB
»in ( -- addr )
ist eine Variable, die den Offset auf das gegenwärtige Zeichen im Quell-
text enthält.
>in indiziert relativ zum Beginn des Blockes, der durch die Variable bIk
gekennzeichnet wird. Ist blk = 8 , so wird als Quelle der tib angenom-
men.
Vergleiche word
pad ( -- addr )
liefert die Adresse des temporären Speichers PAD . Die Adresse von
PAD ändert sich, wenn der Dictionarypointer DP verändert wird, z.B.
durch ALLOT oder ,„ (Komma).
input ( -- addr ) U
addr ist die Adresse einer Uservariablen, die einen Zeiger auf ein Feld
von vier Kompilationsadressen enthält, die für ein Eingabegerät die
Funktionen KEY KEY? DECODE und EXPECT realisieren.
Vergleiche die Beschreibung der INPUT- und OUTPUT-Struktur.
keyboard ee)
ein mit INPUT: definiertes Wort, das die Tastatur als Eingabegerät setzt.
Die Worte KEY KEY? DECODE und EXPECT beziehen sich auf die
Tastatur.
Siehe (KEY (KEY? (DECODE und (EXPECT
empty-keys (_ =)
löscht den Tastaturpuffer über den Int.21h, Fct.dC, AL=B.
(key? ( -- flag ) "(key-question"
Das Flag ist TRUE , wenn eine Taste gedrückt wurde, sonst FALSE .
Vergleiche KEY? .
key? (-- flag ) "key-question"
Das Flag ist TRUE , falls ein Zeichen zur Eingabe bereitsteht, sonst ist
flag FALSE . Eines der INPUT-Worte.
- 88 - Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
(key (-- 16b ) "(key"
wartet auf einen Tastendruck. Während der Wartezeit wird PAUSE
ausgeführt.
Zeichen des erweiterten ASCII-Zeichensatzes werden in den unteren 8 Bit
von 16b übergeben. Funktionstasten liefern negative Werte.Steuerzeichen
werden nicht ausgewertet, sondern unverändert abgeliefert.
Vergleiche KEY.
key ( -- 16b ) 83
empfängt ein Zeichen vom Eingabegerät. Es wird kein Echo ausgesandt.
KEY wartet, bis tatsächlich ein Zeichen empfangen wurde.
Die niederwertigen 8 Bit enthalten den ASCII-Code des zuletzt empfan-
genen Zeichens. Alle gültigen ASCII-Codes können empfangen werden.
Die oberen 8 Bit enthalten systemspezifische Informationen, den Tas-
tatur-Scancode.
Die Funktionstasten werden als negative Zahlenwerte zurückgegeben, so
daß beispielsweise auf einer PC/XT-Tastatur folgende Tasten ent-
sprechende 16Bit-Werte liefern :
Tasten Fl - F1ß: =59Eu268
Cursorblock: -71 (home) - -81 (pgdn)
Zahlen 8 - 9: 48 (6) - 57 (9)
KEY ist eines der INPUT-Worte.
(decode ( addr pos® key -—- addr posl ) "(decode"
wertet key aus. key wird in der Speicherstelle addr+pos1 abgelegt
und als Echo auf dem Bildschirm ausgegeben. Die Variable SPAN und
pos werden inkrementiert. Backspace löscht das Zeichen links vom Cursor
und dekrementiert posl und SPAN.
Vergleiche INPUT: und (expect ..
(expect ( addr len -- ) "(expect"
erwartet len Zeichen vom Eingabegerät, die ab addr im Speicher abgelegt
werden. Ein Echo der Zeichen wird ausgegeben. Return beendet die Ein-
gabe vorzeitig. Ein abschließendes Leerzeichen wird statt des <CR> aus-
gegeben. Die Länge der Zeichenkette wird in der Variablen SPAN über-
geben.
Vergleiche EXPECT .
Ein- / Ausgabe im volksFORTH =u69F =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
expect ( Zieladresse maxAnzahl -- ) 83
empfängt maxAnzahl Zeichen und speichert sie ab der Zieladresse im
Speicher, ohne ein count byte einzubauen. Der count wird statt dessen
in der Variablen span abgelegt. Ist maxAnzahl = ® , so werden keine
Zeichen übertragen.
Die Übertragung wird beendet, wenn ein #CR erkannt oder maxAnzahl
Zeichen übertragen wurden. Das #CR wird nicht mit abgespeichert.
Alle Zeichen werden als Echo, statt des #CR wird ein Leerzeichen ausge-
geben.
Dies ist das expect aus der Literatur, mit dem man an beliebigen Stel-
len im Speicher Eingabepuffer jeder Länge anlegen kann. Eines der
INPUT-Worte.
Vergleiche SPAN .
span ( -- addr ) 83
Der Inhalt der Variablen SPAN gibt an, wieviele Zeichen vom letzten
EXPECT übertragen wurden; in ihr ist die Anzahl der tatsächlich einge-
gebenen Zeichen des zuletzt ausgeführten expect abgelegt.
span wird ausgelesen, um zu sehen, ob die erwartete Zeichenzahl emp-
fangen oder die Eingabe vorher mit <CR> abgebrochen wurde. Bei span
ist zu beachten, daß es direkt nach einem expect benutzt werden muß,
weil auch einige FORTH-Systemwörter span benutzen.
>expect ( Zieladresse maxAnzahl.Zeichen -- )
legt ebenfalls einen zu erwartenden String an einer Zieladresse ab, aller-
dings wird jetzt das count-byte eingebaut.
nullstring? ( addr -- addr ff ! addr tf )
prüft, ob der counted String an der gegebenen Adresse die Länge NULL
hat. Wenn dies der Fall ist, wird true hinterlegt, ansonsten bleibt addr
erhalten und false wird übergeben.
stop? (-- flag ) "stop-question"
Ein komfortables Wort, das es dem Benutzer gestattet, einen Programmab-
lauf anzuhalten oder zu beenden.
Steht vom Eingabegerät ein Zeichen zur Verfügung, so wird es eingelesen.
Ist es #ESC oder CTRL-C , so ist Flag TRUE , sonst wird auf das
nächste Zeichen gewartet. Ist dieses jetzt #ESC oder CTRL-C , so wird
STOP? mit TRUE verlassen, sonst mit FALSE.
Steht kein Zeichen zur Verfügung, so ist Flag FALSE.
- 10: Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
source
word
parse
name
find
( -- addr len )
übergibt Adresse und Länge des Quelltextes; wenn die Blocknummer = 8
ist, entsprechen diese Angaben denen des Text-Eingabe-Puffers TIB ;
das ist der Grund, warum Block ® niemals geladen werden kann. Ist die
Blocknummer nicht NULL, beziehen sich die Angaben auf den Massenspei-
cher.
( delim -—- addr )
durchsucht den Quelltext (siehe SOURCE) nach einem frei wählbaren Be-
grenzer und legt den gefundenen String in der counted Form im Speicher
an der Adresse here ab.
Führende Zeichen vom Typ delim werden ignoriert. Deshalb erwartet word
immer einen Delimiter und übernimmt nicht automatisch den üblichen Be-
grenzer, das Leerzeichen. Daher typisch:
RO ER
( delim -- addr len )
erwartet ebenfalls ein Zeichen als Begrenzer, liefert die nächste delim
begrenzte Zeichenkette des Quelltextes aber schon in der üblichen Form
addr count passend für type.
Die Länge ist Null, falls der Quelltext erschöpft oder das erste Zeichen
der delimiter ist. parse verändert die Variable >in.
Typisches Auftreten: ;
: .( ASCII ) parse type ;
( -- string )
holt den nächsten durch Leerzeichen abgeschlossenen String aus dem
Quelltext, wandelt ihn in Großbuchstaben um und hinterläßt die Adresse,
ab der der String im Speicher steht.
Siehe word .
( string -- string ff I cfa tf )
erwartet die Adresse eines counted Strings. Dieser String wird in der
aktuellen Suchreihenfolge gesucht und das Resultat dieser Suche über-
geben.
Wird das Wort gefunden, so liegt die cfa und ein Pseudoflag tf bereit:
- Ist das Wort immediate, so ist das flag positiv, sonst negativ.
- Ist das Wort restrict, so hat das flag den Betrag 2, sonst Betrag 1.
Typisch: ... (name) find ...
was " RStein) Lin...
.. name find ...
Ein- / Ausgabe im volksFORTH I -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
execute
perform
query
interpret
( addr -- )
Das durch addr gekennzeichnete Wort wird aufgerufen bzw. ausgeführt.
Dabei kann es sich um ein beliebiges Wort handeln. Eine Fehlerbedingung
existiert, falls addr nicht cfa eines Wortes ist.
Typisch: ' (name) execute
( addr -- )
ist ein execute für einen Vektor und entspricht ®@ execute . Typisch
beim Einsatz einer Prozedurvariable:
Variable <(vector)
" noop <«vector) |!
(vector) perforn
Hier wird zuerst eine Variable angelegt und anschließend dieser Variablen
mit Hilfe des ' ("Tick") die CFA eines Wortes zugewiesen. Dieses Wort .
kann nun über die Adresse der Prozedurvariablen und PERFORM ausge-
führt werden. Allgemein wird diese Variable mit NOOP abgesichert.
( 83
ist die allgemeine Texteingabe-Prozedur für den Texteingabe-Puffer.
query stoppt die Programmausführung und liest eine Textzeile von max.
88 Zeichen mit Hilfe von expect ein.
Die Zeichen werden von einem Eingabegerät geholt und in den Text-Ein-
gabe-Puffer übertragen, der bei TIB beginnt. Die Übertragung endet
beim Empfang von #CR oder wenn die Länge des Text-Eingabe-Puffers
erreicht wird. Der Inhalt von >IN und BLK wird zu ® gesetzt und
#TIB enthält die Zahl der empfangenen Zeichen.
Zu beachten ist, daß der Inhalt von TIB überschrieben wird. Damit
werden auch alle Worte im TIB , die noch nicht ausgeführt wurden,
ebenfalls überschrieben. Um Text aus dem Puffer zu lesen, kann WORD
benutzt werden.
Siehe EXPECT .
(„==,)
ist der allgemeine Text-Interpreter des FORTH-Systems und beginnt die
Interpretation des Quelltextes bei dem Zeichen, das durch den Inhalt der
Variablen >in bezeichnet wird. >in indiziert relativ zum Beginn des
Blockes, der durch die Variable blk gekennzeichnet wird. Ist bik =,
so interpretiert interpret die max. 80 Zeichen im tib.
w
Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
output
display
(emit
emit
charout
tipp
(type
type
5.7 Ausgabe von Zeichen
( -- addr ) U
addr ist die Adresse einer Uservariablen, die einen Zeiger auf sieben
Kompilationsadressen enthält, die für ein Ausgabegerät die Funktionen
EMIT CR TYPE DEL PAGE AT und AT? realisieren.
Vergleiche die gesonderte Beschreibung der Output-Struktur.
(.==)
ist ein mit OUTPUT: definiertes Wort, das den Bildschirm als Ausgabe-
gerät setzt, wenn es ausgeführt wird. Die Worte EMIT CR TYPE DEL
PAGE AT und AT? beziehen sich dann auf den Bildschirm.
(8b -- ) "(emit"
eibt 8b auf dem Bildschirm aus. Ein PAUSE wird ausgeführt. Alle Werte
werden als Zeichen ausgegeben, Steuercodes sind nicht möglich, d.h. alle
Werte < $28 werden als PC-spezifische Zeichen ausgegeben.
Vergleiche EMIT.
(16b --) 83
gibt die unteren 8 Bit an das Ausgabegerät. Eines der OUTPUT-Worte.
(8 --)
gibt 8b auf Standard-1/O-Gerät aus. Dazu wird die Fct.86 des Int21h be-
nutzt. ASCII-Werte < $28 werden als Steuercodes interpretiert. CHAROUT
ist ein Primitiv für die Ausgabe-routinen und sollte vermieden werden,
da die Ausgabe dann nicht über die Videotreiber läuft.
( addr count -- )
ist die Primitiv-Implementierung für TYPE über den MSDOS Character-
Output.
Siehe auch DISPLAY in KERNEL.SCR.
( addr len -- )
gibt den String, der im Speicher bei addr beginnt und die Länge len hat,
auf dem Bildschirm aus. Ein PAUSE wird ausgeführt.
Vergleiche TYPE OUTPUT: und (EMIT.
( addr +n -- ) 83
sendet +n Zeichen, die ab addr im Speicher abgelegt sind, an ein Aus-
gabegerät. Ist +n = @ , so wird nichts ausgegeben.
Ein- / Ausgabe im volksFORTH =>
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ltype ( seg:addr Länge -- )
ist ein segmentiertes TYPE.
space )
gibt ein Leerzeichen aus.
spaces ( Anzahl -- )
gibt eine bestimmte Anzahl von Leerzeichen aus.
= 74 = Ein- / Ausgabe im volksFORTH
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
6. Strings
Hier befinden sich grundlegende Routinen zur Stringverarbeitung.
Vor allem wurden auch Worte aufgenommen, die den Umgang mit den vom Betriebs-
system geforderten ®-terminated Strings ermöglichen. FORTH hat hier gegenüber C
den Nachteil, daß FORTH-Strings standardmäßig mit einem Count-Byte beginnen,
das die Länge des Strings enthält. Ein abschließendes Zeichen (z.B. ein Null-Byte)
ist daher unnötig. Da das Betriebssystem aber in C geschrieben wurde, müssen
Strings entsprechend umgewandelt werden.
Standardmäßig arbeitet FORTH mit counted Strings, die lediglich durch eine Adresse
gekennzeichnet werden. Das Byte an dieser Adresse enthält die Angabe, wie lang
die Zeichenkette ist. Auf dieses count byte folgt dann die Zeichenkette selbst.
Dadurch ist die Länge eines Standard-Strings in FORTH auf 255 Zeichen begrenzt.
Die kürzeste Zeichenkette ist ein String der Länge NULL, für dessen Überprüfung
der Befehl NULLSTRING? zur Verfügung steht.
5SfrfofrirgH
addr
So sieht der String FORTH an der Adresse addr im Speicher unter FORTH aus.
Es (==)
ist nur während des Compilierens in Wörtern zu verwenden. Die ge-
wünschte Zeichenkette wird von ." und " eingeschlossen, wobei das
Leerzeichen nach ." nicht mitzählt. Wenn das Wort abgearbeitet wird,
so wird der String zwischen ." und " ausgegeben:
: Hallo ." Ich mache FORTH" ;
E ( -- addr ) GI "string"
G=52) compiling
liest den Text bis zum nächsten " und legt ihn als counted string im
Dictionary ab. Kann nur während der Kompilation ver-wendet werden. Zur
Laufzeit wird die Startadresse des counted string auf den Stack gelegt.
Das Leerzeichen, das auf das erste Anführungszeichen folgt, ist nicht
Bestandteil des Strings. Wird in der folgenden Form benutzt:
: Hallo " Ich mache FORTH" count type ;
Strings er
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
Fi (--) "string literal"
speichert einen counted String ab HERE . Wird in der folgenden Form
benutzt : Create Hallo ,„" Ich mache FORTH"
Hallo count type
nullstring? ( addr -- addr false } true )
prüft, ob der counted String an der Adresse addr ein String der Länge
NULL ist. Wenn dies zutrifft, wird TRUE übergeben. Anderenfalls bleibt
addr erhalten und FALSE wird übergeben.
"lit ( -- addr )
wird in compilierenden Worten benutzt, die auf INLINE-Strings zugreifen.
Siehe auch ?" und ".
ah (sen)
druckt den nachfolgenden String immer sofort aus. Der String wird von )
beendet.
Anwendung: .( Ich mache FORTH )
( (--)
leitet einen Kommentar ein, d.h. Text, der vom Compiler ignoriert wird.
) beendet einen Kommentar. Dieses Wort ist aber selbst kein FORTH-Befehl,
muß deshalb auch nicht mit Leerzeichen abgetrennt sein.
6.1 String-Manipulationen
Hier im Glossar bezeichnet der Stackkommentar ( string -- ) die Adresse eines
counted Strings, dagegen ( addr len -- ) die Charakterisierung durch die
Anfangsadresse der Zeichenkette und ihre Länge.
Keine Stringvariable - Benutze:
: String: Create dup „ ® c, allot Does) 1+ count ;
caps ( -- addr )
liefert die Adresse einer Variablen, die angibt, ob beim Stringvergleich
auf Groß- und Kleinschreibung geachtet werden soll.
capital ( char -- char! )
Die Zeichen im Bereich a bis z werden in die Großbuchstaben A bis 2
umgewandelt, ebenso die Umlaute äöü . Andere Zeichen werden nicht
verändert.
N Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
upper ( addr len -- )
wandelt einen String in Großbuchstaben um. Es werden keine Parameter
zurückgegeben.
capitalize ( string -- string )
ist durch UPPER ersetzt worden. Bei Bedarf kann es folgendermaßen
definiert werden:
: capitalize ( string -- string ) dup count upper ;
/string ( addr® len index -- addri restlen ) "eut-string"
verkürzt den durch addrd und len gekennzeichneten String an der mit
index angegebenen Stelle und hinterläßt die Parameter des rechten Teil-
strings.
-trailing ( addr® len® -- addrl leni ) "minus-trailing"
kürzt einen String um die Leerzeichen, die sich am Ende des Strings be-
finden. Anschließend liegen die neueen Parameter auf dem Stack, passend
z.B. für TYPE.
scan ( addr® len char -- addrl restlen )
durchsucht einen mit addr und len angegebenen String nach einem Zei-
chen char.
Wird das Zeichen gefunden, so wird die Adresse der Fundstelle und die
Restlänge einschließlich des gefundenen Zeichens übergeben.
Wird char nicht gefunden, so ist addri die Adresse des ersten Bytes
hinter dem String und die Restlänge ist NULL.
skip ( addr® len char -- addri restlen )
durchsucht einen mit addr® und len angegebenen String nach einer Ab-
weichung von dem gegebenen Zeichen char.
Beim ersten abweichenden Buchstaben wird die Adresse der Fundstelle
und die Restlänge ohne das abweichende Zeichen übergeben.
Besteht der gesamte String aus dem Zeichen char, so ist addri die
Adresse des Bytes hinter dem String und die Restlänge ist NULL.
12 (ee)
gibt die Position eines Zeichen in einem String an. Dieses ?" wird in
Definitionen benutzt, um z.B. bei
: vocal? ( char -- index ) capital ?" aeiou” ;
Ascii ( char) vocal?
festzustellen, ob es sich bei dem gegebenen Zeichen um einen Vokal
handelt (index ungleich NULL) oder um welchen Vokal es sich handelt
(a=1, e=2, i=3 etc.) ..
Strings TUR
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
count ( string -- addr+1 len )
wandelt eine String-Addresse in die Form addr len um, die für z.B. TYPE
notwendig ist.
bounds ( addr len -- limit start )
ist definiert als
: bounds over + swap ;
und kann z.B. dazu benutzt werden, die Parameter einer Zeichenkette in
DO..LOOP-gemäße Argumente umzurechnen:
: upper ( addr len -- )
bounds ?DO
I c@ capital I c!
LOOP ;
type ( addr len -- )
gibt eine Zeichenkette aus, die an addr beginnt und die angebene Länge
hat.
»type ( addr len -- )
ist ein TYPE , das zuerst den String nach PAD kopiert. Dies ist in
Multitasking-Systemen wichtig und wird folgendermaßen definiert:
: >type ( addr count -- )
pad place
pad count type ;
place ( addrö len dest.addr -- )
legt eine Zeichenkette, die durch ihre Anfangsadresse und ihre Länge ge-
kennzeichnet ist, an der Zieladresse als counted String ab.
PLACE wird in der Regel benutzt, um Text einer bestimmten Länge als
counted String abzuspeichern; dabei darf dest.addr gleich, größer oder
kleiner als addrß sein.
Die Wirkungsweise von PLACE wird in der Definition von >EXPECT
deutlich, wo die Anzahl der von EXPECT eingelesenen Zeichen mit
SPAN @ ausgelesen und von PLACE an der Zieladresse eingetragen wird:
)expect ( addr len --)
stash expect span @ over place ;
attach ( addr len string --)
fügt einen String an den durch addr und len gekennzeichneten String an,
wobei der Count addiert wird.
append ( char string -- )
fügt ein Zeichen an den angegebenen String an und in-crementiert den
Count.
PBa- Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
detract
— match
search
(find
( string -- char )
zieht das erste Zeichen aus einer Zeichenkette und de-crementiert den
Count.
6.2 Suche nach Strings
6.2.1 In normalem Fließtext:
( buf.addr buf.len string -—- match.addr buf.rest )
Der Pufferbereich an buf.addr mit der Länge buf.len wird nach einer
vollständigen Übereinstimmung mit dem counted String überprüft. Die
Adresse der Übereinstimmung und die Restlänge des Puffers wird über-
geben. MATCH befindet sich im Vokabular EDITOR .
( buf len string -- offset flag )
durchsucht einen Speicherbereich mit angegebener Länge nach einem
counted string.
Der Abstand vom Anfang des Speicherbereiches und ein Flag werden
übergeben . Ist das Flag wahr, wurde der String gefunden, sonst nicht.
Der Quelltext von SEARCH befindet sich im Editor und ist mit dessen
Suchfunktion leicht aufzufinden.
6.2.2 Im Dictionary:
( string thread -- string ff Infa tf )
erwartet die Adresse eines counted string und eine Suchreihe. Wird das
Wort in dieser Reihe gefunden, so wird ein true flag und die nfa
übergeben; wird es nicht gefunden, wird ein false flag übergeben und
die Stringadresse bleibt erhalten.
Typische Anwendung:
... last @ current @ (find...
Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
find
( string -- string.addr ff ! cfa tf )
erwartet die Adresse eines counted Strings. Dieser String wird in der
aktuellen Suchreihenfolge gesucht und das Resultat dieser Suche über-
geben.
Wird das Wort gefunden, so liegt die cfa und ein Pseudoflag tf bereit:
- Ist das Wort immediate, so ist das Flag positiv, sonst negativ.
- Ist das Wort restrict, so hat das Flag den Betrag 2, sonst Betrag 1.
Typische Anwendung:
.. (name ) find...
" «string>" find ...
. name find ...
6.3 @-terminated Strings
Es gibt noch eine andere Darstellungsform für Strings, die beispielsweise für MS-
DOS geeigneter ist. Diese Strings werden zwar ebenfalls durch eine Adresse ge-
kennzeichnet; diese Adresse enthält aber kein count byte . Statt dessen werden
diese Zeichenketten mit einem Nullbyte abgeschlossen.
asciz
Yasciz
counted
( -- asciz )
(me) compiling
holt das nächste Wort des Quelltextes ( TIB oder BLOCK ) in den Spei-
cher und legt es als nullterminierten String (mit abschließendem Null-
Byte) im Dictionary ab. Diese Adresse asciz im Dictionary wird zurückge-
liefert.
Wird in der folgenden Form benutzt :
asciz (string?
Vergleiche ,".
( string addr.dest -- asciz )
wandelt den counted String an der Adresse STRING um in einen null-
terminierten String, der an der gegebenen Ziel-Adresse ADDR abgelegt
wird. Die Länge des Strings im Speicher bleibt gleich.
An der zurückgelieferten Adresse asciz liegt der neue String, wobei die
übergebene Zieladresse und die zurückgelieferte ASCIZ-Adresse nicht
gleich sein müssen.
>ASCIZ ist das grundlegende Wort, um FORTH-Strings in MS-DOS-Strings
umzuwandeln.
( asciz -— addr len )
wird benutzt, um die Länge eines mit einem Nullbyte terminierten Strings
zu bestimmen. asciz ist die Anfangsadresse dieses Strings, addr und len
sind die Parameter. die z.B. von TYPE erwartet werden.
- 89 -
Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
digit?
6.4 Konvertierungen: Strings -— Zahlen
6.4.1 String in Zahlen wandeln
( char -- digit true )
( char -- false )
prüft, ob das Zeichen char eine gültige Ziffer entsprechend der aktuellen
Zahlenbasis in BASE ist. Ist das der Fall, so wird der Zahlenwert der
Ziffer und TRUE auf den Stack gelegt. Ist char keine gültige Ziffer,
wird FALSE übergeben.
accumulate ( +d® addr char -- +d1 addr )
convert
number?
dient der Umwandlung von Ziffern in Zahlen.
Multipliziert die Zahl +d® mit BASE , um sie eine Stelle in der aktu-
ellen Zahlenbasis nach links zu rücken, und addiert den Zahlenwert von
char. char muß eine in der Zahlenbasis gültige Ziffer darstellen, addr
wird nicht verändert.
Wird z.B. in CONVERT benutzt. .
( +d® addr® -- +di addri )
wandelt den Ascii-Text ab addr® +1 in eine Zahl entsprechend der
Zahlenbasis BASE um. Der enstehende Zahlenwert und die Adresse des
ersten nicht wandelbaren Zeichens im Text werden hinterlassen.
( addr -- d 8> I n @< I addr false )
wandelt den counted String bei der Adresse addr in eine Zahl n um. Die
Umwandlung erfolgt entsprechend der Zahlenbasis in BASE oder wird
vom ersten Zeichen im String bestimmt.
Enthält der String zwischen den Ziffer auch die Asciizeichen für Punkt
oder Komma, so wird er als doppelt genaue Zahl interpretiert und 9>
gibt die Zahl der Ziffern hinter dem Punkt einschließlich an.
Sonst wird der String in eine einfach genaue Zahl n umgewandelt und
eine Zahl kleiner als Null hinterlassen.
Wenn die Ziffern des Strings nicht in eine Zahl umgewandelt werden kön-
nen, bleibt die Adresse des Strings erhalten und FALSE wird auf den
Stack gelegt.
Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Die Zeichen, die zur Bestimmung der- Zahlenbasis dem Ziffern-string vor-
angestellt werden können, sind:
% (Basis 2 "binär")
& (Basis 18 "dezimal")
$ (Basis 16 "hexadezimal")
h «Basis 16 "hexadezimal")
Der Wert in BASE wird dadurch nicht verändert.
number ( addr --d)
wandelt den counted String bei der Adresse addr in eine Zahl d um. Die
Umwandlung erfolgt entsprechend der Zahlenbasis in BASE . Eine Fehler-
bedingung besteht, wenn die Ziffern des Strings nicht in eine Zahl
verwandelt werden können. Durch Angabe eines Präfix (siehe NUMBER? )
kann die Basis für diese Zahl modifiziert werden.
apl ( -- addr ) "decimal point location"
ist eine Variable, die die Stellung des Dezimalpunktes angibt.
Ein Beispiel der Umwandlung von Zeichen in Zahlen:
In FORTH wird die Eingabe von Zahlen oft mit der allgemeinen Texteingabe und
über die Befehle zur Umwandlung von Strings in Zahlen realisiert. In der Literatur
wird dazu oft diese Lösung mit QUERY angeboten:
: in# ( <stringd -- dt£f nt£f addr ff)
query bl word number? ;
Diese Lösung ist ungünstig, da QUERY den TIB löscht. Zugleich stellt die Definition
von NUMBER? eine unglückliche Stelle im volksFORTH dar.
Es gibt im Laxen&Perry-F83 ein Wort gleichen Namens, das ganz anders (besser!)
mit den Parametern umgeht. Hier folgt die Definition des F83-NUMBER?, aus dem
volksFORTH NUMBER? aufgebaut:
: F83-NUMBER? ( string --df)
number? ?dup IF 9< IF extend THEN true exit THEN
drop 0 6 false ;
Damit stellt das Wort INPUT# eine wenig aufwendige Zahleneingabemöglichkeit für
16/32Bit-Zahlen dar:
\ input# jrg 29jul88
: input# ( (string? --df)
pad c/1l 1- »expect \ get 63 char maximal
pad F83-number? \ converts string > number
So kann der Anwender das übergebene Flag auswerten und die doppelt-genaue Zahl
entsprechend seinen Vorstellungen einsetzen, im einfachsten Fall mit DROP zu
einer einfach-genauen Zahl machen.
= 89 = Strings
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
#Ss
hold
sign
#)
6.4.2 Zahlen in Strings wandeln
( +d8 -- +dl) 83 "sharp"
Der Rest von +d® geteilt durch den Wert in BASE wird in ein Ascii-
Zeichen umgewandelt und dem Ausgabestring in Richtung absteigender
Adressen hinzugefügt. +d1 ist der Quotient und verbleibt auf dem Stack
zur weiteren Bearbeitung. Üblicherweise zwischen {# und #> benutzt.
(+d--898) 83 "sharp-s"
+d wird mit # umgewandelt, bis der Quotient zu Null geworden ist.
Dabei wird jedes Zwischenergebnis in ein Ascii-Zeichen umgewandelt und
dem String für die strukturierte Zahlenausgabe angefügt. Wenn +d von
vornherein den Wert Null hatte, wird eine einzelne Null in den String
gegeben. Wird üblichwerweise zwischen <# und #> benutzt.
( char -- ) 83
Das Zeichen char wird in den Ausgabestring für die Zahlenausgabe ein-
gefügt. Wird üblicherweise zwischen <# und #> benutzt.
(Gns==n) 83
Wenn n negativ ist, wird ein Minuszeichen in den Ausgabestring für die
Zahlenausgabe eingefügt. Wird üblicherweise zwischen <# und #> be-
nutzt.
( 32b -- addr len ) 83 "sharp-greater"
Am Ende der strukturierten Zahlenausgabe wird der 32b Wert vom Stack
entfernt. Hinterlegt werden die Adresse des erzeugten Ausgabestrings und
eine positive Zahl als die Anzahl der Zeichen im Ausgabestring, passend
z.B. für TYPE.
Strings
FORTH-Gesellschaft e.V, PC-volksFORTH83 rev. 3.81
7. Umgang mit Dateien
Das File-Interface wurde grundlegend überarbeitet.
Auf der Benutzerebene stehen die gleichen Worte wie im volksFORTH 3.88 für den
ATARI und für CP/M zur Verfügung; die darunterliegende Implementation wurde
jedoch grundlegend geändert, so daß jetzt in FORTH auch sequentielle Files, die
nicht die starre BLOCK-Struktur haben, manipuliert werden können.
Damit ist es endlich möglich, auch volksFORTH für kleine Hilfsprogramme zu ver-
wenden, die mit anderen Programmen erstellte Files "bearbeiten" und durch den Be-
fehl SAVESYSTEM als "standalone"-Programm abgespreichert wurden.
Besonders weitreichende Möglichkeiten erschließen sich dadurch, daß beim Aufruf
von volksFORTH auf der Betriebssystemebene noch eine ganze Kommandozeile mit
übergeben werden kann, die dann unmittelbar nach dem Booten von FORTH ausge-
führt wird. Durch die Systemvariable RETURN_CODE kann nach Verlassen des
FORTHProgramms ein Wert an MS-DOS zurückgegeben werden, der mit dem Batch-
Befehl ERRORLEVEL abgefragt werden kann.
Darüberhinaus ist es auch möglich, mit dem Befehl MSDOS aus dem FORTH heraus
eine weitere COMMAND.COM shell aufzurufen und später mit EXIT wieder ins
FORTH zurückzukehren, wobei der Bildschirm, der zum Zeitpunkt des Aufrufs be-
stand, wiederhergestellt wird.
Selbstverständlich kann neben MSDOS selber auch jedes andere beliebige An-
wendungsprogramm aufgerufen werden - auch eine weitere Inkarnation des FORTH-
Systems - so daß sich mit diesen Möglichkeiten die Begrenzungen überwinden
lassen, die in dem beschränkten Adreßraum von 64k liegen. Auch komplizierte
Overlaystrukturen sind nicht mehr notwendig, es werden einfach aus einem zen-
tralen "Verwaltungsprogramm" heraus spezielle FORTH-Anwendungsprogramme aufge-
rufen.
Das Fileinterface des volksFORTH benutzt die Dateien des MSDOS und dessen Sub-
directories.
Dateien bestehen aus einem FORTH-Namen und einem MSDOS-Namen, die nicht
übereinstimmen müssen.
Ist das FORTH-Wort, unter dem ein File zugreifbar ist, gemeint, so wird im
folgenden vom (logischen) FORTH-File gesprochen. Dies entspricht einer
Dateivariablen in den PASCAL-ähnlichen Sprachen. Der Zugriff auf eine Datei
erfolgt daher in volksFORTH über den Namen eines Files ; dieser Namen ermöglicht
dann den Zugriff entweder auf den Datei-Steuerblock (FCB) oder die MSDOS-
Handle-Nummer.
Ist das File auf der Diskette gemeint, das vom MSDOS verwaltet wird, so wird vom
(physikalischen) DOS-File gesprochen,
= 84 = Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Durch das Nennen des FORTH-Namens wird das FORTH-File (und das zugeordnete
DOS-File) zum aktuellen File, auf das sich alle Operationen wie LIST , LOAD,
CONVEY usw. beziehen.
Beim Öffnen eines Files wird die mit PATH angegebene Folge von Pfadnamen
durchsucht. Dabei ist PATH ein von MSDOS völlig unabhängiger Pfad, so daß ver-
schiedene Projekte auch mit verschiedenen FORTH-Systemen über ihren eigenen
Pfad verwaltet werden können.
Der gültige MSDOS-Pfad wird davon nicht beeinflußt. Ist eine Datei einmal geöffnet,
so kann diese Folge beliebig geändert werden, ohne daß der Zugriff auf das File
behindert wird. Aus Sicherheitsgründen empfiehlt es sich aber, Files so oft und so
lange wie irgend möglich geschlossen zu halten. Dann kann eine Änderung der
Folge von Pfadnamen in PATH dazu führen, daß ein File nicht mehr gefunden
wird.
volksFORTH bearbeitet seine Quelltexte in sogenannten Screen-Files, die üblicher-
weise die Endung .SCR haben.
Dies sind Files, die in 1 KB große Screens aufgeteilt sind, jeweils in 16 Zeilen zu
je 64 Zeichen strukturiert.
Üblicherweise enthält der Screen ® eines jeden Files eine kurze Erklärung über den
Inhalt des Files - dies ist auch deshalb sinnvoll, da der Screen ® eines Files nie
geladen werden kann.
Screen 1 enthält üblicherweise den sogenannten "loadscreen". Dieser steuert den
Ladevorgang des gesamten Files. Ein Beispiel für einen solchen LOADSCREEN ist der
Scrl der Datei VOLKS4TH.SYS, der die aktuelle Arbeitsumgebung VOLKS4TH.COM
zusammenstellt.
In Zeile ® eines jeden Screens ist ein Kommentar über den Inhalt des Screens und
das Datum der letzten Änderung enthalten.
Um - vor allem auf Festplatten - Directories anzusprechen, gibt es verschiedene
Methoden. Um beispielsweise Files in einem Directory "WORK" zu suchen oder an-
zulegen, geben Sie ein :
cd work
Jetzt werden alle Files und Sub-Directories im Directory WORK gesucht oder neu
geschaffen. Ist das Directory WORK noch nicht vorhanden, so erzeugen Sie es mit :
md work
Wenn Sie Dateien auf einem bestimmten Laufwerk, z.B. A: , ansprechen wollen,
geben Sie ein:
A:
Hierbei wird A: zum aktuellen Laufwerk gemacht.
Im einfachsten Fall existiert die zu benutzende Datei auf dem Massenspeicher und
der Datei-Name bereits im volksFORTH-Dictionary. Soiche Files sprechen Sie an,
indem Sie einfach den Filenamen eingeben.
Umgang mit Dateien = 85"-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Mit dem Wort files zeigt Ihnen voliksFORTH eine Liste dieser bereits im FORTH-
System vorhandenen Dateien und Dateinamen, zusammen mit den zugeordneten DOS-
Dateien und den Handle-Nummern.
Melden Sie irrtümlich eine Datei an, deren Name nicht im FORTH-Wörterbuch gefun-
den wird, erscheint die übliche Fehlermeldung, das "?".
Um dagegen zu kontrollieren, ob eine Datei auf Disk existiert, benutzen Sie dir.
Soll in einem solchen Fall ein File, das auf der Disk schon existiert, neu von
volksFORTH bearbeitet werden, so wird es durch use <filename> zum sogenannten
"aktuellen" File gemacht, in die Liste FILES und ins Wörterbuch eingetragen.
So macht use test.scr das MSDOS-File TEST.SCR zum aktuellen File, auf das
sich solange alle weiteren File-Operationen beziehen, bis ein anderes File zum
aktuellen File gemacht wird. Der Zugriff auf verschiedene Laufwerke ist für die
Laufwerke A: bis H: vordefiniert.
Das Wort use erzeugt deshalb im FORTH-System das Wort TEST.SCR, falls es noch
nicht vorhanden war. Wissen Sie also nicht mehr, ob Sie ein File schon benutzt
haben, so können Sie das Wort use voranstellen, mit files nachsehen oder
probehalber den Datei-Namen eingeben.
Möchten Sie ein neue Datei oder ein eigenes Screenfile anlegen, so wählen Sie
einen Namen und benutzen:
makefile <filename)>
Danach erfolgen die Schreib/Lesezugriffe des DOS auf <filename>. Bei einem Block-
file schätzen Sie die notwendige Größe nn in Blocks ab und geben ein:
makefile <filename®? nn more (z.B. 208 more)
Dabei ist der Name maximal 8 Buchstaben und die Extension maximal 3 Buchstaben
lang. Diese Extension kann, muß aber nicht angegeben werden. Als Konvention wird
vorgeschlagen, daß Files, die FORTH-Screens, also Quelltexte, enthalten, die
Endung .SCR erhalten. Files, die Daten enthalten, die nicht unmittelbar lesbar sind,
sollten auf .BLK enden.
Auf makefile hin legt das System eine neue Quelltext-Datei von beispielsweise
26 KB Größe an. Das System geht bei 29KB davon aus, daß 1 KB Programmtexte in
den ersten zehn Blöcken (8 - 9) und 1 KB Kommentare in den Shadow-Screens 19
- 19 eingetragen werden. Das File wird nur logisch (!) in der Mitte geteilt. Wenn
auf allen Screens nur Quelltexte eingetragen werden, so hat das keine negativen
Konsequenzen, Sie bekommen dann nur im Editor mit SHIFT-F9 keinen Kommentar
angezeigt.
Sie haben nun eine Datei, das die Screens 9..19 enthält. Geben Sie jetzt ein:
11 oder 1 edit
Nach der Abfrage einer dreibuchstabigen Kennung, die Sie mit <CR> beantworten
können, editieren Sie jetzt den Screen 1 Ihres neuen Files test.scr . Sie können,
falls der Platz nicht ausreicht, Ihr File später einfach mit more verlängern. Ein
- 86 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
File kann leider nicht verkürzt werden.
Mit dem volksFORTH-Editor können Sie selbstverständlich auch stream files ohne
die FORTH-typische Blockstruktur ansehen und editieren.
Drei wichtige Wörter für screen files sind:
Mit <nn> list wird Screen nn auf dem Bildschirm angezeigt - also zum Beispiel
mit 1 list der Screen 1 des Files TEST.SCR.
Mit <nn> load wird ein Screen nn geladen, d.h. durch den FORTH-Compiler in das
Wörterbuch compiliert.
Mit include <filename> kann man unkompliziert ein ganzes Screenfile laden. Diese
Operation ist der Sequenz use <filename) 1 load äquivalent.
Beim Vergessen eines FORTH-Files mit Hilfe von FORGET , EMPTY usw. werden
automatisch alle Blockpuffer, die aus diesem File stammen, gelöscht und, wenn sie
geändert waren, auf die Diskette zurückgeschrieben. Das File wird anschließend ge-
schlossen. Bei Verwendung von flush werden alle Files geschlossen. FLUSH sollte
vor jedem Diskettenwechsel ausgeführt werden, und zwar nicht nur, um die ge-
änderten Blöcke zurückzuschreiben, sondern auch damit alle Files geschlossen wer-
den. Sind nämlich Files gleichen Namens auf der neuen Diskette vorhanden, so wird
eine abweichende Länge des neuen Files vom FORTH nicht erkannt. Bei Verwendung
von VIEW wird automatisch das richtige File geöffnet.
Sind bereits sehr viele Files geöffnet, kommt.es in der MSDOS-Grundeinstellung
recht schnell zu der Fehlermeldung des Betriebssystems: too many open files . Da-
gegen hilft die Änderung der Datei CONFIG.SYS:
FILES=16
Eine Besonderheit volksFORTH ist der Direktzugriff auf den Massenspeicher. Das
Wort DIRECT schaltet das FileInterface ab und der Massenspeicher wird direkt
physikalisch angesprochen ! j
Wenn nach dem Befehl EMPTY die Meldung F: direct auftaucht, ist das File-
interface abgeschaltet. Solch ein Direktzugriff kann wieder auf das Fileinterface
umgeschaltet werden, indem man einen Dateinamen aufruft. Bei den Dateinamen in
der Liste der FILES ist also kein USE notwendig.
Wenn Sie als Beispiel direkt auf Drive A: zugreifen wollen, so ist die Syntax:
direct a:
Nun kann mit list , load , aber auch mit edit (!) auf die Disk zugegriffen
werden! Deshalb ist bei Festplatten besondere Vorsicht geboten, da der Schreib-
/Lesezeiger direkt auf dem Bootsektor der Platte stehen kann. Sollte Ihnen dies
passieren, verlassen Sie den Editor mit CTRL-U (undo) und <ESC>.
Umgang mit Dateien = 80 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 9.81
Beim Direktzugriff muß allerdings beachtet werden, daß es für volksFORTH nur noch
1 KB große Blöcke gibt, die hintereinander liegen und nur durch ihre Blocknummern
identifiziert sind. Eine 360K DS/DD-Disk enthält dann für volksFORTH keine Files
und kein Directory, sondern es steht lediglich Platz für 362 Blöcke zur Verfügung.
Es gibt zwar einige Leute, die diese direct-Funktion dazu benutzen, um mit dem
FORTH-Editor die Systembereiche ihrer Festplatte zu editieren; aber normalerweise
ermöglicht der Direct-Zugriff dem volksFORTH, ohne MSDOS auszukommen und den
Massenspeicher sehr schnell und effizient zu bedienen.
Einige wichtige Worte:
call (==)
ermöglicht den Aufruf von *,COM und *%.EXE-Files.
call \park würde im Root-Directory Ihrer Harddisk ein Programm namens
PARK aufrufen und ausführen.
msdos 0-2)
verläßt das volksFORTH zur MSDOS-Ebene; mit exit kehren Sie ins
FORTH zurück.
savesystem <name> (-=)
schreibt eine bootbare Form des jetzt laufenden FORTH-Systems unter
dem Namen <name> auf den Massenspeicher. Dabei muß <name> die
Endung .COM haben, wenn dieses System später wieder unter MSDOS ge-
startet werden soll.
Dieses Wort wird benutzt, um fertige Applikationen zu erzeugen. In
diesem Fall sollte das Wort, daß die Applikation ausführt, in 'COLD
gespeichert. Ein Beispiel:
Sie haben ein Kopierprogramm geschrieben, das oberste ausführende Wort
heißt COPYDISK . Mit der Befehlsfolge
' copydisk Is 'cold
savesystem copy.com
erhalten Sie ein Progamm namens COPY.COM , das sofort beim Start
COPYDISK ausführt.
direct ( ==)
schaltet das MSDOS-Fileinterface aus und auf Direktzugriff um. Auf den
Filezugriff schalten Sie durch das Nennen eines Filenamens um.
- 88 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
7.1 Pfad-Unterstützung
volksFORTH besitzt eine eigene, vollständig von MSDOS unabhängige Pfadunter-
stützung. Die Verwaltung von Directories entspricht in etwa der des MSDOS-
Command-interpreters COMMAND.COM .
Beispiel: PATH A:\;B:\COPYALL\DEMO; \AUTO\
In diesem Beispiel wird zunächst die Diskstation A, dann das Directory
COPYALL\DEMO auf Diskstation B und schließlich das Directory AUTO auf dem
aktuellen Laufwerk gesucht.
Beachten Sie bitte das Zeichen "\" vor und hinter AUTO . Das vordere Zeichen "\"
steht für das Hauptdirectory. Wird es weggelassen, so wird AUTO\ an das mit
DIR gewählte Directory angehängt. Das hintere Zeichen "\" trennt den Filenamen
vom Pfadnamen.
Durch die vollständige Unabhängigkeit kann z.B. volksFORTH mit dem Pfad
C:\4TH; \4TH\WORK arbeiten, während MSDOS den Pfad C:\UTIL\TOOLS absucht.
path (--)
Dieses Wort gestattet es, mehrere Directories nach einem zu Öffnenden
File durchsuchen zu lassen. Das ist dann praktisch, wenn man mit
mehreren Files arbeitet, die sich in verschiedenen Directories oder
Diskstationen befinden. Es wird in den folgenden Formen benutzt:
path dirl;\dir2\subdir2;\dir3
Hierbei sind <dirl>, <dir2> etc. Pfadnamen. Wird ein File auf dem Mas-
“ senspeicher gesucht, so wird zunächst <diri>, dann <dir2> etc. durch-
sucht. Zum Schluß wird das File dann im aktuellen Directory (siehe DIR)
gesucht. Beachten Sie bitte, daß keine Leerzeichen in der Reihe der Pfad-
namen auftreten dürfen.
path ohne Argument zeigt die aktuelle Pfadangabe und druckt
die Reihe der Pfadnamen aus. Dieses Wort entspricht dem Kommando PATH
des Kommandointerpreters.
path ; löscht die aktuelle Pfadangabe und es wird nur noch das
aktuelle Directory durchsucht.
7.2 DOS-Befehle
dos
Viele Worte des Fileinterfaces, die normalerweise nicht benötigt werden,
sind in diesem Vokabular enthalten.
Umgang mit Dateien = 89I--
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
dir
zeigt das Inhaltsverzeichnis des Massenspeichers. Ohne weitere Eingaben
wird der aktuelle Suchpfad einschließlich des Laufwerks angezeigt.
delete <filename>
löscht eine Datei <filename> im aktuellen Directory .
ren <filename.alt> <filename.neu>
benennt eine Datei nach üblicher MSDOS-Syntax um.
ftype <filename>
gibt eine Text-Datei aus. FTYPE wurde so genannt, weil es ein FORTH-
Wort type gibt.
md <dir>
legt ein neues Directory an.
cd <dir>
wechselt Directory (mit Pfadangabe).
rd <dir>
löscht ein Directory.
dos: FORTH-Name DOS-Name "
DOS: erwartet nach seinem Aufruf zwei Namen: Zuerst den FORTH-Namen,
den der Befehl haben soll, dann den Namen der DOS-Funktion, die aus-
geführt werden soll. Diese wird von einem Leerzeichen und einem quote "
abgeschlossen. Ein Beispiel ist:
dos: £ftype type "
Danach wird beim Aufruf des FORTH-Wortes FTYPE der MSDOS-Befehl
TYPE ausgeführt.
7.3 Block-orientierte Dateien
Damit volksFORTH effizient auf den Massenspeicher zugreifen kann, bietet es -
wie die meisten anderen FORTH-Systeme auch -— einen besonderen Puffermechanis-
mus für den Diskzugriff. Dadurch wird der Geschwindigkeitsunterschied zwischen
den langsamen Laufwerken und dem schnellen Hauptspeicher ausgeglichen.
Entgegen der Literatur [Brodie) ist im volkFORTH das Ende eines Screens nicht
durch ein Doppel-Nullbyte 08 gekennzeichnet. volksFORTH arbeitet statt dessen mit
SKIP und SCAN und wertet die Länge aus, die in >in bereits abgearbeitet ist.
= 98 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
view
list
files
isfile
isfile@
fromfile
fswap
[FCB]
file
( <name) -- )
wird in der Form view <name> benutzt.
Wenn <name> im Wörterbuch gefunden wird, so wird das File geöffnet, in
dem der Quelltext von <name> steht und der Block wird gelistet, auf dem
<name> definiert ist.
Siehe: LIST
C(bik# --)
zeigt den block mit der angegebenen Nummer an.
==)
zeigt alle FORTH-Dateien an. Diese müssen nicht mit den MSDOS-Files
identisch sein. Dagegen zeigt dir die MSDOS-Files an.
( -- addr )
ist die Adresse einer Variablen, die auf das aktuelle FORTH-File zeigt.
Der Wert in dieser Variablen entspricht typisch der Adresse des File-
ControlBlocks FCB. Ist der Wert in dieser Adresse gleich Null, so wird
direkt ohne ein File auf den Massenspeicher zugegriffen.
(== fcb)
holt den FCB des isfile. Die Sequenz
isfile@ f.handle @
liefert die DOS-Handlenummer.
( -- addr )
ist die Adresse einer Variablen, die auf das FORTH-File zeigt, aus dem
copy und convey die Blöcke lesen.
fronfile @ liefert den FCB dieser Datei.
v==,)
vertauscht isfile und fromfile .
Vergleiche im Editor das Drücken der Taste F9.
(== fcb )
ist eine Konstante des Typs FCB und dient für Vergleiche, ob ein Wort
einen FCB darstellt. Es ist definiert als:
' kernel.scr @
( fceb --) DOS
druckt den FORTH-Filenamen des Files aus, dessen FCB-Adresse auf dem
Stack liegt.
Umgang mit Dateien - 9 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
filename ( -- addr ) Dos
ist die Anfangsadresse eines 62-Byte großen Speicherbereichs, der zum
Ablegen von Filenamen während DOS-File-Operationen dient.
fnamelen (-- N) DOS
ist eine Konstante, die die maximale Länge von logischen Filenamen, be-
stehend aus Drive, Path und Name, die in den FCB's abgespeichert werden
können, bestimmt. Wird dieser Wert verändert, so kann die neue Länge
erst in den FCB's verwendet werden, die nach der Änderung angelegt
werden.
AUBiICHDHELE GH (=)
Entspricht MS-DOS, macht das dadurch bezeichnete logische Laufwerk zum =
aktuellen Laufwerk.
DTA ( -- 888 )
ist als Konstante die Start-Adresse der DiskTransferArea.
capacities ( -- addr )
ist die Adresse eines Vektors, der die Kapazitäten der angeschlossenen
logischen Laufwerken in 1ikByte-Blöcken enthält. Dafür sind maximal 6
Einträge (siehe: #DRIVES ) vorgesehen. Mit dem Hilfsprogramm DISKS.CFG
können die Kapazitäten für die Diskettenlaufwerke eingestellt werden.
drv ( -- #drive )
übergibt die Nummer des aktuellen Laufwerks.
drive ( #drive -- )
macht das Laufwerk mit der angegebenen Nummerzum aktuellen Laufwerk.
Hierbei entspricht n=®d dem Laufwerk A, n=1 dem Laufwerk B usw. . Auf
dem aktuellen Laufwerk werden Files und Directories erzeugt (und nach
Durchsuchen von PATH gesucht).
8 block liefert die Adresse des ersten Blocks auf dem aktuellen Lauf-
werk. ö
Vergleiche »drive und offset..
file <name>
erzeugt ein FORTH-Wort mit dem gleichen Namen. Wird dieses Wort später
aufgerufen, so vermerkt es sich als aktuelles File isfile und als
Hintergund-Datei fromfile . Diesem logischen FORTH-File kann man dann
mit assign oder make eine MSDOS-Datei zuordnen.
= 92 = Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
make <name>
wird in der Form
make (Dateiname)
benutzt. Es erzeugt ein MSDOS-File im aktuellen Directory und ordnet es
dem aktuellen FORTH-File zu. Es hat die Länge Null (siehe more ),
Beispiel: file test.scr test.scr make test.scr'
makefile (name>
assign
file?
file
load
bIk
erzeugt eine FORTH-Datei mit diesem Namen und ebenfalls eine MSDOS-
Datei mit dem gleichen Namen. Dieses File wird auch sofort geöffnet, hat
aber noch die Länge ®, wenn keine Größe mit nn more angegeben wurde.
makefile ist ein Ersatz für die Prozedur in dem Beispiel, das bei make
angegeben wurde.
)
wird benutzt in der Form
assign (filename)
und weist dem aktuellen logischen FORTH-File eine physikalische DOS-
Datei zu.
(=)
zeigt den FORTH-Filenamen des aktuellen Files an.
(==)
zeigt den MSDOS-Namen, das Handle sowie Datum des letzten Zugriffs der
aktuellen Datei.
Cbik# --)
lädt/compiliert den block mit der angegebenen Nummer an.
( -- addr )
ist die Adresse einer Variablen, die die Blocknummer des gerade inter-
pretierten Blocks enthält. Wird TIB interpretiert, enthält BLK den
Wert NULL ; d.h., auch wenn Sie den Inhalt interaktiv auslesen, so
erhalten Sie immer den Wert 9 !
Umgang mit Dateien u Zum
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
loadfrom (bIk# --)
wird in folgender Form benutzt:
( block# ) loadfrom “Dateiname>
Dies ist wichtig, wenn während des Compilierens Teile eines anderen
Files geladen werden sollen. Damit kann die Funktion eines Linkers imi-
tiert werden.
Beispiel: 15 loadfrom tools.scr
Dieses Wort benutzt use, um Files zu selektieren; das bedeutet, daß in
diesem Beispiel automatisch eine Datei namens tools.scr erzeugt wird,
falls dieses File noch nicht existierte.
Dieses Wort hat nichts mit from oder fromfile zu tun, obwohl es
ähnlich heißt.
include (==)
wird in der Form benutzt:
include <Dateiname>
Hier wird ein File vollständig geladen. Voraussetzung ist, daß in Screen
#1 Anweisungen stehen, die zum Laden aller Screens führen.
b/blk ( -- &1024 ) "bytes pro block"
ist die Länge eines Blocks (bzw. Screens, immer 1 KByte) wird auf den
Stack gelegt.
Siehe B/BUF.
b/buf ( =n,;) "bytes pro buffer"
n ist die Länge eines Blockpuffers incl. der Verwaltungs-informationen
des Systems, in der Version 3.81 für den PC $%408 Byte, bestehend aus
$408 Byte Puffer und $8 Byte Verwaltungsinformation.
bIk/drv -—-n) "blocks pro drive"
n ist die Anzahl der auf dem aktuellen Laufwerk verfügbaren Blöcke.
(more Rs)
wie MORE , jedoch wird das File nicht geschlossen.
more (n--)
vergrößert die aktuelle Datei (isfile) um eine bestimmte Anzahl von
Blöcken, die hinter angehängt werden. Anschließend wird die Datei ge-
schlossen.
- 94. - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
capacity (--n)
n ist die Speicherkapazität einer Datei, wobei Block ® mitgezählt wird.
Deshalb ist für Quelltexte nur capacity 1- (d.h. minus Block 9)
nutzbar. Wenn shadow screens verwendet werden, steht nur capacity
2/ 1- zur Verfügung.
block { u-- addr ) 83
addr ist die Adresse des ersten Bytes des Blocks u in dessen Blockpuffer.
Der Block u stammt aus dem File in ISFILE.
BLOCK prüft den Pufferbereich auf die Existenz des Blocks Nummer u.
Befindet sich der Block u in keinem der Blockpuffer, so wird er vom Mas-
senspeicher in einen an ihn vergebenen Blockpuffer geladen. Falls der
Block in diesem Puffer als UPDATEd markiert ist, wird er auf den Mas-
senspeicher gesichert, bevor der Blockpuffer an den Block u vergeben
wird.
Nur die Daten im letzten Puffer, der über BLOCK oder BUFFER ange-
sprochen wurde, sind sicher zugreifbar. Alle anderen Blockpuffer dürfen
nicht mehr als gültig angenommen werden (möglicherweise existiert nur 1
Blockpuffer).
Vorsicht ist bei Benutzung des Multitaskers geboten, da eine andere Task
block oder buffer ausführen kann. Der Inhalt eines Blockpuffers wird
nur auf den Massenspeicher gesichert, wenn der Block mit update als
verändert gekennzeichnet wurde.
(block ( bik file -- addr )
liest den Block blk aus dem File, dessen FCB bei der Adresse file beginnt
und legt diesen in einen Puffer bei der Adresse addr ab.
buffer ( block# -- addr )
weist dem block mit der angegebenen Nummer einen Blockpuffer im Spei-
cher zu. Die Zuweisung wird von der internen Logik vorgenommen - an-
schließend wird die Startadresse dieses Pufferbereiches übergeben. Dabei
entspricht addr der Adresse des ersten Bytes des Blocks in seinem Puffer.
Der große Unterschied zwischen block und buffer ist, daß block
tatsächlich die Daten von Disk in den Puffer liest. buffer dagegen re-
serviert nur den Puffer, initialisiert ihn nicht und liest keine Daten vom
Massenspeicher. Daher ist der Inhalt dieses Blockpuffers undefiniert.
(buffer ( bIik file -- addr )
reserviert einen 1kByte großen Puffer im Adreßbereich des FORTH-
Systems für den Block biIk. file ist die Adresse des FCB's, in dem sich
der Block befindet. Ist file = ®, dann handelt es sich um einen DIRECTen
physikalischen Zugriff. addr ist die Anfangsadresse des Puffers.
Umgang mit Dateien = 98.—
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
offset ( -- addr )
liefert die Adresse einer UserVariablen, deren Inhalt zu der Blocknummer
addiert wird, die sich beim Aufruf von block , buffer usw. auf dem
Stack befindet.
fblock@ ( addr bik fcb -- ) DOS
1024 Bytes, die im File fcb in Block blk stehen, werden ab der Adresse
addr im FORTH-Adressbereich abgelegt.
fblockt Kkaddrı. bIK feb —— ) DOS
1024 Bytes, die ab der Adresse addr innerhalb des FORTH-Adressbereichs
stehen, werden auf den Block bik innerhalb des Files geschrieben, das
durch fcb characterisiert ist.
*block C(bIik --d) DOS
Die doppeltgenaue Zahl d ist die Byteadresse des ersten Bytes im 1924-
Byte großen Block bIk.
/block (d-- rest bik ) DOS
Die doppeltgenaue Zahl D wird umgerechnet in die REST-Anzahl von
Bytes innerhalb des 1924-Byte großen Blocks bIk.
r/w ( addr bIk fcb r/w -- *f )
ist ein deferred Wort, bei dessen Aufruf das systemabhängige Wort für
den blockorientierten Massenspeicherzugriff ausgeführt wird.
Dabei ist addr die Anfangsadresse des Speicherbereiches für den Block
block, fcb die Addresse des Files, in dem sich der Block befindet. r/w ist
gleich Null, wenn vom Speicherbereich auf den Massenspeicher geschrie-
ben werden soll oder r/w =1, wenn der Block gelesen werden soll. *f ist
nur im Fehlerfall wahr, sonst falsch.
(r/w ( addr bik fcb r/w -- *f )
Die Standardroutine für das deferred Wort R/W.
eof ( -- true )
entspricht der Konstanten TRUE = -1.
- 96 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
7.4 Verwaltung der Block-Puffer
core? ( bIk# filename -- addr ! ff )
prüft, ob sich der Block mit der angegebenen Nummer aus der genannten
Datei bereits in einem der Block-Puffer befindet. Wenn das der Fall ist,
wird die Anfangsadresse des Puffers übergeben, anderenfalls ein false
flag . “
Vergleiche BLOCK , BUFFER und ISFILE.
(core? ( blk# filename -- addr ! false )
ist die Standardroutine für das Wort CORE? .
update (==)
markiert den zur Zeit gültigen Pufferspeicher als verändert. Von dieser
update-Kennzeichnung wird dann die Sicherung der Daten abhängig ge-
macht, wenn dieser Blockpuffer für einen anderen Block benötigt oder
wenn SAVE-BUFFERS ausgeführt wird.
Vergleiche PREV .
save-buffers N)
Das Alias sav im Editor heißt normalerweise save-buffers und rettet
alle als UPDATEd markierten Pufferbereiche auf Disk und löscht die
UPDATE-Kennzeichnungen. Hierbei bleibt die bestehende Zuweisung blk ->
buffer erhalten, die Blöcke werden jedoch nicht verändert und bleiben für
weitere Zugriffe im Speicher erhalten.
flush A)
schreibt alle als UPDATEd markierten Pufferbereiche auf Disk und löscht
die UPDATE-Markierung. Allerdings wird jetzt die Zuweisung BLK ->
BUFFER zerstört. Zugleich wird die Datei geschlossen und das Inhaltsver-
zeichnis aktualisiert.
Vergleiche SAVE-BUFFERS und EMPTY-BUFFERS .
emptybuf ( buffer.addr -- )
empty-buffers GE)
löscht den Inhalt aller Blockpuffer, ohne die Daten von als UPDATEd4
markierten Blockpuffern auf den Massenspeicher zurückzuschreiben. Es
zerstört die Zuweisung BLK -> BUFFER und löscht die UPDATE-Mar-
kierung.
Umgang mit Dateien = Imre
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
freebuffer ("e=a)
Entfernt den Blockpuffer mit der niedrigsten Adresse aus der Liste der
Blockpuffer und gibt den dadurch belegten Speicherbereich frei. FIRST
wird entsprechend um B/BUF erhöht. Ist der Inhalt des Puffers als
UPDATEd markiert, so wird er zuvor auf den Massenspeicher gesichert.
Gibt es im System nur noch einen Blockpuffer, so geschieht nichts.
Vergleiche ALLOTBUFFER .
allotbuffer (=)
Fügt der Liste der Blockpuffer noch einen weiteren hinzu, falls oberhalb
vom Ende des Retunstacks dafür noch Platz ist. FIRST wird entspre-
chend geändert.
Vergleiche FREEBUFFER und ALL-BUFFERS .
all-buffers ==)
Belegt den gesamten Speicherbereich von LIMIT abwärts bis zum oberen
Ende des Returnstacks mit Blockpuffern.
Siehe ALLOTBUFFER .
first ( -- addr )
ist eine Variable, die einen Zeiger auf den Blockpuffer mit der niedrig-
sten Adresse darstellt. So liefert Ihnen FIRST @ die Startadresse des
Blockpufferbereiches.
Vergleiche ALLOTBUFFER .
limit ( -- addr )
ist im Gegensatz zu FIRST keine Variable, sondern liefert direkt die
addr, unterhalb der sich die Blockpuffer befinden. Das letzte Byte des
obersten Blockpuffers befindet sich in addr-1.
Vergleiche ALL-BUFFERS und ALLOTBUFFER.
Die Anzahl der Blockpuffer im aktuellen System läßt sich so ausrechnen:
:» #buf ( -- Anzahl )
linit first@e- b/buf/ ;
prev ( -- addr )
addr ist die Adresse einer Variablen, deren Wert der Anfang der Liste
aller Blockpuffer ist. Der erste Blockpuffer in der Liste ist der zuletzt
durch BLOCK oder BUFFER vergebene.
offset ( -- addr )
addr ist die Adresse einer Uservariablen, deren Inhalt zu der Block-
nummer addiert wird, die sich bei Aufruf von BLOCK , BUFFER usw.
auf dem Stack befindet. OFFSET wird durch DRIVE verändert.
=, Ge Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
status (--)
ist ein defered Wort, das vor dem Laden eines Blockes oder vor dem Ab-
arbeiten der Tastatureingabe ausgeführt wird. Normalerweise ist es mit
NOOP vorbesetzt.
7.5 Index-, Verschiebe- und Kopierfunktionen für Block-Files
Die meisten FORTH-Systeme, die bevorzugt mit Block-Dateien arbeiten, verfügen
über eine INDEX-Funktion, die die Zeile 8 eines jeden Screens anzeigt. Diese Zeile
gibt üblicherweise den Inhalt des Screens an.
Allgemein ist die Syntax für Index: (start) <end) index
Das nachfolgend beschriebene INDEX erwartet dagegen nur die Angabe des Blockes,
bei dem die INDEX-Anzeige beginnen soll ; wird kein Argument übergeben, so
beginnt die INDEX-Anzeige mit Screen 1. Auch können nach dem Kompilieren die
durch i als headerless gekennzeichneten Worte mit clear gelöscht werden.
| : range ( from to -- to+1 from )
2dup u) IF swap THEN 1+ swap ;
i : .„£fnane isfile@ [ DOS ]J .file ;
: index ( from -- )
depth 0= IF 1 THEN capacity 1- range
." von " .fnane
( range) DO cr I4 .r space
I block c/l -trailing type
stop? IF leave THEN
LOOP ;
copy (ul u2--)
Der Block ul wird in den Block u2 kopiert.
Innerhalb einer Datei wird ein bereits beschriebener Zielblock überschrie-
ben, der alte Inhalt des Blocks u2 ist verloren.
Vergleiche auch CONVEY. j
Ist ein FROMFILE angemeldet, so arbeitet COPY immer in Bezug auf
das FROMFILE.. Der Befehl 3 4 copy kopiert dann den Block# 3 aus
der Hintergrunddatei FROMFILE in die aktuelle Datei ISFILE und nicht
innerhalb des ISFILE ! \ \
Umgang mit Dateien =#99 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
from <name>
gibt an, aus welchem File bei Datei-Operationen herauskopiert werden
soll. Vergleiche auch die Datei STREAM.SCR .
from abc.scr 1 10 copy
kopiert den Block 1 von File FROMFILE in den Block# 18 ins aktuelle
ISFILE , wobei der Zielblock leer sein muß; soll nicht überschrieben, son-
dern eingefügt werden, wird
from abc.scr 1 18 1 convey
eingesetzt.
convey ( 1st.block last.block to.block -- )
Verschiebt die Blöcke von I1st.block bis einschließlich last.block nach
to.block. Die Bereiche dürfen sich überlappen. Eine Fehlerbehandlung wird
eingeleitet, wenn last.block kleiner als 1st.block ist. —
Die Blöcke werden aus dem File in FROMFILE ausgelesen und in das
File in ISFILE geschrieben. FROMFILE und ISFILE dürfen gleich sein,
Das Beispiel
46 5 convey
kopiert die Blöcke 4,5,6 nach 5,6,7. Der alte Inhalt des Blockes 7 ist
verloren, der Inhalt der Blöcke 4 und 5 ist gleich.
CONVEY wird auch benutzt, wenn man gerne einen freien Block in ein
Blockfile einfügen möchte:
(INSERT ( start# -- )
fügt an der angegebenen Zielposition einen Block ein.
: (insert ( start# -- )
dup 1+ capacity 1- swap 1 more convey ;
INSERT =)
fügt vor dem aktuellen Block einen Block ein.
: insert (==)
scr @ dup (insert
block b/blk blank update ;
7.6 FCB-orientierte Dateien
pushfile (==) c
wird in :-Definitionen benutzt, um den aktuellen Zustand der File-
variablen ISFILE und FROMFILE nach dem Ende der Colon-Definition
wiederherzustellen.
Vergleichen Sie bitte den Mechanismus der lokalen Variablen: PUSH
- 100 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
open C-—)
öffnet das aktuelle File zur Bearbeitung; ist aber in den meisten Fällen
überflüssig, weil Files beim Zugriff automatisch geöffnet werden.
tmptyfile ==)
legt eine leere Datei zum aktuellen Dateinamen an. Wird z.B in MAKE
benutzt.
killfile (==)
löscht ohne weitere Rückfrage des aktuelle MSDOS-File; das aktuelle
FORTH-File wird dabei nicht gelöscht, denn das FORTH-File ist wie eine
Dateivariable in anderen Sprachen zu betrachten und dementsprechend als
Variable mit forget <filename> zu löschen.
close (==)
schließt das aktuelle File und aktualisiert das Inhaltsverzeichnis des
Massenspeichers.
flush Ge)
schließt alle geöffneten Dateien und aktualisiert das Inhaltsverzeichnis
des Massenspeichers. Zugleich werden alle Zwischenpuffer auf die Disk
zurückgeschrieben.
fopen (fcb -- )
ist im volks4TH nicht vorhanden, weil die erwartete Funktion von
FRESET erfüllt wird. Deshalb kann man dies so definieren:
' FRESET Alias FOPEN
freset (fcb--) DOS
fcb ist die Adresse eines FileControlBlocks. Das dadurch charakterisierte
File wird "zurückgesetzt", d.h. das File wird geöffnet (wenn es noch nicht
geöffnet war) und der Schreib/Lesezeiger wird auf den Anfang des Files
gesetzt.
felose (feb -= ) DOS
Das File, dessen FCB-Adresse auf dem Stack liegt, wird geschlossen.
fgete ( fcb -- 8b I eof ) DOS
Aus dem File, dessen FCB-Adresse auf dem Stack liegt, wird das nächste
Byte gelesen und der Schreib/Lesezeiger um eine Position weitergerückt.
Wenn das letzte Byte bereits gelesen war, wird die End-Of-File-Mar-
kierung -1 zurückgegeben.
Umgang mit Dateien — Io >
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
fpute (8b fcb -- ) DOS
Das Byte 8B wird an der aktuellen Position des Schreib/Lesezeigers in
das File FCB geschrieben. Dabei wird der Zeiger um eine Position weiter
gerückt.
file@ ( dfaddr fcb -- Sb | eof ) DOS
Das Byte an der 32-bit Position dfaddr im File, daß durch fcb charak-
terisiert ist, wird gelesen. Liegt dfaddr jenseits des letzten Bytes im File,
so wird -1 zurückgegeben. Nach erfolgreichem Lesen steht der Lese-
/Schreibzeiger hinter dem gelesenen Byte.
file! ( 8b dfaddr fcb -- ) DOS
Das Byte 8B wird an die Position dfaddr des Files fcb geschrieben.
fseek ( dfaddr fcb -- ) DOS
Der Schreib/Lesezeiger des Files, das durch fcb charakterisiert ist, wird
auf die Position dfaddr gesetzt. Dabei ist dfaddr eine doppeltgenaue Zahl,
so daß maximal Files von 4-GByte Größe verwaltet werden können.
savefile ( addr len -- )
wird in der Form:
savefile (name?
benutzt und schreibt die Anzahl von len Bytes ab der Adresse addr in
das neu erzeugte File mit dem Namen <name»>.
lfsave ( seg:addr quan string -- )
erzeugt ein File mit dem Namen, der als gecounteter String an der
Adresse string abgelegt ist und schreibt die Anzahl quan Bytes ab der
erweiterten Adresse seg:addr in dieses neue File.
lfputs ( seg:addr quan fcb -- )
quan Bytes ab der erweiterten Adresse seg:addr werden ab der aktuellen
Position des Schreib/Lesezeigers in das File geschrieben, das durch fecb
charakterisiert ist. Danach steht der Schreib/Lesezeiger hinter dem letz- —
ten geschriebenen Byte. Um z.B. den Bildschirmspeicher in seinem aktu-
ellen Zustand in eine Datei zu schreiben, wird es in der Form benutzt:
. open video® O6 c/dis isfile@ lfputs close ...
Ifgets ( seg:addr quan fcb -- #read ) DOS
siehe: READ . Lediglich wird statt der Handlenummer die Adresse des
FCB's des gewünschten Files angegeben. Entsprechend dem Beispiel bei
'LFPUTS lassen sich mit diesem Wort Bildschirmmasken direkt in den Bild-
schirmspeicher laden. .
= 102» Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
asciz
asciz
counted
loadfile
file-link
"creat
"open
( -- asciz )
holt das nächste Wort im Quelltext in den Speicher und legt es als null-
terminierten String bei der Adresse asciz ab.
( string addr -- asciz )
Mit diesem Operator wird der gecountete String an der Adresse string
umgewandelt in einen nullterminierten String, der an der Adresse addr
abgelegt wird. asciz ist die Adresse, an der der neue String liegt.
( asciz -- addr len )
wird benutzt, um die Länge eines mit einer Null terminierten Strings zu
bestimmen. asciz ist die Anfangsadresse dieses Strings (MS-DOS verwaltet
Strings so), addr und len sind die Stringparameter, die z.B. von TYPE
verarbeitet werden würden.
( -- addr )
ist eine Variable als Pointer auf das File, das gerade geladen wird.
( -- addr )
ist eine Variable, die den Anfang zur Verwaltung einer Liste der File-
Control-Blöcke (FCB) enthält. Der Inhalt von FILE-LINK zeigt auf den
Anfang des Parameterfeldes des zuletzt definierten FCB's - und an dieser
Stelle steht dann die Adresse des davor definierten FCB's usw., so daß
dadurch alle FCB's aufgefunden werden können. Diese Liste wird u.a. von
forget und files benutzt.
7.7 HANDLE-orientierte Dateien
( asciz attribut -- handle ff ! err#) DOs
Der MS-DOS Systemaufruf, um ein neues File zu erzeugen.
( asciz mode -- handle ff | err#) DOS
Der MS-DOS Systemaufruf für das Öffnen eines Files. asciz ist die
Adresse des vollen Namensstrings und mode bezeichnet die Art des File-
Attributes. Dabei sind mögliche Attribute :
0 Constant read-only
1 Constant write-only
2 Constant read-write
Bei Erfolg liegt eine HANDLE-Nummer unter einer Null auf dem Stack,
ansonsten eine Fehlernummer.
Umgang mit Dateien - 103 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
"read
"close
"unlink
"dir
"select
"disk?
attribut
(fsearch
fsearch
( seg:addr quan handle -- #read ) DOS
quan Bytes werden aus dem File gelesen, daß durch die Kennummer
handle charakterisiert ist. Sie werden im erweiterten Speicherbereich bei
seg:addr abgelegt. Nach Ende der Leseoperation liegt die Anzahl der
Bytes auf dem Stack, die tatsächlich bis zum Ende des Files gelesen
werden konnten. Es können jedoch nur maximal 64kByte auf einmal ge-
lesen werden.
( handle -- ) DOS
Der MS-DOS Systemaufruf, um das File, das durch handle characterisiert
ist, zu schließen. °
( asciz -- err# ) DOS
Der MS-DOS Systemaufruf, um einen Fileeintrag zu löschen.
( addr drive -- err#) DOS
Der MS-DOS Systemaufruf, mit dem das aktuelle Directory an der Adresse
addr als nullterminierter String abgelegt wird.
(Mes) DOS
Der MS-DOS Systemaufruf, mit dem das aktuelle Laufwerk selektiert wird.
(==) DOS
Der MS-DOS Systemaufruf, mit dem das aktuelle Laufwerk abgefragt wird.
( -- addr ) DOS
Eine Variable, die die File-Attribute enthält, die bei der Suche nach
Files in einem Directory berücksichtigt werden. Standardmäßig mit 7 ini-
tialisiert, so daß in die Suche read-only, hidden und system -Files ein-
geschlossen sind.
( string -- asciz *#f ) DOS
Das File, dessen Name als String ab Adresse string steht, wird in der
Directory gesucht. Enthält der Filename keine Suchpfadinformation, dann
wird im aktuellen Directory gesucht. Bei Erfolg liegt eine Null auf dem
Stack, sonst eine Fehlernummer.
( string -- asciz *#f ) DOS
Ein deferred Wort. Es enthält die Suchstrategie (siehe: (FSEARCH ), die
beim Öffnen eines Files verwendet wird, um das File auf der Disk zu
lokalisieren,
- 194 -
Umgang mit Dateien
_
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
"first
"next
direct
#drives
/drive
»drive
capacity
?diskerror
( asciz attr -- err#) DOS
Der MS-DOS Systemaufruf, um erstmalig nach einem File zu suchen.
(--err#) DOS
Der MS-DOS Systemaufruf, der nach FIRST benutzt wird, um weitere
passende Filenamen aufzufinden.
7.8 Direkt-Zugriff auf Disketten
(==)
Die Filevariablen werden auf Null gesetzt und damit beziehen sich die
Diskzugriffe durch BLOCK auf physikalische Blocks.
(=--ä)
ist eine Konstante, die die mögliche Anzahl von logischen Laufwerken im
System definiert. Diese Anzahl ist nur im DIRECT-Modus von Bedeutung.
So, wie der Kern compiliert ist, sind maximal 6 Laufwerke zugelassen.
( bIkl -- bIk2 drive )
für den DIRECT-Modus beim Diskzugriff. Aus der absoluten Blocknummer
bIkl wird (siehe: CAPACITIES ) die relative Blocknummer bIlk2 auf Lauf-
werk DRIVE berechnet. Dabei entspricht Laufwerk A: dem Drive ® etc...
( bIkl #drv -- bIk2 ) "to-drive"
dient zum "Umrechnen" von Blocknummern im DIRECT-Modus.
blk2 ist die absolute Blocknummer, die dem relativen Block bikl auf
Drive #drv entspricht. Beispiel
23 1 »drive block
holt den Block mit der Nummer 21 vom Laufwerk 1, egal welches.
Laufwerk gerade das aktuelle ist.
(--n)
gibt die Kapazität in 1024-Byte Blöcken des aktuellen Files bzw. des
aktuellen Laufwerks bei DIRECT-Zugriff.
7.9 Fehlerbehandlung
(==)
Ein deferred Wort, daß die Fehlerbehandlungsroutine für Disk- und File-
zugriffe enthält. Standardmäßig ist die Routine (DISKERROR zugewiesen.
Umgang mit Dateien - 185 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
error# ( -- addr )
Eine Variable, die die Fehlernummer des letzten Fehlers beim Zugriff auf
ein File enthält.
(diskerror ( #err --) DOS
Die Standard-System Fehlerbehandlungsroutine für Fehler beim Diskzu-
griff. Hiermit ist das deferred Wort ?DISKERROR initialisiert.
=3106 - Umgang mit Dateien
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
8. Speicheroperationen
Die INTEL-Prozessoren haben eine verkomplizierte Art, den Adreßraum jenseits von
64kBytes zu adressieren - nämlich mit sogenannten "Segmentregistern".
Am besten kommt man damit noch zurecht, wenn man diese Prozessoren als 16-bit
Prozessoren betrachtet, die in der Lage sind, mehrere Programme, die jeweils höch-
stens 64k Programmspeicherbereich haben, gleichzeitig im Speicher zu halten. Es ist
deshalb auch unvernünftig, auf diesen Prozessoren ein FORTH-System mit 32-bit
Adressen zu installieren - es handelt sich eben nicht um 32-bit Prozessoren.
Um in volksFORTH den gesamten 1 MB-Adreßraum zu nutzen, ist die Möglichkeit
gegeben, aus dem FORTH heraus mit dem Wort call (im DOS-Vokabular) ein weiteres
.COM- oder .EXE-Programm aufzurufen. Dies können natürlich ihrerseits FORTH-
Programme sein, denen dann auch noch eine ganze Eingabezeile als Parameter mit
"auf den Weg" gegeben werden kann.
Damit wäre es zum Beispiel möglich, den Full-Screen Editor aus dem System auszu-
lagern und mit den Befehlen FIX, EDIT, ED usw. jeweils ein .COM-Programm
aufzurufen, das den FORTH-Editor als "stand-alone" Programm enthält und damit
keinen Adreßraum im Entwicklungssystem mehr verbraucht.
Über die Systemvariable RETURN_CODE ist es auch noch möglich, einen Fehlercode
bei Beendigung des FORTH-Programms an MS-DOS zu übergeben, der dann in Batch-
Files getestet werden kann.
Die Intel-Prozessoren setzen die Speicheradressen aus zwei Teilen zusammen, dem
SEGMENT und dem OFFSET. Dies ist jedoch nicht mit "echten" 32Bit-Adressen zu
verwechseln. Diese werden auf einem 16Bit-Stack in der Reihenfolge "low-word"
unter dem "high-word" abgelegt. Überträgt man diese Philosophie auf die
"seg:addr"-Adressen des 8986, dann blockiert dauernd die Segmentadresse den
Stack. |
Deshalb wird bei den Operatoren, die im erweiterten Adreßraum des 8886 operieren,
die Segmentadresse UNTER der Offsetadresse auf den Stack gelegt. Der
Stackkommentar dafür lautet "seg:addr". Den Operatoren, die als Adreßargument
eine "erweiterte" Adresse benötigen, wird ein "l" im Namen vorangestellt.
8.1 Speicheroperationen im 16-Bit-Adressraum
@ ( addr -- 16b ) 83 "fetch"
Von der Adresse addr wird der Wert 16b aus dem Speicher geholt. Siehe
auch !.
volksFORTH enthält nicht das Wort ?.. Benutzen Sie:
2? Cadde-I) 8. ;
Speicheroperationen - 107 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
( 16b addr -- ) 83 "store"
16b werden in den Speicher auf die Adresse addr geschrieben. In 8Bit-
weise adressierten Speichern werden die zwei Bytes addr und addr+l
überschrieben.
+ {wi addr -- ) 83 "plus-store"
wl wird zu dem Wert w in der Adresse addr addiert. Benutzt die plus-
Operation. Die Summe wird in den Speicher in die Adresse addr geschrie-
ben. Der alte Speicherinhalt wird überschrieben.
2! ( 32b addr -- ) 83 "two-store"
32b werden in den Speicher ab Adresse addr geschrieben.
2@ ( addr -- 32b ) 83 "two-fetch"
Von der Adresse addr wird der Wert 32b aus dem Speicher geholt.
c! ( 16b addr -- ) 83 "e-store"
Von 16b werden die niederwertigsten 8 Bit in den Speicher an der
Adresse addr geschrieben.
c@ ( addr -- 8b ) 83 "c-fetch"
Von der Adresse addr wird der Wert 8b aus dem Speicher geholt.
move ( addrd addri u -- )
Beginnend bei addr6 werden u Bytes nach addri kopiert. Dabei ist es
ohne Bedeutung, ob überlappende Speicherbereiche aufwärts oder abwärts
kopiert werden, weil MOVE die passende Routine dazu auswählt. Hat u
den Wert Null, passiert nichts.
Siehe auch CMOVE und CMOVE>.
cmove ( addr® addri u -- ) 83 "c-move"
Beginnend bei addr® werden u Bytes zur Adresse addrl kopiert. Zuerst
wird das Byte von addr® nach addri bewegt und dann aufsteigend fort-
gefahren. Wenn u Null ist, wird nichts kopiert.
cmove> ( addr® addri u -- ) 83 "c-move-up"
Beginnend bei adDr® werden u Bytes zur Adresse adDri kopiert. Zuerst
wird das Byte von addrö +u -1 nach addrl +u -1 kopiert und dann
absteigend fortgefahren. Wenn u Null ist, wird nichts kopiert. Das Wort
wird benutzt, um Speicherinhalte auf höhere Adressen zu verschieben,
wenn die Speicherbereiche sich überlappen.
= 1908 = Speicheroperationen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
fill
erase
blank
flip
ctoggle
off
on
here
align
( addr u 8b -- )
Von der Adresse addr an werden u Bytes des Speichers mit 8b über-
schrieben. Hat u den Wert Null, passiert nichts.
(addru--)
Von der Adresse addr an werden u Bytes im Speicher mit $08 überschrie-
ben. Hat u den Wert Null, passiert nichts.
(add u--)
Von der Adresse addr an werden u Bytes im Speicher mit Leerzeichen BL
(828) überschrieben. Hat u den Wert Null, passiert nichts.
(ul -- u2)
ist das Byteswap des obersten Stackelements.
ul ist eine 16-bit Zahl mit den Bits B15..B8 und B7..B@, wobei man
B15..B8 als das "high-Byte", B8..B®O als das "low-Byte" bezeichnet. Durch
FLIP wird das High- mit dem Low-Byte ausgetauscht, so daß u2 als
Ergebnis die Bits in der Reihenfolge B7..Bß® und B15..B8 angeordnet hat.
Dieses FLIP entspricht der Definition:
: cswap ( 16b -- 16b' ) $100 um* or ;
( 8b addr -- ) 83 "e-toggle"
Für jedes gesetzte Bit in 8b wird im Byte mit der Adresse addr das ent-
sprechende Bit invertiert (d.h. ein zuvor gesetztes Bit ist danach ge-
löscht und ein gelöschtes Bit ist danach gesetzt). Für alle gelöschten
Bits in 8b bleiben die entsprechenden Bits im Byte mit der Adresse addr
unverändert. Der Ausdruck dup c@ rot xor swap c! wirkt genauso.
( addr -- )
schreibt den Wert FALSE in den Speicher mit der Adresse addr.
( addr -- )
schreibt den Wert TRUE in den Speicher mit der Adresse addr.
( -- addr ) 83
addr ist die Adresse des nächsten freien Dictionaryplatzes.
(--)
rundet normalerweise den Dictionary-Pointer und damit auch HERE auf
die nächste geraden Adresse auf. Ist HERE gerade, so geschieht nichts.
Im volks4th für den 8088-Prozessor hat ALIGN keine Wirkung.
Speicheroperationen - 199 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
c
allot
dp
uallot
udp
pad
count
place
( 16b -- ) 83 "comma"
ist ein 2 ALLOT für die gegebenen 16b und speichert diese 16b an
HERE 2- ab.
(8 -- ) "c-comma"
ist ein ALLOT für ein Byte und speichert 1 Byte in HERE 1- ab.
(w--) 83
allokiert w Bytes im Dictionary. Die Adresse des nächsten freien Dic-
tionaryplatzes wird entsprechend verstellt.
( -- addr ) "d-p"
ist eine Uservariable, in der die Adresse des nächsten freien Dictionary-\._
platzes steht.
(nl --n2)
allokiert bzw. deallokiert ni Bytes in der Userarea. n2 gibt den Anfang
des allokierten Bereiches relativ zum Beginn der Userarea an. Eine
Fehlerbehandlung wird eingeleitet, wenn die Userarea voll ist.
( -- addr ) "u-d-p"
ist eine Uservariable, in dem das Ende der bisher allokierten Userarea
vermerkt ist.
( -- addr ) 83
addr ist die Startadresse einer "scratch area". In diesem Speicherbereich
können Daten für Zwischenrechnungen abgelegt werden. Wenn die nächste
verfügbare Stelle für das Dictionary verändert wird, ändert sich auch die
Startadresse von PAD . Die vorherige Startadresse von PAD geht
ebenso wie die Daten dort verloren.
( addri -- addr2 8b ) 83
addr2 ist addri+l und 8b der Inhalt von addri. Das Byte mit der
Adresse addrl enthält die Länge des Strings angegeben in Bytes. Die
Zeichen des Strings beginnen bei addri+1. Die Länge eines Strings darf
im Bereich (9..255) liegen.
Vergleiche "counted String" .
( addri +n addr2 -- )
bewegt +n Bytes von der Adresse addrl zur Adresse addr2+1 und
schreibt den Wert +n in die Speicherstelle mit der Adresse addr2. Wird in
der Regel benutzt, um Text einer bestimmten Länge als "counted string"
abzuspeichern. addr2 darf gleich, größer und auch kleiner als addrl sein.
u
- 118 -
Speicheroperationen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
dump
b/seg
ds@
1@
lc@
le!
lmove
( addr Anzahl -- )
Dieser wichtige Befehl zeigt ab einer gegebenen Adresse eine bestimmte
Anzahl Bytes des Hauptspeichers an. Denn ist es sinnvoll, nachdem man
im Speicher ganze Bereiche reserviert und dort Strukturen abgelegt hat,
sich diese Bereiche auch anzusehen. Ebenso zeigt Ihnen der Befehl
(n)}) block b/blk dump
einen Ihrer Quelltextblöcke an.
(ar)
ist eine Konstante, die angibt, wieviele Bytes zwischen zwei Segmenten
liegen. Dies sind beim 8086 16 Bytes, beim 89286 im 286-Modus jedoch
64 Bytes. volksFORTH auf dem 89286 setzt zur Zeit voraus, daß der
8086-Emulationsmodus eingeschaltet ist.
(--seg )
legt die Segmentadresse des Segments auf den Stack, in dem sich das
maximal 64kByte große FORTH-System gerade befindet. Das Daten-,
Extra-, Stack- und Codesegment werden durch FORTH alle auf den
gleichen Wert gesetzt.
8.2 Segmentierte Speicheroperationen
( seg:addr -- n )
entspricht dem ® , jedoch im erweiterten Adreßraum.
m
n seg:addr -- )
entspricht dem ! , jedoch im erweiterten Adreßraum.
( seg:addr -- 8b )
entspricht dem C®@ , jedoch im erweiterten Adreßraum.
( 8b seg:addr -- )
entspricht dem C! , jedoch im erweiterten Adreßraum.
( from.seg:addr to.seg:addr quan -- )
entspricht dem. MOVE ,„ jedoch im erweiterten Adreßraum. Es können
hiermit maximal 64KBytes auf einmal bewegt werden.
Speicheroperationen - tlul=
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Idump
lallocate
lfree
( seg:addr len -- )
entspricht dem TYPE , jedoch im erweiterten Adreßraum. Es ist zu be-
achten, daß TYPE in den Videodisplaytreibern BIOS.VID und MULTI.VID
so implementiert ist, daß bei Erreichen des Zeilenendes nicht automatisch
ein CR ausgeführt wird. Statt dessen werden alle Zeichen, die "jenseits"
des rechten Rands liegen, nicht ausgegeben.
( seg:addr quan -- ) TOOLS
entspricht dem DUMP , jedoch im erweiterten Adreßraum und zeigt ab
einer angegebenen Adresse eine bestimmte Anzahl Bytes an.
( #pages -- seg ff | rest err# ) EXTEND
Hiermit können im erweiterten Adreßraum die Anzahl #pages Speicher-
platz angefordert werden.
Die Größe einer "Page" in Bytes entspricht der Konstanten B/SEG . Wenn
die Speicheranforderung erfüllt werden kann, dann wird unter einer NULL
als Flag für den Erfolg der Operation die Segmentadresse des ersten Seg-
ments innerhalb eines zusammenhängenden Speicherbereichs von #page
Pages auf den Stack gelegt.
Ansonsten liegt unter einem Fehlercode die maximale Anzahl von Pages,
die noch als zusammenhängender Bereich verfügbar sind. Diese Funktion
ist in dem Wort SAVEVIDEO benutzt, um den Bildschirminhalt in den
Speicher zu kopieren.
Die komplementären Funktionen sind LFREE und RESTOREVIDEO .
( seg -- err# )
Der Speicherbereich, der an der Segmentadresse seg beginnt, wird wieder
an das Betriebssystem zurückgegeben.
Diese Operation ist nur definiert, wenn zu einem vorherigen Zeitpunkt
eine LALLOCATE-Operation durchgeführt worden war, die als Ergebnis die
Segmentadresse seg gehabt hatte.
Es wird ein Fehlercode auf dem Stack übergeben, der im Erfolgsfall ® ist.
= 112 =
Speicheroperationen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
9. Datentypen
Allgemein bestehen Programme aus einem Programm:Datenteil und einem An-
weisungsteil. Dabei enthält der Befehlsteil die zu Algorithmen angeordneten
Befehle, die sich wiederum aus Operanden und Operatoren zusammensetzen. Der
Datenteil dagegen beschreibt eines Programmes den statischen Datenbereich, der die
zu bearbeitenden Daten enthält.
Diese Datenbereiche sind durch die Interpretation ihres Inhaltes strukturiert, wobei
Datenbereiche mit gleicher Strukturierung zum gleichen Datentyp gehören. Denn um
mit einer Reihe von Bytes arbeiten zu können, muß man wissen, ob diese Bytes
eine Zeichenkette, den Inhalt einer Variablen oder die Listenzellen einer :-Defini-
tion darstellen.
Die Strukturierung und Verwaltung sowie die Interpretation des Dateninhaltes im
Datenteil wird in den PASCAL-ähnlichen Sprachen am Programmanfang durch die
Deklarationen der Datentypen, in FORTH dagegen erst im Befehlsteil eines Pro-
grammes durch die eingesetzten Befehle bestimmt.
Da in FORTH die Typisierung über die Auswahl und den Einsatz von geeigneten
Operatoren erfolgt, gehören in FORTH alle die Datenstrukturen dem gleichen Typ
an, denen die Operatoren gemeinsam sind. In FORTH bestimmt also die jeweilige
Operation den Datentyp des entsprechenden Bereiche - so interpretiert die Be-
fehlsfolge pad count type die im Speicherbereich PAD abgelegten Daten als Zei-
chenkette !
Glossar
Create (==) 83
ist ein definierendes Wort, das in der Form:
Create (name)
benutzt wird. CREATE erzeugt einen Kopf für <name».
Die nächste freie Stelle im Dictionary (vergl. HERE und DP ) ist nach
einem CREATE «name das erste Byte des Parameterfelds von <name>.
Wenn <name> ausgeführt wird, legt es die Adresse seines Parameterfelds
auf den Stack. CREATE reserviert keinen Speicherplatz im Parameterfeld
von <name>.
Constant ( 16b -- ) 83
ist ein definierendes Wort, das in der Form:
16b Constant <name)>
benutzt wird. Wird <name> später ausgeführt, so wird 16b auf den Stack
gelegt.
Datentypen ZERks, =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
2Constant
( 32b -- ) 83
ist ein definierendes Wort, das in der Form:
32b 2Constant (name)
benutzt wird. Erzeugt einen Kopf für <name> und legt 32b in dessen
Parameterfeld so ab, daß bei Ausführung von <name> 32b wieder auf den
Stack gelegt wird.
Variable (=) 83
ist ein definierendes Wort, benutzt in der Form:
Variable <name)
VARIABLE erzeugt einen Kopf für <name> im Dictionary und hält 2 Byte
in seinem Parameterfeld frei. Siehe ALLOT .
Dieses Parameterfeld wird für den Inhalt der Variablen benutzt, jedoch
nicht initialisiert. Wird <name> ausgeführt, so wird die Adresse des Para-
meterfeldes von <name> auf den Stack gelegt. Mit @ und ! kann der
Wert von <name> gelesen und geschrieben werden.
Siehe auch +!.
2Variable (a, 83
ist ein definierendes Wort, das in der Form:
2Variable (name)
benutzt wird. Es erzeugt einen Kopf für <name> und hält 4 Byte in sei-
nem Parameterfeld frei, die den Inhalt der doppelt-genauen Variablen
aufnehmen. 2VARIABLE wird nicht initialisiert. Wenn <name> ausgeführt
wird, wird die Adresse des Parameterfelds auf den Stack gelegt.
Siehe VARIABLE .
(--sys ) 83 "colon"
ist ebenfalls ein definierendes Wort, das in der Form:
: <name) <actions) ;
benutzt wird.
Es erzeugt die Wortdefinition für <name> im Kompilations-Vokabular,
schaltet den Kompiler an und kompiliert anschließend den Quelltext wird.
- 14 - Datentypen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Achtung:
Das erste Vokabular der Suchreihenfolge - das "transient" Vokabular -
wird durch das Kompilations-Vokabular ersetzt! Das Kompilations-Voka-
bular wird nicht geändert. .
Soll also das CONTEXT-Vokabular für eine :-Definition geändert werden,
so ist das gewünschte Vokabular entweder innerhalb einer Definition mit
den eckigen Klammern
: <(nane) [ <vocabulary) ] ... ;
zum CONTEXT zu machen oder außerhalb einer Definition zweimal in die
Suchreihenfolge aufzunehmen ( also ) und später zu löschen ( toss ):
<vocabulary?> also
: <colondefinition) ; toss
<name> wird als "colon-definition" oder ":-Definition" bezeichnet. Die
neue Wortdefinition für <name> kann nicht im Dictionary gefunden wer-
den, bis das zugehörige ; oder ;CODE erfolgreich ausgeführt wurde.
RECURSIVE macht <name> jedoch sofort auffindbar.
Vergleiche HIDE und REVEAL .
Eine Fehlerbehandlung wird eingeleitet, wenn ein Wort während der
Kompilation nicht gefunden bzw. nicht in eine Zahl (siehe auch BASE )
gewandelt werden kann.
Der auf dem Stack hinterlassene Wert sys dient der Kompiler-Sicherheit
und wird durch ; bzw. ;CODE abgebaut.
; e-=9) 83 1c "semi-colon"
(sys --) compiling
beendet die Kompilation einer :-Definition.
; macht den Namen dieser colon definition im Dictionary auffindbar,
schaltet den Kompiler aus, den Interpreter ein und kompiliert ein
UNNEST (siehe auch EXIT ). Der Stackparameter sys, der in der Regel
von : hinterlassen wurde, wird geprüft und abgebaut. Eine Fehlerbe-
handlung wird eingeleitet, wenn sys nicht dem erwarteten Wert ent-
spricht.
Datentypen - ms =
FORTH-Gesellschaft e.V. PC-voiksFORTH83 rev. 3.81
Defer
Alias
(sr
ist ein definierendes Wort, das in der Form:
Defer <name)>
benutzt wird. Erzeugt den Kopf für ein neues Wort <name> im Dictionary,
hält 2 Byte in dessen Parameterfeld frei und speichert dort zunächst die
Kompilationsadresse einer Fehlerroutine, Wird <name> nun ausgeführt, so
wird eine Fehlerbehandlung eingeleitet.
Man kann dem Wort <name> jedoch zu jeder Zeit eine andere Funktion
zuweisen mit der Sequenz:
" «action) Is (name)
Nach dieser Zuweisung verhält sich <name> wie <action>.
Mit diesem Mechanismus kann man zwei Probleme elegant lösen:
1: Einerseits läßt sich <name> bereits kompilieren, bevor ihm “
eine sinnvolle Aktion zugewiesen wurde.
2; Andererseits ist die Veränderung des Verhaltens von
<name> für spezielle Zwecke auch nachträglich möglich,
ohne neu kompilieren zu müssen.
Deferred Worte im System sind R/W "COLD 'RESTART 'ABORT 'QUIT
NOTFOUND .STATUS und DISKERR . Diese Worte sind DEFERred, da-
mit ihr Verhalten für die Anwendung geändert werden kann.
( <fä -- )
ist ein Wort, mit dem das Verhalten eines deferred Wortes verändert
werden kann. IS wird in der Form:
' «action? Is <name)
benutzt. Wenn <name> kein deferred Wort ist, wird eine Fehlerbehandlung
eingeleitet, sonst verhält sich <name> anschließend wie <action).
Siehe DEFER .
«ierä,#- )
ist ein definierendes Wort, das typisch in der Form:
'" <oldname)> Alias (newname)
benutzt wird. ALIAS erzeugt einen Kopf für <newname> im Dictionary.
Wird <newname> aufgerufen, so verhält es sich wie \cldname>. Insbeson-
dere wird beim Kompilieren nicht <newname>, sondern <oldname> im Dic-
tionary eingetragen.
= 116 =
Datentypen
FORTH-Geseilschaft e.V. PC-volksFORTH83 rev. 3.81
Vocabulary (=>) 83
Input:
ist e . definierendes Wort, das in der Form:
: Vocabulary (name>
benutzt wird. VOCABULARY erzeugt einen Kopf für <name>, das den
Anfang einer neuen Liste von Worten bildet. Wird <name> ausgeführt, so
werden bei der Suche im Dictionary zuerst die Worte in der Liste von
<name> berücksichtigt. Wird das VOCABULARY (name) durch die Sequenz:
<name)> definitions
zum Kompilations-Vokabular, so werden neue Wort-Definitionen in die
Liste von <name> gehängt.
Vergleiche auch CONTEXT CURRENT ALSO TOSS ONLY FORTH und
ONLYFORTH .
( ==n) "input-colon"
ein definierendes Wort, benutzt in der Form:
Input: (name)
newKEY newKEY? newDECODE newEXPECT ;
INPUT: erzeugt einen Kopf für <name> im Dictionary und kompiliert einen
Satz von Zeigern auf Worte, die für die Eingabe von Zeichen zuständig
sind. Wird <name> ausgeführt, so wird ein Zeiger auf das Parameterfeld
von <name> in die Uservariable INPUT geschrieben. Alle Eingaben wer-
den jetzt über die neuen Eingabeworte abgewickelt.
Die Reihenfolge der Worte nach INPUT: <name> bis zum semi-colon muß
eingehalten werden: ..key ..key? ..decode ..expect .
Im System ist das mit INPUT: definierte Wort keyboard enthalten,
nach dessen Ausführung alle Eingaben von der Tastatur geholt werden.
Siehe DECODE und EXPECT.
Datentypen 47 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Output: (==) "output-colon"
ist ein definierendes Wort, benutzt in der Form:
Output: <name)>
newEMIT newCR newTYPE newDEL newPAGE newAT newAT? ;
OUTPUT: erzeugt einen Kopf für <name> im Dictionary und kompiliert
einen Satz von Zeigern auf Worte, die für die Ausgabe von Zeichen zu-
ständig sind. Wird <name> ausgeführt, so wird ein Zeiger auf das Para-
meterfeld von <name> in die Uservariable OUTPUT geschrieben. Alle
Ausgaben werden jetzt über die neuen Ausgabeworte abgewickelt.
Die Reihenfolge der Worte nach OUTPUT: <name> bis zum semi-colon muß
eingehalten werden: ..emit ..cr ..type ..del ..page ..at ..at?.
Im System ist das mit OUTPUT: definierte Wort display enthalten,
nach dessen Ausführung alle Ausgaben auf den Bildschirm geleitet wer-
den. Vergleiche auch das Wort PRINT aus dem Printer-Interface.
User (--') 83
ist ein definierendes Wort, benutzt in der Form:
User (name)
USER erzeugt einen Kopf für <name> im Dictionary und hält 2 Byte in
der Userarea frei (siehe UALLOT ). Diese 2 Byte werden für den Inhalt
der Uservariablen benutzt und werden nicht initialisiert. Im Parameterfeld
der Uservariablen im Dictionary wird nur ein Offset zum Beginn der
Userarea abgelegt.
Wird <name> ausgeführt, so wird die Adresse des Wertes der Uservariab-
len in der Userarea auf den Stack gelegt.
Uservariablen werden statt normaler Variablen z.B. dann benutzt, wenn
der Einsatz des Multitaskers geplant ist und mindestens eine Task die
Variable unbeeinflußt von anderen Tasks benötigt. Jede Task hat ihre
eigene Userarea.
9.1 Ein- und zweidimensionale Felder
Wie in dem Buch "In FORTH denken" [S.192/193] diskutiert wird, stellen die meisten
FORTH-Systeme aus gutem Grund kein Definitionswort für Arrays zur Verfügung.
Weil aber der Aufbau dieser Definitionen nicht immer problemlos zu handhaben ist
und die notwendigen Algorithmen in der Literatur manchmal falsch dargestellt wer-
den, seien hier die Definitionen für eindimensionale Felder (Vektoren) und zwei-
dimensionale Arrays angegeben.
Diese Datenstrukturen verbergen der zugrunde liegende Zellgröße in eigenen Defini-
tionen, um die Worte ohne die typischen 2+ 2- 2% schreiben zu können. Die
- 118 - Datentypen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Basisgröße der /rressierung in einem 16bit-System ist das Byte, die Adressberech-
nungen arbeiten * 16Bit-, also 2Byte-Adressen.
1 Constant byte
2 Constant integer
4 Constant double
I : bytes ; \ bytes ist 1*
I : integers 2% ; \ Größe eines Bereiches
tı : doubles 4%;
i : byte+t i# ; \ nächste byte-Adresse
I x: integer+ 2+; \ nächste word-Adresse
ı : double+t 4+;
Obwohl FORTH als Sprache keine Typisierung der Daten erwartet, arbeitet die hier
vorgestellte PELD:-Definition mit einer Typübernahme:
: Feld:
Create ( #elements type - )
dup c, *
here over erase
allot
Does) ( index <addr? - addr )
eosnt BE # + 5;
Diese FELD:-Definition übergibt zur Laufzeit die Adresse des gegebenen Elementes,
abhängig vom Typ der Variablen. Das Feld wird zur Compile-Zeit mit Nullen
initialisiert.
In der möglichen Anwendung einer Meßdatenerfassung von Meßstellen wird die
Handhabung von FELD: deutlich:
5 byte Feld: Bonn
5 integer Feld: Köln
5 double Feld: Moers
: Merte cr
5020 IkKkölln @ T7Tu.r LOOP cr;
Der Zugriff auf eine solche Datenstruktur kann z.B. über eine Schleife erfolgen,
wobei - wie immer in FORTH - die zum Datentyp passenden Operatoren einge-
setzt werden müssen.
Die Arbeit mit einer Matrix ist ähnlich, nur wird hier der Zugriff über zwei ge-
schachtelte Schleifen erfolgen. Bitte beachten Sie, daß beim Zugriff FORTH-un-
typische Schleifenvariablen eingesetzt werden, die über dieSynonymdeklaration
Alias definiert wurden.
Diese Definition von MATRIX: übernimmt ebenfalls eine Typangabe:
: Matrix: \ #zeilen #spalten range (double}integeribyte)
\ #zeile #spalte -- element_addr )
Create
2dup swap \ integer!byte #zeile
cr c% \ store #? and #?
* *% dup \ amount bytes amount bytes
here swap erase \ from here amount preset to ®
allot \ amount allot
Datentypen - #9. —
FORTH-Gesellschaft e.V.
PC-volksFORTH83 rev. 3.81
Does>
dup c@ 3 roll *
2 roll +
over bytet
c@ * +
integert
\ Drei Meßstationen haben je 4 Meßwerte erfaßt
\
3 Constant #Stationen
und gespeichert
4 Constant #Werte
' I Alias Stationf
' J Alias Wert#
#Stationen #Werte byte Matrix: Messung
\ Wert!#Stat.|#Wert}Feldname!Operation
10
15
10
#s
3 0 ® Messung
6 0 1 Messung
9 ® 2 Messung
12 0 3 Messung
10 Messung c! 72
11 Messung c! % 2
1 2 Messung c! 9 2
1 3 Messung c! 1 2
all ==)
tationen ® DO cr
#Werte 0 DO
LOOP ;
LOOP
vn”>, rmy,o©
ei
ce!
el
ei
Messung c!
Messung c!
Messung c!
Messung c!
Wert# Station# Messung c@ 3 .r
Den einzelnen Operationen zum Einspeichern der Werte steht das Auslesen der
Werte über zwei geschachtelte Schleifen gegenüber.
Eine weitere, oft genutzte Datenstruktur ist ein Ringpuffer (queue), hier in der
Form eines 255 Byte langen counted strings.
hinten angehängt und vorne ausgelesen, so daß sich eine FIFO-Struktur ergibt:
Create QUEUE © c, 255 allot
more? ( addr -- n)
ce ;
q@ ( addr -- char)
dup more? IF detract exit
In diesen Puffer werden Zeichen
ELSE ." Ringpuffer leer! " drop
THEN ;
a! ( addr char --) append ;
q- ( addr --) count type ;
: gfill ( addr --)
$FF )expect ;
Datentypen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
9.2 Methoden der objektorientierte Programmierung
Der METHODS>-A,.satz entbindet den Programmierer von der Pflicht, jedesmal den
zum Datentyp passenden Operator auswählen zu müssen. Mit den generalisierten
Operatoren get put und show wird die jeweils notwendige Zugriffsmethode aus
einer Tabelle von Methoden ausgeführt .
Mittlerweile bildet sich allerdings als Bezeichnung für generalisierte Operatoren
auch die Syntax x@ x! xtype ein.
\ Terry Rayburn METHODS» euroFORML 87
: Methods) ([compile] Does)»
compile exit ; immediate restrict
\ early binding
[Method]: Create 2* „ immediate Does)
here 2-@e @ 5 + svap@ +@, ;
0 [Method]: [get] 1 [Method]: [put] 2 [Method]: [show]
\ late binding
: Method: Create 2* ,
Does) @ over 2- @ 5 + + perform ;
6 Method: get 1 Method: put 2 Method: show
Der METHODS>-Ansatz wird in den Definitionen so eingesetzt:
: Integer:
Variable Methods) @ ! u? ;
12:2? 2@d.;
: Double:
2Variable Methods) 2@ 2! 2? ;
: Queue: Create B c, 255 allot
Methods) q@ g!gq. ;
clear \ löscht die Namen der Worte auf dem Heap
Später im Programm wird dann mit den generalisierten Methoden auf die Daten-
strukturen zugegriffen:
Integer: Konto 1000 Konto put Konto show
Double: Moleküle 200.000 Moleküle put Moleküle get d.
Queue: Puffer Puffer qfill
Ascii A Puffer put
Puffer show
Die Methods>-Operatoren können mit den bekannten FORTH-Operatoren gemischt
werden. Ebenso können die Tabelle belicbig geändert oder erweitert werden, so z.B.
mit 4 Method: init .
Soll diese Methode des Initialisierens nur bei Integer: eingesetzt werden, sind die
anderen Tabellen entsprechend an der vierten Position aufzufüllen:
Datentypen =, =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
: Integer:
Variable Methods) @ ! u? off ;
i z 2init ( addr -- ) 0. 2swap 2! ;
: Double:
2Variable Methods) 2@ 2! 2? 2init ;
I : ginit GAS)
." Pufferinitialisierung noch nicht definiert! " ;
: Queue: Create ® c, 255 allot
Methods) q@ q! q. qinit ;
Der Zugriff erfolgt dann wie gezeigt mit Konto init oder Druckpuffer init . Die
logische Konsequenz ist die Verbindung beider Möglichkeiten zu :METHODS> :
:Methods) [compile] :Does> compile exit ; immediate
:Methods> erwartet eine Reihe von Operatoren und weist diese (Zugriffs-) —
Methoden dem zuletzt definierten Wort zu. Es wird analog zu :DOES> und
METHODS> in dieser Form eingesetzt:
Create Puffer ® c, 255 allot
:Methods) q@ da! q. qinit ;
Variable Zähler :Methods) @ ! u? off ;
Puffer show zähler init
= 122 - Datentypen
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
18. Manipulieren des Systemverhalten
Das grundlegende Systemverhalten ist bei den traditionellen Programmiersprachen in
der Laufzeit-Bibliothek {runtime library) festgelegt.
Diese runtime library enthält die grundlegenden Routinen, die bei der Ausführung
der Programme vorhanden sein müssen wie z.B. die Bildschirmansteuerung oder den
Massenspeicherzugriff.
In FORTH entspricht das Programm KERNEL.COM dieser Laufzeit-Bibliothek. Auf
diesen Systemkern wird dann die fertige Anwendung, also Ihr Programm, geladen.
Ein Beispiel für eine solche Applikationserstellung ist das Erstellen des volks-
FORTH-Arbeitssystems volks4th.com von der MS-DOS Kommandoebene aus:
A:>kernel include volks4th.sys
Im Gegensatz zu anderen Compilern, denen meist ein Assembler-Quelltext zugrunde
liegt, ist KERNEL.COM aus einem FORTH-Quelltext durch METACOMPILATION erzeugt
worden. Da sich ein FORTH-Quelltext besser pflegen und leichter ändern läßt als
ein Assemblerprogramm, kann das grundlegende Systemverhalten in KERNEL.COM
leicht neuen Erfordernissen anpassen.
18.1 Patchen von FORTH-Befehlen
Möchte man ohne MetaCompilation das Verhalten von Funktion in KERNEL.COM
ändern, so "patcht" man dieses Programm - eine Vorgehensweise, die WordStar-
Nutzern gut bekannt ist. Soll beispielsweise die Funktion des Wortes . (DOT) im
Kern geändert werden, ist so vorzugehen:
\ "patchen" von :-Definitionen im Kern, z.B. ".":
". »body @ Constant altdot
. new. (n--)) RDROP <(new.action) ;
"new. Tut »body ! \ nun läuft die neue Version
altdot ” »body ! \ und nun wieder die alte Version
Dabei ist es wichtig, die neue Arbeitsweise von . mit RDROP einzuleiten.
Im Gegensatz dazu können Sie die Eigenschaften Ihres volksFORTH-Arbeitssystems
über den Inhalt von VOLKS4TH.SYS und durch direkte Änderung der Systemqauell-
texte individuell anpassen werden.
Manipulieren des Systemverhalten =123. =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
18.2 Verwendung von DEFER-Wörtern
Eine weitere Möglichkeit, das Systemverhalten zur Laufzeit zu beeinflussen, wird in
dem Wort name gezeigt:
Dort sorgt ein exit vor dem Definitions-abschließenden Semicolon für einen freien
Platz im Wort. In diesen freien Platz kann später mit Hilfe des Wortes 'name ein
weiteres Wort "eingehängt" werden, das dann beim Aufruf von name mit ausge-
führt wird. Auf diese Weise wird das Gesamtverhalten nicht vollständig geändert,
sondern um eine weitere Funktion ergänzt.
Oft möchte man auch das Verhalten einer Anwendung an bestimmten Punkten
umschaltbar machen. Dies wird in volksFORTH erreicht durch:
Defer <name>
So kann man schon auf ein Wort Bezug nehmen, bevor es definiert zu wurde. Dazu
reicht es, volks4TH den Namen bekannt zu geben. Später können immer wieder
andere Routinen an Stelle dieses Wortes ausgeführt werden:
' <action> Is (name)
( bitte auf das Häkchen ' achten!)
Wird allerdings <name> ausgeführt, bevor es mit IS initialisiert wurde, so er-
scheint die Meldung "Crash" auf dem Bildschirm. Deshalb finden Sie oft diesen
Ausdruck:
Defer (name) ' noop Is (name)
So simpel ist die vektorielle Programmausführung in FORTH implementiert. Damit
kann man zwei Probleme elegant lösen:
1. Das Wort <name> läßt sich bereits kompilieren, ohne daß ihm eine
sinnvolle Aktion zugewiesen wurde. Damit ist die Kompilation von
Wörtern möglich, die erst später definiert werden (Vorwärts-Referen-
zen).
2, Die nachträglich Veränderung von bereits kompilierten Wörtern ist
damit möglich; vorausgesetzt, sie wurden als Defer-Wörter einge-
tragen. Wörter, die mit der Defer-Anweisung erzeugt wurden, lassen
sich also in ihrem Ablaufverhalten nachträglich ändern. Diese Wörter
behalten also ihren Namen bei, verändern aber ihr Verhalten.
Als Beispiel betrachten Sie bitte folgendes:
: Versuch#1 ." erster Versuch" cr;
: Versuch#2 ." zweiter Versuch" cr ;
Defer Beispiel
Versuch#1 Is Beispiel
Beispiel perform
- 124 - Manipulieren des Systemverhalten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Damit haben Sie jetzt BEISPIEL ausgeführt. Schauen Sie sich die Meldung an und
geben ein:
' Versuch#2 Is Beispiel
Führen Sie erneut Beispiel perforn aus - Sie bekommen nun die andere
Meldung! Auf diese Art und Weise können Sie dem Wort BEISPIEL beliebige
Funktionen zuweisen.
Die Kombination DEFER/IS behält also den Namen bei, ändert aber das Verhalten
eines Wortes. Damit ist die Kombination DEFER/IS inhaltlich das Gegenteil von
ALIAS , das den Namen ändert, aber die Funktion beibehält.
Mit ALIAS können Sie in volksFORTH einem Wort recht einfach einen neuen
Namen geben. Sollte Ihnen das V des Editors nicht gefallen, benennen Sie es um
in WHERE ! Dieses Umbenennen läßt sich auf zwei Arten durchführen, entweder
im traditionellen FORTH-Stil mit
: where v;
oder dem volksFORTH gemäß mit
' vw Alias where
10.3 Neudefinition von Befehlen
Sollen dagegen Worte des Compilers unter anderem Namen benutzt werden, so ist
das in FORTH ebenfalls kein Thema:
: NeuName AltNane ;
' THEN Alias ENDIF immediate restrict
: ENDIF [compile]) THEN ; immediate restrict
Eine Anwendung dieser Synonym-Deklarationen besteht darin, einen sogenannten
Standard-Prolog zu verwirklichen: Damit Programme auch Wörter benutzen können,
die der jeweilige Compiler nicht zur Verfügung stellt, schreibt man für den je-
weiligen Compiler einen kleinen Vorspann (prelude) in FORTH83-Code zum Pro-
gramm, der die jeweilig benötigten Definitonen enthält.
Oft stellt ein anderer Compiler eine identische Funktion unter einem anderen
Namen zur Verfügung. So verwenden viele FORTH-Systeme GOTOXY statt des AT
zur Cursorpositionierung. Nun ändert man im Prolog den Namen über die Alias-
Funktion und erspart sich das quälende Suchen/Ersetzen im Editor.
Manipulieren des Systemverhalten = 1238 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
18.4 DEFERed Wörter im volksFORTH83
Darüberhinaus besitzt das volksFORTH83 eine Reihe von Strukturen, die dazu die-
nen, das Verhalten des Systems zu ändern. Im System sind bereits folgende
DEFERred Worte vorhanden:
R/W 'cOLD 'RESTART 'ABORT 'QuIT NOTFOUND
STATUS DISKERR MAKEVIEW und CUSTOM-REMOVE .
Um sie zu ändern, benutzt man den Ausdruck:
' <«<action) Is (name)
Hierbei ist, wie oben besprochen, <name> ein durch DEFER erzeugtes Wort und
<action> der Name des Wortes, das in Zukunft bei Aufruf von <name> ausgeführt
wird.
Anwendungsmöglichkeiten dieser deferred Worte:
Durch Ändern von R/W kann man andere Floppies oder eine RAM-Disk betreiben.
Es ist auch leicht möglich, Teile einer Disk gegen überschreiben zu schützen.
Durch Ändern von NOTFOUND kann man z.B. Worte, die nicht im Dictionary ge-
funden wurden, anschließend in einer Disk-Directory suchen lassen oder auto-
matisch als Vorwärtsreferenz vermerken.
Ändert man 'COLD , so kann man die Einschaltmeldung des volksFORTH83
unterdrücken und stattdessen ein Anwenderprogramm starten, ohne daß Eingaben
von der Tastatur aus erforderlich sind (siehe z.B. "Erstellen einer Applikation").
Ähnliches gilt für 'RESTART.
'ABORT ist z.B. dafür gedacht, eigene Stacks, z.B. für Fließkommazahlen, im
Fehlerfall zu löschen. Die Verwendung dieses Wortes erfordert aber schon eine ge-
wisse Systemkenntnis.
Das gilt auch für das Wort 'QUIT.. 'QUIT wird dazu benutzt, eigene Quitloops in
den Compiler einzubetten. Wer sich für diese Materie interessiert, sollte sich den
Quelltext des Tracer anschauen. Dort wird vorgeführt, wie man das macht.
STATUS schließlich wird vor Laden eines Blocks ausgeführt. Man kann sich damit
anzeigen lassen, welchen Block einer längeren Sequenz das System gerade lädt und
z.B. wieviel freier Speicher noch zur Verfügung steht.
CUSTOM-REMOVE kann vom fortgeschrittenen Programmierer dazu benutzt werden,
eigene Datenstrukturen, die miteinander durch Zeiger verkettet sind, zu vergessen.
Ein Beispiel dafür sind die File Control Blöcke des Fileinterfaces.
- 126 - Manipulieren des Systemverhalten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
18.5 Vektoren im volksFORTH83
Es gibt im System die Uservariable ERRORHANDLER . Dabei handelt es sich um
eine normale Variable, die als Inhalt die Kompilationsadresse eines Wortes hat. Der
Inhalt der Variablen wird auf folgende Weise ausgeführt:
errorhandler perform
Zuweisen und Auslesen dieser Variablen geschieht mit @ und ! . Der Inhalt
von ERRORHANDLER wird ausgeführt, wenn das System ABORT" oder ERROR"
ausführt und das von diesen Worten verbrauchte Flag wahr ist. Die Adresse des
Textes mit der Fehlermeldung befindet sich auf dem Stack.
Siehe z.B. (ERROR .
Das volksFORTH83 benutzt die indirekten Vektoren INPUT und OUTPUT . Die
Funktionsweise der sich daraus ergebenden Strukturen soll am Beispiel von INPUT
verdeutlicht werden:
INPUT ist eine Uservariable, die auf einen Vektor zeigt, in dem wiederum vier
Kompilationsadressen abgelegt sind. Jedes der vier Inputworte KEY KEY?
DECODE und EXPECT führt eine der Kompilationsadressen aus. Kompiliert wird
solch ein Vektor in der folgenden Form:
Input: vector <namel) <(name2) (name3) <(name4) ;
Wird VECTOR ausgeführt, so schreibt er seine Parameterfeld-Adresse in die
USERVariable INPUT. Von nun an führen die Inputworte die ihnen so zugewiese-
nen Worte aus. KEY führt also <NAME1> aus usw...
Das Beispiel KEY? soll dieses Prinzip verdeutlichen:
: key? (-- ce) input @ 2+ perform ;
Tatsächlich wurde KEY? im System ebenso wie die anderen Inputworte durch das
nicht mehr sichtbare definierende Wort IN: erzeugt. Ein Beispiel für einen
Inputvektor, der die Eingabe von der Tastatur holt:
Input: keyboard
(key (key? (decode (expect ;
keyboard
ergibt:
input pointer
ln
KEYBOARD code (key (key? (decode (expect
Manipulieren des Systemverhalten 12a,
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Analog verhält es sich mit OUTPUT und den Outputworten EMIT CR TYPE DEL
PAGE AT und AT? . Outputvektoren werden mit OUTPUT: genauso wie die
Inputvektoren erzeugt.
Bitte beachten Sie, daß immer alle Worte in der richtigen Reihenfolge aufgeführt
werden müssen! Soll nur ein Wort geändert werden, so müssen sie trotzdem die
anderen mit hinschreiben.
18.6 Glossar
Defer (--)
ein definierendes Wort, das in der Form:
Defer (name)
benutzt wird. Erzeugt den Kopf für ein neues Wort <name> im Dictionary,
hält 2 Byte in dessen Parameterfeld frei und speichert dort zunächst die
Kompilationsadresse einer Fehlerroutine.
Wird <name> nun ausgeführt, so wird eine Fehlerbehandlung eingeleitet.
Man kann dem Wort <name)> jedoch zu jeder Zeit eine andere Funktion
zuweisen mit der Sequenz:
' «action)> Is (name)
Nach dieser Zuweisung verhält sich <name> wie <action>.
Mit diesem Mechanismus kann man zwei Probleme elegant lösen:
Einerseits läßt sich <name> bereits kompilieren, bevor ihm eine sinnvolle
Aktion zugewiesen wurde Damit ist die Kompilation erst später
definierter Worte (Vorwärts-Referenzen) indirekt möglich.
Andererseits ist die Veränderung des Verhaltens von <name> für spezielle
Zwecke auch nachträglich möglich, ohne neu kompilieren zu müssen.
Deferred Worte im System sind: R/W 'COLD 'RESTART 'ABORT 'QUIT
NOTFOUND .STATUS und DISKERR . Diese Worte sind DEFERred, damit
ihr Verhalten für die Anwendung geändert werden kann.
Is (cfa--)
ist ein Wort, mit dem das Verhalten eines deferred Wortes verändert wer-
den kann. IS wird in der Form:
' <action)> Is (name)
benutzt. Wenn <name> kein deferred Wort ist, wird eine Fehlerbehandlung
eingeleitet, sonst verhält sich <name> anschließend wie <action?>. Das
Wort IS des volksFORTH83 kann innerhalb von Definitionen benutzt
werden.
Siehe DEFER .
128 - Manipulieren des Systemverhalten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
perform
noop
Alias
Input:
( addr --)
erwartet eine Adresse, unter der sich ein Zeiger auf die Kompilations-
adresse eines Wortes befindet. Dieses Wort wird dann ausgeführt.
perform entspricht der Anweisungsfolge ®@ execute .
=)
macht gar nichts.
(cfa --)
ist ein definierendes Wort, das typisch in der Form:
' «oläname) Alias (newname)>
benutzt wird. ALIAS erzeugt einen Kopf für <newname> im Dictionary.
Wird <newname> aufgerufen, so verhält es sich wie <oldname)>. Insbeson-
dere wird beim Kompilieren nicht <newname>, sondern <oldname> im Dic-
tionary eingetragen.
Im Unterschied zu : <(newname) <oldname> ; ist es mit ALIAS möglich,
Worte, die den Returnstack beeinflussen (z.B. >r oder r> ), mit an-
derem Namen zu definieren. Außer dem neuen Kopf für <newname> wird
kein zusaetzlicher Speicherplatz verbraucht. Gegenwärtig wird bei Aus-
führung von >name aus einer CFA in der Regel der letzte mit ALIAS
erzeugte Name gefunden.
(42) "input-colon"
ist ein definierendes Wort, benutzt in der Form:
Input: <name)> newKEY newKEY? newDECODE newEXPECT ;
INPUT: erzeugt einen Kopf für <name> im Dictionary und kompiliert einen
Satz von Zeigern auf Worte, die für die Eingabe von Zeichen zuständig
sind. Wird <name> ausgeführt, so wird ein Zeiger auf das Parameterfeld
von <name> in die Uservariable INPUT geschrieben. Alle Eingaben
werden jetzt über die neuen Eingabeworte abgewickelt.
Die Reihenfolge der Worte nach INPUT: <name> bis zum Semicolon muß
eingehalten werden:
..kKey ..key? ..decode ..expect
Im System ist das mit INPUT: definierte Wort keyboard enthalten,
nach dessen Ausführung alle Eingaben von der Tastatur geholt werden.
Siehe DECODE und EXPECT.
Manipulieren des Systemverhalten = 129 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Output:
'abort
'cold
'quit
'restart
(quit
==) "output-colon"
ist ein definierendes Wort, benutzt in der Form:
Output: (name)
newEMIT newCR newTYPE newDEL newPAGE newAT newAT? ;
OUTPUT: erzeugt einen Kopf für <name> im Dictionary und kompiliert
einen Satz von Zeigern auf Worte, die für die Ausgabe von Zeichen zu-
ständig sind. Wird <name> ausgeführt, so wird ein Zeiger auf das Para-
meterfeld von <name> in die Uservariable OUTPUT geschrieben. Alle
Ausgaben werden jetzt über die neuen Ausgabeworte abgewickelt.
Die Reihenfolge der Worte nach OUTPUT: <name) muß eingehalten werden:
..emit ..cr ..type ..del ..page ..at ..at?
Im System ist das mit OUTPUT: definierte Wort DISPLAY enthalten,
nach dessen Ausführung alle Ausgaben auf den Bildschirm geleitet
werden.
Vergleiche auch das Wort PRINT aus dem Printer-Interface.
) "tick-abort"
ist ein deferred Wort, das mit NOOP vorbesetzt ist. Es wird in ABORT
ausgeführt, bevor QUIT aufgerufen wird. Es kann benutzt werden, um
"automatisch" selbstdefinierte Stacks zu löschen.
Ge-) "tick-cold"
ist ein deferred Wort, das mit NOOP vorbesetzt ist. Es wird in COLD
aufgerufen, bevor die Einschaltmeldung ausgegeben wird. Es wird benutzt,
um Geräte zu initialisieren oder Anwenderprogramme automatisch zu star-
ten.
a=)) "tick-quit"
ist ein deferred Wort, das normalerweise mit (QUIT besetzt ist. Es wird
in QUIT aufgerufen, nachdem der Returnstack enleert und der interpre-
tierende Zustand eingeschaltet wurde. Es wird benutzt, um spezielle
Kommandointerpreter (wie z.B. im Tracer) aufzubauen.
(==) "tick-restart"
Dies ist ein deferred Wort, das mit NOOP vorbesetzt ist. Es wird in
RESTART aufgerufen, nachdem 'QUIT mit (QUIT besetzt wurde. Es
wird benutzt, um Geräte nach einem Warmstart zu re-initialisieren.
(==) "paren-quit"
Dieses Wort ist normalerweise der Inhalt von 'QUIT .. Es wird von QUIT
benutzt. Es akzeptiert eine Zeile von der aktuellen Eingabeeinheit, führt
sie aus und druckt "ok" bzw. "compiling".
- 130 -
Manipulieren des Systemverhalten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
status (--) "dot-status"
Dieses Wort ist ein deferred Wort, das vor dem Einlesen einer Zeile bzw.
dem Laden eines Blocks ausgeführt wird. Es ist mit NOOP vorbesetzt
und kann dazu benutzt werden, Informationen über den Systemzustand
oder den Quelltext auszugeben.
makeview ( -- 16b)
ist ein deferred Wort, dem mit IS ein Wort zugewiesen wurde. Dieses
Wort erzeugt aus dem gerade kompilierten Block eine 16b Zahl, die von
Create in das Viewfeld eingetragen wird. Das deferred Wort wird benötigt,
um das Fileinterface löschen zu können,
Manipulieren des Systemverhalten 1831 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
1l. Vokabular-Struktur
Eine Liste von Worten ist ein Vokabular. Ein FORTH-System besteht im allgemeinen
aus mehreren Vokabularen, die nebeneinander existieren. Neue Vokabulare werden
durch das definierende Wort VOCABULARY erzeugt und haben ihrerseits einen
Namen, der in einer Liste enthalten ist. Gewöhnlich kann von mehreren Worten mit
gleichem Namen nur das zuletzt definierte erreicht werden. Befinden sich jedoch die
einzelnen Worte in verschiedenen Vokabularen, so bleiben sie einzeln erreichbar.
11.1 Die Suchreihenfolge
Die Suchreihenfolge gibt an, in welcher Reihenfolge die verschiedenen Vokabulare
nach einem Wort durchsucht werden.
Sie besteht aus zwei Teilen, dem auswechselbaren und dem festen Teil. Der aus-
wechselbare Teil enthält genau ein Vokabular. Dies wird zuerst durchsucht. Wird
ein Vokabular durch Eingeben seines Namens ausgeführt, so trägt es sich in den
auswechselbaren Teil ein. Dabei wird der alte Inhalt überschrieben. Einige andere
Worte ändern ebenfalls den auswechselbaren Teil. Soll ein Vokabular immer durch-
sucht werden, so muß es in den festen Teil übertragen werden. Dieser enthält null
bis sechs Vokabulare und wird nur vom Benutzer bzw. seinen Worten verändert. Zur
Manipulation stehen u.a. die Worte ONLY ALSO TOSS zur Verfügung. Das Voka-
bular, in das neue Worte einzutragen sind, wird durch das Wort DEFINITIONS an-
gegeben. Die Suchreihenfolge kann man sich mit ORDER ansehen.
Ein Beispiele, das die Veränderung der Suchreihenfolge mit den eingegebenen Be-
fehlen zeigt, wobei das Grundvokabular ROOT zwar in der Suchreihenfolge ent-
halten ist, aber nicht von ORDER angezeigt wird, um die Statuszeile nicht mit
obligatorischen Informationen zu blockieren:
Eingabe: ORDER ergibt dann:
Only£forth FORTH FORTH ROOT FORTH
Editor also EDITOR EDITOR FORTH ROOT FORTH
Assembler ASSEMBLER EDITOR FORTH ROOT FORTH
definitions Forth FORTH EDITOR FORTH ROOT ASSEMBLER
: test ; ASSEMBLER EDITOR FORTH ROOT ASSEMBLER
Hierbei ist vor allem auf colon (:) zu achten, das ebenfalls die Suchlaufpriorität
ändert, indem es das Kompilationsvokabular current in den auswechselbaren Teil
von context überträgt.
Der Inhalt eines Vokabulars besteht aus einer Liste von Worten, die durch ihre
Linkfelder miteinander verbunden sind. Es gibt also genauso viele Listen wie
Vokabulare. Alle Vokabulare sind selbst noch einmal über eine Liste verbunden,
= 182,0= Vokabular-Struktur
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
deren Anfang in VOC-LINK steht. Diese Verkettung ist nötig, um ein komfortables
FORGET zu ermöglichen. Man bekommt beispielsweise folgendes Bild:
Voc-Link Assembler Only Forth }- Null
| | |
Wort | Wort | Wort
| | |
Wort | Wort Wort
| | |
Null Null Null
11.2 Glossar
Vocabulary (=) 83
ein definierendes Wort, das in der Form:
Vocabulary (name)
benutzt wird.
VOCABULARY erzeugt einen Kopf für <name>, das den Anfang einer
neuen Liste von Worten bildet. Wird <name> ausgeführt, so werden bei
der Suche im Dictionary zuerst die Worte in der Liste von <name>
berücksichtigt. Wird das VOCABULARY <name> durch die Sequenz:
<name) definitions
zum Kompilations-Vokabular, so werden neue Wort-Definitionen in die
Liste von <name)> gehängt. Vergleiche auch CONTEXT CURRENT ALSO
TOSS ONLY FORTH ONLYFORTH .
context ( -- addr )
addr ist die Adresse des auswechselbaren Teils der Suchreihenfolge. Sie
enthält einen Zeiger auf das erste zu durchsuchende Vokabular.
eurrent ( -- addr )
addr ist die Adresse eines Zeigers, der auf das Kompilationsvokabular
zeigt, in das neue Worte eingefügt werden.
definitions (--)83
ersetzt das gegenwärtige Kompilationsvokabular durch das Vokabular im
auswechselbaren Teil der Suchreihenfolge, d.h. neue Worte werden in
dieses Vokabular eingefügt.
Vokabular-Struktur » I8Bim
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Only (=
Das Nennen dieses Vokabular löscht die Suchreihenfolge vollständig und
ersetzt sie durch das Vokabular ROOT im festen und auswechselbaren
Teil der Suchreihenfolge. ROOT enthält nur wenige Worte, die für die
Erzeugung einer Suchreihenfolge benötigt werden.
also ( = )
Ein Wort, um die Suchreihenfolge zu spezifizieren. Das Vokabular im aus-
wechselbarem Teil der Suchreihenfolge wird zum ersten Vokabular im
festen Teil gemacht, wobei die anderen Vokabulare des festen Teils nach
hinten rücken. Ein Fehler liegt vor, falls der feste Teil sechs Vokabulare
enthält.
toss (--)
entfernt das erste Vokabular des festen Teils der Suchreihenfolge. Inso-
fern ist es das Gegenstück zu ALSO .
seal (me)
löscht das Vokabular ROOT , so daß es nicht mehr durchsucht wird. Da-
durch ist es möglich, nur die Vokabulare des Anwenderprogramms durch-
suchen zu lassen.
Onlyforth Do)
entspricht der häufig benötigten Sequenz:
ONLY FORTH ALSO DEFINITIONS
Forth =) 83
Das ursprüngliche Vokabular.
Assembler (--)
Ein Vokabular, das Prozessor-spezifische Worte enthält, die für Code-
Definitionen benötigt werden.
words (en)
gibt die Namen der Worte des Vokabulars, das im auswechselbaren Teil
der Suchreihenfolge steht, aus, beginnend mit dem zuletzt erzeugtem
Namen.
forth-83 ==) 83
Laut FORTH83-Standard soll dieses Wort sicherstellen, daß ein Standard-
system benutzt wird. Im volksFORTH funktionslos.
- 134 - Vokabular-Struktur
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
vp ( -- addr ) "v-p"
Eine Variable, die das Ende der Suchreihenfolge markiert. Sie enthält
ausserdem Informationen über die Länge der Suchreihenfolge.
voc-link ( -- addr )
Eine Uservariable, die den Anfang einer Liste mit allen Vokabularen
enthält. Diese Liste wird u.a. für FORGET benötigt.
Vokabular-Struktur -196--
FORTH-Gesellschaft e.V.
PC-voliksFORTH83 rev. 3.81
12. Dictionary -Struktur
Das FORTH-System besteht aus einem Dictionary von Worten. Die Struktur der
Worte und des Dictionaries soll im folgenden erläutert werden.
12.1 Aufbau
Die FORTH-Worte sind in Listen angeordnet (s.a. Struktur der Vokabulare). Die vom
Benutzer definierten Worte werden ebenfalls in diese Listen eingetragen.
Jedes Wort besteht aus sechs Teilen. Es sind dies:
1. block
2. link
3. count
4. name
5. code
6. parameter
Der Nummer des Blocks, in dem das Wort definiert
wurde (siehe auch VIEW).
Die Adresse (Zeiger) namens Ifa , die auf das "Link-
feld" des nächsten Wortes zeigt.
Die Länge des Namens dieses Wortes und drei Mar-
kierungsbits. Die Adresse nfa zeigt auf dieses Byte,
ebenso last.
Der Name selbst.
Eine Adresse (Zeiger), die auf den Maschinencode
zeigt, der bei Aufruf dieses Wortes ausgeführt wird.
Die Adresse dieses Feldes heißt Kompilationsadresse
cfa .
Das Parameterfeld; die Adresse dieses Feldes heißt pfa .
Ein Wort sieht dann so aus:
Wort
block
link
count | name code parameter ...
Im folgenden sollen diese sechs Felder einzeln detalliert betrachtet werden.
Block
Das Blockfeld enthält in codierter Form die Nummer
des Blocks und den Namen des Files, in dem das Wort
- 136 -
Dicetionary-Struktur
FORTH-Gesellschaft e.V.
Link
— Countfeld
PC-volksFORTH83 rev. 3.81
definiert wurde. Wurde es von der Tastatur aus ein-
gegeben, so enthält das Feld Null.
über das Linkfeld sind die Worte eines Vokabulars zu
einer Liste verkettet. Jedes Link-Feld enthält die
Adresse des vorherigen Link-Feldes. Jedes Wort zeigt
also auf seinen Vorgänger. Das unterste Wort der
Liste enthält im Link-Feld eine Null. Die Null zeigt
das Ende der Liste an.
Das count field enthält die Länge des Namens (1..31
Zeichen) und drei Markierungsbits :
restrict immediate indirect Länge
Bit:
6 5 4..0
Ist das immediate-Bit gesetzt, so wird das entspre-
chende Wort im kompilierenden Zustand unmittelbar
ausgeführt, und nicht ins Dictionary kompiliert (siehe
auch IMMEDIATE ).
Ist das restrict-Bit gesetzt, so kann das Wort nicht
durch Eingabe von der Tastatur ausgeführt, sondern
nur in anderen Worten kompiliert werden. Gibt man es
dennoch im interpretierenden Zustand ein, so er-
scheint die Fehlermeldung "compile only" (siehe
auch RESTRICT ).
Ist das indirect-Bit gesetzt, so folgt auf den Namen
kein Codefeld, sondern ein Zeiger darauf. Damit kann
der Name vom Rumpf ( Code- und Parameterfeld )
getrennt werden. Die Trennung geschieht z.B. bei
Verwendung der Worte ı oder ALIAS.
Beispiel: ' 1+ Alias addl
ergibt folgende Struktur im Speicher (Dictionary) :
Dicetionary-Struktur
= 1978 —
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Name
Code
Parameter
block | link | 524 addi pointer
andere Worte
|
| Block | link' | $82 | 1+ | code | parameter
Der Name besteht normalerweise aus ASCII-Zeichen.
Bei der Eingabe werden Klein- in Großbuchstaben um-
gewandelt. Daher druckt WORDS auch nur großge-
schriebene Namen. \
Da Namen sowohl groß als auch klein geschrieben
eingegeben werden können, haben wir eine Konvention
erarbeitet, die die Schreibweise von Namen festlegt:
Bei Kontrollstrukturen wie DO LOOP etc. werden
alle Buchstaben groß geschrieben.
Bei Namen von Vokabularen, immediate Worten und
definierenden Worten, die CREATE ausführen, wird
nur der erste Buchstabe groß geschrieben.
Beispiele sind: Is FORTH Constant
Alle anderen Worte werden klein geschrieben.
Beispiele sind: dup cold base
Bestimmte Worte, die von immediate Worten kompiliert
werden, beginnen mit der öffnenden Klammer "("
gefolgt vom Namen des immediate Wortes.
Ein Beispiel: DO kompiliert (do.
Diese Schreibweise ist nicht zwingend; Sie sollten sich
aber daran halten, um die Lesbarkeit Ihrer Quelltexte
zu erhöhen.
Jedes Wort weist auf ein Stück Maschinencode. Die
Adresse dieses Code-Stücks ist im Codefeld enthalten.
Gleiche Worttypen weisen auf den gleichen Code. Es
gibt verschiedene Worttypen, z.B. :-Definitionen,
Variablen, Konstanten, Vokabulare usw. Sie haben je-
weils ihren eigenen charakte- ristischen Code ge-
meinsam. Die Adresse des Code-Feldes heißt Kompi-
lationsadresse.
Das Parameterfeld enthält Daten, die vom Worttypen
abhängen. Beispiele :
a) Typ "Constant"
Hier enthält das Parameterfeld des Wortes den Wert
- 198 —
Dictionary-Struktur
FORTH-Gesellschaft e.V.
PC-volksFORTH83 rev. 3.81
der Konstanten. Der dem Wort zugeordnete Code liest
den Inhalt des Parameterfeldes aus und legt ihn auf
den Stack.
b) Typ "Variable"
Das Parameterfeid enthält den Wert der Variablen, der
zugeordnete Code liest jedoch nicht das Parameterfeld
aus, sondern legt dessen Adresse auf den Stack. Der
Benutzer kann dann mit dem Wort @ den Wert holen
und mit dem Wort ! überschreiben.
c) Typ ":-definition"
Das ist ein mit : und ; gebildetes Wort. In diesem -
Fall enthält das Parameterfeld hintereinander die
Kompilationsadressen der Worte, die diese Definition
bilden. Der zugeordnete Code sorgt dann dafür, daß
diese Worte der Reihe nach ausgeführt werden.
Beispiel :
: test dup ;
ergibt:
| TEST | code | pointer pointer |
rn
DUP code parameter
UNNEST code parameter
Das Wort : hat den Namen TEST erzeugt. UNNEST
wurde durch das Wort ; erzeugt
d) Typ "Code"
Worte vom Typ "Code" werden mit dem Assembler er-
zeugt. Hier zeigt das Codefeld in der Regel auf das
Parameterfeld. Dorthin wurde der Maschinencode
assembliert.
Codeworte im volksFORTH können leicht "umgepatcht"
werden, da lediglich die Adresse im Codefeld auf eine
Dicetionary-Struktur
= 1396
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
here
dp
udp
allot
uallot
©
neue (andere) Maschinencodesequenz gesetzt werden
muß.
12.2 Glossar
( -- addr ) 83
addr ist die Adresse des nächsten freien Dictionaryplatzes.
( -- addr ) "d-p"
Eine Uservariable, die die Adresse des nächsten freien Dicetionary-platzes
enthält.
( -- addr ) "u-d-p"
Eine Uservariable, in dem das Ende der bisher allokierten Userarea ver-
merkt ist.
(w--) 83
Allokiere w Bytes im Dictionary. Die Adresse des nächsten freien Dic-
tionaryplatzes wird entsprechend verstellt.
(nl--n2)
Allokiere bzw. deallokiere ni Bytes in der Userarea. n2 gibt den Anfang
des allokierten Bereiches relativ zum Beginn der Userarea an. Eine
Fehlerbehandlung wird eingeleitet, wenn die Userarea voll ist.
(16b --) "c-comma"
ist ein ALLOT für ein Byte und speichert die unteren 8 Bit von 16b in
HERE 1- .
( 16b --) 83 "comma"
ist 2 ALLOT für 16b und speichere 16b ab HERE 2
( -- addr ) 83 "tick"
Wird in der Form ' <«name)> benutzt.
addr ist die Kompilationsadresse von <name>. Wird <name> nicht in der
Suchreihenfolge gefunden, so wird eine Fehlerbehandlung eingeleitet.
- 140 -
Dietionary-Struktur
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
name
'name
name
align
forget
(==)
Eine Besonderheit von name ist, daß dieses Wort über zwei EXITs
verfügt. Zum einen das explizite exit und zum anderen das Semicolon,
das ja auch ein exit ist. Die so einkompilierte Adresse kann dazu be-
nutzt werden, beim Aufruf von name ein weiteres Wort ausführen zu
lassen. Dieser Mechanismus kann als eine Variation von Deferred Worten
aufgefaßt werden, weil auch hier das Wortverhalten geändert wird.
Siehe 'NAME und auch DEFER .
( -- addr )
liefert die Bezugsadresse für das Einhängen eines Wortes, wie es bei
name dargestellt wurde. Diese Möglichkeit, das Verhalten von Worten zu
erweitern, wird bsp. im Editor eingesetzt. Dort wird im Wort showload
ein Wort show über 'name in name eingehängt und dann in
showoff durch das Eintragen von exit wieder überschrieben, d.h. aus-
gehängt.
( addr -- ) "dot-name"
addr ist die Adresse des Countfeldes eines Namens. Dieser Name wird
ausgedruckt. Befindet er sich im Heap, so wird das Zeichen ı vorange-
stellt. Ist addr Null, so wird "???" ausgegeben.
(=)
macht nichts, weil der 8986/88 Prozessor auch von ungeraden Adressen
Befehle holen kann, im Gegensatz zum 68®ß6der. Diese Worte sind vor-
handen, damit Sourcecode zwischen den Systemen transportabel ist.
Querverweis: HALIGN .
=) 83
Wird in der Form FORGET (name) benutzt. Falls <name> in der Such-
reihenfolge gefunden wird, so werden <name> und alle danach definierten
Worte aus dem Dictionary entfernt. Wird <name> nicht gefunden, so wird
eine Fehlerbehandlung eingeleitet. Liegt <name> in dem durch SAVE ge-
schützten Bereich, so wird ebenfalls eine Fehlerbehandlung eingeleitet. Es
wurden Vorkehrungen getroffen, die es ermöglichen, aktive Tasks und
Vokabulare, die in der Suchreihenfolge auftreten, zu vergessen.
Dietionary-Struktur = 1996 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
remove
(forget
( die sym thread -- dic sym )
Dies ist ein Wort, das zusammen mit CUSTOM-REMOVE verwendet wird.
dic ist die untere Grenze des Dictionarybereiches, der vergessen werden
soll und sym die obere. Typisch zeigt sym in den Heap. thread ist der
Anfang einer Kette von Zeigern, die durch einen Zeiger mit dem Wert Null
abgeschlossen wird. Wird REMOVE dann ausgeführt, so werden alle Zei-
ger (durch Umhängen der übrigen Zeiger) aus der Liste entfernt, die in
dem zu vergessenden Dictionarybereich liegen. Dadurch ist es möglich,
FORGET und ähnliche Worte auf Datenstrukturen anzuwenden.
( addr -- ) "paren-forget"
Entfernt alle Worte, deren Kompilationsadresse oberhalb von addr liegt,
aus dem Dictionary und setzt HERE auf addr. Ein Fehler liegt vor, falls
addr im Heap liegt.
custom-remove ( die symb -- dic symb )
save
empty
last
Ein deferred Wort, daß von FORGET, CLEAR usw. aufgerufen wird. dic
ist die untere Grenze des Dictonaryteils, der vergessen wird und symb
die obere. Gewöhnlich zeigt symb in den Heap. :
Dieses Wort kann dazu benutzt werden, eigene Datenstrukturen, die Zeiger
enthalten, bei FORGET korrekt abzuabrbeiten. Es wird vom Fileinterface
verwendet, daher darf es nicht einfach überschrieben werden. Man kann
es z.B. in folgender Form benutzen :
: (name) [ ' custom-remove body @ , ]
“liststart) @ remove ;
(name) Is custom-remove
Auf diese Weise stellt man sicher, daß das Wort, das vorher in CUSTOM-
REMOVE eingetragen war, weiterhin ausgeführt wird.
Siehe auch REMOVE .
WE)
Kopiert den Wert aller Uservariablen in den Speicherbereich ab ORIGIN
und sichert alle Vokabularlisten. Wird später COLD ausgeführt, so be-
findet sich das System im gleichen Speicherzustand wie bei Ausführung
von SAVE.
==)
Löscht alle Worte, die nach der letzten Ausführung von SAVE oder dem
letzten Kaltstart definiert wurden. DP (und damit HERE )wird auf sei-
nen Kaltstartwert gesetzt und der Heap gelöscht.
( -- addr )
Variable, die auf das Countfeld des zuletzt definierten Wortes zeigt.
Siehe auch RECURSIVE und MYSELF .
- 142 -
Dietionary-Struktur
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
hide
reveal
origin
name)
>body
>name
==)
Entfernt das zuletzt definierte Wort aus der Liste des Vokabulars, in das
es eingetragen wurde. Dadurch kann es nicht gefunden werden. Es ist
aber noch im Speicher vorhanden. (s.a. REVEAL LAST )
( ==)
Trägt das zuletzt definierte Wort in die Liste des Vokabulars ein, in dem
es definiert wurde.
( -- addr )
addr ist die Adresse, ab der die Kaltstartwerte der Uservariablen abge-
speichert sind.
( addri -- addr2 ) "name-from"
addr2 ist die Kompilationsadresse, die mit dem Countfeld im addrı
korrespondiert.
( addri -- addr2 ) "to-body"
addr2 ist die Parameterfeldadresse, die mit der Kompilationsadresse addrl
korrespondiert.
( addrli -- addr2 ) "to-name"
addr2 ist die Adresse eines Countfeldes, das mit der Kompilationsadresse
addri korrespondiert. Es ist möglich, daß es mehrere addr2 für ein addri
gibt. In diesem Fall ist nicht definiert, welche ausgewählt wird.
In der Literatur finden Sie für die Umrechnung von Feld-Adressen auch oftmals
folgende Worte:
»link »)name 2- ;
link> 2+ name) ;
n>link a
l>name 2+ 5;
Dicetionary-Struktur - 133 +
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
13. Der HEAP
Eines der ungewöhnlichen und fortschrittlichen Konzepte des volksFORTH83 besteht
in der Möglichkeit, Namen von Worten zu entfernen, ohne den Rumpf zu vernichten
(headerless words).
Das ist insbesondere während der Kompilation nützlich, denn Namen von Worten,
deren Benutzung von der Tastatur aus nicht sinnvoll wäre, tauchen am Ende der
Kompilation auch nicht mehr im Dictionary auf. Man kann dem Quelltext sofort an-
sehen, ob ein Wort für den Gebrauch außerhalb des Programmes bestimmt ist oder
nicht.
Die Namen, die entfernt wurden, verbrauchen natürlich keinen Speicherplatz mehr.
Damit wird die Verwendung von mehr und längeren Namen und dadurch auch die
Lesbarkeit gefördert.
Namen, die später eliminiert werden sollen, werden durch das Wort ı gekenn-
zeichnet. Das Wort ; muß unmittelbar vor dem Wort stehen, däs den zu elimi-
nierenden Namen erzeugt. Der so erzeugte Name wird in einem besonderen Spei-
cherbereich, dem Heap, abgelegt. Der Heap kann später mit dem Wort CLEAR ge-
löscht werden. Dann sind natürlich auch alle Namen, die sich im Heap befanden,
verschwunden. Das folgende Beispiel soll eine Art Taschenrechner darstellen:
ı Variable sum 1 sum !
Es werden weitere Worte definiert und dann CLEAR ausgeführt:
: clearsum (--) ®sun!;
: add (n--) sun +! ;
: show (-—-) suın®@.;
clear
Diese Definitionen liefern die Worte CLEARSUM ADD und SHOW , während der
Name der Variablen SUM durch CLEAR entfernt wurde. Das Codefeld und der
Wert 0001 existieren jedoch noch. Man kann den Heap auch dazu "mißbrauchen",
Code, der nur zeitweilig benötigt wird, nachher wieder zu entfernen. Der Assembler
wird auf diese Art geladen, so daß er nach Fertigstellen der Applikation mit
CLEAR wieder entfernt werden kann und keinen Platz im Speicher mehr benötigt.
Glossar
I (=) "headerless"
setzt bei Ausführung ?HEAD so, daß der nächste erzeugte Name nicht
im normalen Dictionaryspeicher angelegt wird, sondern auf dem Heap.
- 144 - Der HEAP
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
clear ,
löscht alle Namen und Worte im Heap, so daß vorher mit |! definierte
Worte nicht mehr benutzt werden können. Auf diese Weise kann der Gel-
tungsbereich von Prozeduren eingeschränkt werden.
heap ( -- addr )
Hier ist addr der Anfang des Heap. Er wird z.B. durch HALLOT geändert.
hallot GN)
allokiert bzw. deallokiert n Bytes auf dem Heap. Dabei wird der Stack
verschoben, ebenso wie der Beginn des Heap.
heap? ( addr -- flag ) "heap-question"
übergibt ein wahres Flag, wenn addr ein Byte im Heap adressiert, an-
sonsten FALSE.
?head ( -- addr ) "question-head"
ist eine Variable, die angibt, ob und wieviele der nächsten zu erzeugen-
den Namen im Heap angelegt werden sollen.
Siehe auch }.
halign (--) "h-align"
dient nur der Softwarekompatibilität zu den anderen volks4TH-Systemen,
da der 8886-Prozessor nicht align-ed werden braucht.
Querverweis: ALIGN.
Der HEAP - 145 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
14. Die Ausführung von FORTH-Worten
Der geringe Platzbedarf übersetzter FORTH-Worte rührt wesentlich von der Existenz
des Adressinterpreters her.
Wie im Kapitel über die Dictionary-Struktur beschrieben, besteht eine :-Definition
aus dem Codefeld und dem Parameterfeld. Im Parameterfeld steht eine Folge von
Adressen. Ein Wort wird kompiliert, indem seine Kompilationsadresse dem Para-
meterfeld der :-Definition angefügt wird. Eine Ausnahme bilden die Immediate-
Worte. Da sie während der Kompilation ausgeführt werden, können sie dem Para-
meterfeld der :-Definition alles mögliche hinzufügen. Daraus wird klar, daß die
meisten Worte innerhalb der :-Definition nur eine Adresse, also in einem 16-Bit-
System genau 2 Bytes an Platz verbrauchen. Wird die :-Definition nun aufgerufen,
so sollen alle Worte, deren Kompilationsadresse im Parameterfeld stehen, ausgeführt
werden. Das besorgt der Adressinterpreter.
14.1 Der Aufbau des Adressinterpreters
Beim volksFORTH83 benutzt der Adressinterpreter einige Register der CPU, die im
Kapitel über den Assembler aufgeführt werden. Es gibt aber mindestens die folgen-
den Register :
IP ist der Instruktionszeiger (Instructionpointer ). Er zeigt auf die
nächste auszuführende Instruktion. Das ist beim volks-FORTH83 die
Speicherzelle, die die Kompilationsadresse des nächsten
auszuführenden Wortes enthält.
W ist das Wortregister. Es zeigt auf die Kompilationsadresse des
Wortes, das gerade ausgeführt wird.
sP ist der (Daten-) Stackpointer. Er zeigt auf das oberste Element des
Stacks.
RP ist der Returnstackpointer. Er zeigt auf das oberste Element des
Returnstacks.
14.2 Die Funktion des Adressinterpreters
NEXT ist die Anfangsadresse der Routine, die die Instruktion ausführt, auf die IP
gerade zeigt. Die Routine NEXT ist ein Teil des Adressinterpreters. Zur Verdeut-
lichung der Arbeitsweise ist dieser Teil hier in High Level geschrieben:
Variable IP
Variable W
: Next
= 146 = Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
IPee vv!
2 Ip +!
W perforn ;
Tatsächlich ist NEXT jedoch eine Maschinencoderoutine, weil dadurch die Aus-
führungszeit von FORTH-Worten erheblich kürzer wird. NEXT ist somit ein Makro,
die diejenige Instruktion ausführt, auf die das Register IP zeigt.
Ein Wort wird ausgeführt, indem der Code, auf den die Kompilations-adresse zeigt,
als Maschinencode angesprungen wird. Der Code kann z.B. den alten Inhalt des IP
auf den Returnstack bringen, die Adresse des Parameterfeldes im IP speichern und
dann NEXT anspringen. Diese Routine gibt es wirklich, sie heißt "docol" und ihre
Adresse steht im Codefeld jeder :-Definition.
Das Gegenstück zu dieser Routine ist ein FORTH-Wort mit dem Namen EXIT.
Dabei handelt es sich um ein Wort, das das oberste Element des Returnstacks in
den IP bringt und anschließend NEXT anspringt. Damit ist dann die Ausführung
der Colon-Definition beendet.
Beipiel :
ı 2* dup + ;
Son ZAHL;
a.) Ein Aufruf von
Brenn
von der Tastatur aus führt zu folgenden Situationen :
FTerFrT® Fr]
IP Stack/Returnstack
b.) Nach der ersten Ausführung von NEXT bekommt man :
2. docol 2% . exit 5 system
addri Stack/Returnstack
system
| 2% docol dup + exit 5 addri
IP Stack/Returnstack
€) Nochmalige Ausführung von NEXT ergibt:
( DUP ist ein Wort vom Typ "Code")
- 147 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
d.)
e.)
5 system
docol dup + exit 5 addri
IP Stack/Returnstack
Nach der nächsten Ausführung von NEXT zeigt der IP auf EXIT
und nach dem darauf folgenden NEXT wird addri wieder in den
| 2% | docol | 2*
IP geladen:
[e®
a
IP Stack/Returnstack
Die Ausführung von . erfolgt analog zu den Schritten b,c und d.
Anschließend zeigt IP auf EXIT in 2..
Nach Ausführung von NEXT kehrt das System wieder in den Text-
interpreter zurück. Dessen Rückkehradresse wird durch system ange-
deutet. Damit ist die Ausführung von 2. beendet .
14.3 Verschiedene IMMEDIATE-Worte
In diesem Abschnitt werden Beispiele für immediate Worte angegeben, die mehr als
nur eine Adresse kompilieren.
a.) Zeichenketten (strings), die durch " abgeschlossen werden, liegen
als counted strings im Dictionary vor.
Beispiel: abort" Test"
liefert: I (ABORT" 1 04 ı Tieisiıti
bi. Einige Kontrollstrukturen kompilieren ?BRANCH oder DBRANCH „,
denen ein Offset mit 16 Bit Länge folgt.
Beispiel: 0< IF swap THEN
liefert: 1 0< 1 ?BRANCH | 4 } SWAP I
Beispiel: BEGIN ?dup WHILE @ REPEAT
liefert: 1 ?DUP I ?BRANCH | 8 ! @ } BRANCH } -10 |!
c.) Ebenso fügen DO und ?DO einen Offset hinter das von ihnen
kompilierte Wort (DO bzw. (?DO . Mit dem Dekompiler können Sie
sich eigene Beispiele anschauen.
4.) Zahlen werden in das Wort LIT , gefolgt von einem 16-Bit-Wert,
kompiliert.
- 148 - Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Beispiel: [Ü hex ] 8 1000
liefert: I CLIT ıi $08 } LIT } $1000 |}
14.4 Die Does>-Struktur
Die Struktur von Worten, die mit CREATE .. DOES> erzeugt wurden, soll anhand
eines Beispiels erläutert werden.
Das Beispielprogramm lautet:
: Constant ( <name) -- )
(nn)
Create , Does) @ ;
3 Constant drei
Der erzeugte Code sieht folgendermaßen aus:
L
CONSTANT docol | Create | : | (;code | jmp dodoes> | @ | exit|
Das Wort (;CODE wurde durch DOES> erzeugt. Es setzt das Codefeld des durch
CREATE erzeugten Wortes DREI und beendet dann die Ausführung von
CONSTANT . Das Codefeld von DREI zeigt anschließend auf jmp dodoes> . Wird
DREI später aufgerufen , so wird der zugeordnete Code ausgeführt. Das ist in
diesem Fall jmp dodoes) .
dodoes> legt nun die Adresse des Parameterfeldes von DREI auf den Stack und
führt die auf jmp dodoes) folgende Sequenz von Worten aus. ( Man beachte die
Ähnlichkeit zu :-Definitionen). Diese Sequenz besteht aus @ und EXIT.
Der Inhalt des Parameterfeldes von DREI wird damit auf den Stack gebracht. Der
Aufruf von DREI liefert also tatsächlich 9993.
Statt des jmp dodoes)> und der Sequenz von FORTH-Worten kann sich hinter
(;CODE auch ausschließlich Maschinencode befinden. Das ist der Fall, wenn wir das
Wort ;CODE statt DOES> benutzt hätten. Wird diese Maschinencodesequenz
später ausgeführt, so zeigt das W-Register des Adressinterpreters auf das Codefeld
des Wortes, dem dieser Code zugeordnet ist. Erhöht man also das W-Register um 2,
so zeigt es auf das Parameterfeld des gerade auszuführenden Wortes.
= 49 =
FORTH-Gesellschaft e.V, PC-volksFORTH83 rev. 3.81
state
>in
source
bIk
load
14.5 Glossar
( -- addr ) 83
Eine Variable, die den gegenwärtigen Zustand enthält. Der Wert Null zeigt
den interpretierenden Zustand an, ein von Null verschiedener Wert den
kompilierenden Zustand.
( -- addr ) 83 "to-in"
Eine Variable, die den Offset auf das gegenwärtige Zeichen im Quelltext
enthält.
Siehe auch WORD .
( -- addr +n )
liefert Anfang addr und maximale Länge +n des Quelltextes.
Ist BLK Null, beziehen sich Anfang und Länge auf den Text-eingabe-
puffer, sonst auf den Block, dessen Nummer in BLK steht und der in
den Rechnerspeicher kopiert wurde.
Siehe auch BLOCK und >IN.
( -- addr ) 83 "b-1-k"
Eine Variable, die die Nummer des gerade als Quelltext interpretierten
Blockes enthält. Ist der Wert von BLK Null, so wird der Quelltext vom
Texteingabepuffer genommen.
(n--) 83
Die Inhalte von >IN und BLK , die den gegenwärtigen Quelltext an-
geben, werden gespeichert. Der Block mit der Nummer n wird dann zum
Quelltext gemacht. Der Block wird interpretiert. Die Interpretation wird
bei Ende des Blocks abgebrochen, sofern das nicht explizit geschieht.
Dann wird der alte Inhalt nach BLK und >IN zurückgebracht.
Siehe auch BLK, >IN und BLOCK.
(==) 83,1 "paren"
(==) compiling
wird in der folgenden Art benutzt:
( cce)
Die Zeichen ccc, abgeschlossen durch ) , werden als Kommentar betrach-
tet. Kommentare werden ignoriert. Das Leerzeichen zwischen ( und ccc
ist nicht Teil des Kommentars. ( kann im interpretierenden oder kompi-
lierenden Zustand benutzt werden. Fehlt ) , so werden alle Zeichen im
Quelltext als Kommentar betrachtet.
Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
\\
\needs
+load
thru
+thru
(=) I "skip-line"
Wer) compiling
Ignoriere den auf dieses Wort folgenden Text bis zum Ende der Zeile.
Siehe auch C/L.
(--) T "skip-screen"
(==) compiling
Ignoriere den auf dieses Wort folgenden Text bis zum Ende des Blockes.
Siehe auch B/BLK .
==) "skip-needs"
wird in der folgenden Art benutzt:
\needs <name)
Wird <name> in der Suchreihenfolge gefunden, so wird der auf <name>
folgende Text bis zum Ende der Zeile ignoriert. Wird <name> nicht ge-
funden, so wird die Interpretation hinter <name> fortgesetzt.
Beispiel: \needs Editor 1+ load
lädt den folgenden Block, falls EDITOR im Dictionary nicht vorhanden ist.
Ab der Version 3.81.3 wurde das Konzept um have eingeführt, so daß
die bedingte Kompilation so eingesetzt wird:
have Editor not .IF 1+ load .THEN
In anderen Quellen finden Sie auch exists? .
( Muse) "plus-load"
ladet den Block, dessen Nummer um n höher ist, als die Nummer des
gegenwärtig interpretierten Blockes.
(nn --)
ladet die Blöcke von nl bis inklusive n2.
(ni -—-) ! "plus-thru"
ladet hintereinander die Blöcke, die nl..n2 vom gegenwärtigen Block ent-
fernt sind.
Beispiel 1 2 +thru lädt die nächsten beiden Blöcke.
==) I "next-block"
(--) compiling
Setze die Interpretation auf dem nächsten Block fort.
sr >
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
loadfile ( -- addr)
addr ist die Adresse einer Variablen, die auf das FORTH-File zeigt, das
gerade geladen wird. Diese Variable wird bei Aufruf von LOAD , THRU
usw. auf das aktuelle File gesetzt.
bye —)
Dieses Wort führt FLUSH und EMPTY aus. Anschließend wird der
Monitor des Rechners angesprungen oder eine andere implementationsab-
hängige Funktion ausgeführt. Der Befehl dient zum Verlassen des
volksFORTH.
cold ==)
Bewirkt den Kaltstart des Systems. Dabei werden alle nach der letzter
Ausführung von SAVE definierten Worte entfernt, die Uservariablen auf
den Wert gesetzt, den sie bei SAVE hatten, die Blockpuffer neu initiali-
siert, der Bildschirm gelöscht und die Einschaltmeldung
"volksFORTH-83 rev..."
ausgegeben. Anschliessend wird RESTART ausgeführt.
restart G==)
Bewirkt den Warmstart des Systems. Es setzt 'QUIT, ERRORHANDLER
und "'ABORT auf ihre normalen Werte und führt ABORT aus.
interpret )
Beginnt die Interpretation des Quelltextes bei dem Zeichen, das durch
den Inhalt von )IN indiziert wird. >IN indiziert relativ zum Anfang
des Blockes, dessen Nummer in BLK steht. Ist BLK gleich Null, so
werden Zeichen aus dem Texteingabepuffer interpretiert.
Auch INTERPRET benötigte bisher zur Implementation einen sehr
mysteriösen Systempatch. Dank einer Idee von Mike Perry ist auch diese
letzte Ecke nun abgeschliffen:
Das deferred Wort PARSER enthält entweder den Code für den Inter-
preter oder den Compiler (durch [ und |] wumzuschalten) und Interpret
ist nun eine BEGIN...REPEAT Schleife, in der das nächste Wort aus dem
Quelltext geholt wird. Ist der Quelltext erschöpft, so wird die Schleife
verlassen, andernfalls wird PARSER aufgerufen und dadurch das Wort
entweder interpretiert oder compiliert.
Nun ist es auch sehr viel einfacher als vorher, selber eigene Worte zu
definieren, die in PARSER eingehängt werden. Dies ist immer dann
sinnvoll, wenn der Interpreter in einem Anwendungsprogramm anders als
der übliche FORTH-Interpreter arbeiten soll.
>292 = Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 93,81
prompt
parser
word
parse
name
(ee)
ist ein deferred Wort, das für die Ausgabe des "ok" verantwortlich ist. Es
wurde auch das Wort (QUIT implementiert.
Nun ist es möglich, den FÖRTH-Interpreter auch wie ein "klassisches"
Betriebssystem arbeiten zu lassen, in dem eine Meldung nicht nach jeder
Aktion hinter der Eingabezeile ausgegeben wird, sondern vor einer Aktion
am Anfang der Eingabezeile. Ein entsprechendes Beispiel befindet sich im
Quelltext hinter der Definition von QUIT.
siehe INTERPRET.
(char --»addr-) 83
erzeugt einen counted String durch Lesen von Zeichen vom Quelltext, bis
dieser erschöpft ist oder der Delimiter char auftritt.
Der Quelltext wird nicht zerstört. Führende Delimiter werden ignoriert.
Der gesamte String wird im Speicher beginnend ab Adresse addr als eine
Sequenz von Bytes abgelegt. Das erste Byte enthält die Länge des Strings
(8..255). Der String wird durch ein Leerzeichen beendet, das nicht in der
Längenangabe enthalten ist. Ist der String länger als 255 Zeichen, so ist
die Länge undefiniert. War der Quelltext schon erschöpft, als WORD
aufgerufen wurde, so wird ein String der Länge Null erzeugt. Wird der
Delimiter nicht im Quelltext gefunden, so ist der Wert von >IN die
Länge des Quelltextes. Wird der Delimiter gefunden, so wird >IN so
verändert, dass >IN das Zeichen hinter dem Delimiter indiziert. #TIB
wird nicht verändert. Der String kann sich oberhalb von HERE
befinden.
( char -- addr +n )
liefert die Adresse addr und Länge +n des nächsten Strings im Quelltext,
der durch den Delimiter char abgeschlossen wird.
+n ist Null, falls der Quelltext erschöpft oder das erste Zeichen char
ist. >IN wird verändert.
(„u adärz7)
holt den nächsten String, der durch Leerzeichen eingeschlossen wird, aus
dem Quelltext, wandelt ihn in Grossbuchstaben um und hinterlässt die
Adresse addr, ab der der String im Speicher steht.
Siehe auch WORD .
-ı189 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
find ( addrl -- addr?2 n ) 83
addr]l ist die Adresse eines counted string. Der String enthält einen
Namen, der in der aktuellen Suchreihenfolge gesucht wird.
wird das Wort nicht gefunden, so ist addr2 = addrl und n = Null.
Wird das Wort gefunden, so ist addr2 dessen Kompilations-adresse und n
erfüllt folgende Bedingungen:
n ist positiv, wenn das Wort immediate ist, sonst negativ.
n ist vom Betrag 2 , falls das Wort restrict ist, sonst vom Betrag 1.
notfound ( addr -- )
Ein deferred Wort, das aufgerufen wird, wenn der Text aus dem Quelltext
weder als Name in der Suchreihenfolge gefunden wurde, noch als Zahl
interpretiert werden kann.
Kann benutzt werden, um eigene Zahl- oder Stringeingabeformate zu er-
kennen. Ist mit NO.EXTENSIONS vorbesetzt. Dieses Wort bricht die
Interpretation des Quelltextes ab und druckt die Fehlermeldung "?" aus.
quit ( >=) 83
Entleert den Returnstack, schaltet den interpretierenden Zustand ein,
akzeptiert Eingaben von der aktuellen Eingabeeinheit und beginnt die
Interpretation des eingegebenen Textes.
' ( -- addr ) 83 "tick"
wird in der Form benutzt:
' <name)>
addr ist die Kompilationsadresse von <name)>. Wird <name> nicht in der
Suchreihenfolge gefunden, so wird eine Fehlerbehandlung eingeleitet.
vl ( -- addr ) 83,1,C "bracket-tick"
=) compiling
wird in der folgenden Art benutzt:
['J] <name)
Kompiliert die Kompilationsadresse von <name> als eine Konstante. Wenn
die :-definition später ausgeführt wird, so wird addr auf den Stack ge-
bracht. Ein Fehler tritt auf, wenn <name> in der Suchreihenfolge nicht
gefunden wird.
compile (ee) 83,C
Typischerweise in der folgenden Art benutzt:
: <name) ... compile (namex) ... ;
Wird <name> ausgeführt, so wird die Kompilationsadresse von <namex>
zum Dictionary hinzugefügt und nicht ausgeführt. Typisch ist <name>
immediate und <namex> nicht immediate.
- 154 - Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 9,81
[compile]
immediate
— restrict
Literal
(=) 83,1.C "bracket-compile"
ee compiling
Wird in der folgenden Art benutzt:
[compile) <name>
Erzwingt die Kompilation des folgenden Wortes <name>. Damit ist die
Kompilation ven immediate-Worten möglich.
(a) 83
Markiert das zuletzt definierte Wort als "immediate", d.h. dieses Wort wird
auch im kompilierenden Zustand ausgeführt.
(Fan
Markiert das zuletzt definierte Wort als "restrict", d.h. dieses Wort kann
nicht vom Textinterpreter interpretiert, sondern ausschließlich in anderen
Worten kompiliert werden.
() 83,1 "left-bracket”
(=) compiling
Schaltet den interpretierenden Zustand ein. Der Quelltext wird sukzessive
ausgeführt. Typische Benutzung siehe LITERAL .
Sa) 83,1 "right-bracket"
) compiling
Schaltet den kompilierenden Zustand ein. Der Text vom Quelltext wird.
sukzessive kompiliert. Typische Benutzung siehe LITERAL .
( -- 16b ) 83,1,C
( 16b -- ) compiling
Typisch in der folgenden Art benutzt:
[ 16b ] Literal :
Kompiliert ein systemabhängiges Wort, so daß bei Ausführung 16b auf den
Stack gebracht wird.
(--) "comma-quote"
Speichert einen counted String im Dictionary ab HERE . Dabei wird die
Länge des Strings in dessen erstem Byte, das nicht zur Länge hin-
zugezählt wird, vermerkt.
= 199, —
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Ascii (-- char ) 1
(a) compiling
wird in der folgenden Art benutzt:
Ascii ccc
wobei cce durch ein Leerzeichen beendet wird. char ist der Wert des
ersten Zeichens von ccce im benutzten Zeichensatz (gewöhnlich ASCI).
Falls sich das System im kompilierenden Zustand befindet, so wird char
als Konstante compiliert. Wird die :-definition später ausgeführt, so liegt
char auf dem Stack.
Does> ( -- addr ) 83,1,C "does"
(-) compiling
Definiert das Verhalten des Wortes, das durch ein definierendes Wort er-
zeugt wurde. Wird in der folgenden Art benutzt:
: <typ.name)
<defining time action)
<create) <compiletime action)
Does) <runtime action) ;
und später:
<typ.name) <instance.name)>
wobei <create> CREATE ist oder ein anderes Wort, das CREATE
ausführt. Zeigt das Ende des Wort-erzeugenden Teils des definierenden
Wortes an. Beginnt die Kompilation des Codes, der ausgeführt wird, wenn
<instance.name> aufgerufen wird. In diesem Fall ist addr die Parameter-
feldadresse von <name>. addr wird auf den Stack gebracht und die
Sequenz zwischen DOES> und ; wird ausgeführt.
:Does>
wird benutzt in der Form:
Create (name) :Does) ... ;
Folgende Definition liegt im volks4TH :DOES> zugrunde:
I: (does) here >r [compile] Does) ;
:Does)> last @ 0= Abort" without reference"
(does) current @ context ! hide 6] ;
:DOES> legt das Laufzeit-Verhalten des zuletzt definierten Wortes durch
den bis zum ; nachfolgenden Code fest. Das betreffende Wort wurde mit
Create oder einem Create benutzenden Wort definiert. Eine Anwendung
finden Sie bei den Datentypen.
= 186 Die Ausführung von FORTH-Worten
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
recursive =) LC
(e=) compiling
Erlaubt die rekursive Kompilation des gerade definierten Wortes in diesem
Wort selbst. Ferner kann Code für Fehlerkontrolle erzeugt werden.
Siehe auch MYSELF und RECURSE .
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
15. Der Assembler
Für das volksFORTH stehen zwei Assembler zur Verfügung:
- Ein Assembler entsprechend dem Laxen&Perry F83
- und der eigentliche volks4TH-Assembler.
15.1 Registerbelegung
Im Assembler sind FORTH-gemäße Namen für die Register gewählt worden. Dabei ist
die Zuordnung zu den Intel-Namen folgendermassen:
A- <=> AL
A <=) AX
At <=> AH
C- <=) CL
C <=> CcX
C+ <=> CH
Register A und C sind zur allgemeinen Benutzung frei.
D- <=) DL
D <=> DX
D+ <=> DH
Das D Register enthält das oberste Element des (Daten)-Stacks.
R- <=> RL
R <=> BX
R+ <=> RH
Das B Register hält den Return_stack_pointer
Die weiteren Prozessor-Register werden wie folgt genutzt:
“ja Der Assembler
U <=) BP User_area_pointer
S <=) SP Daten_stack_pointer
I <=) SI Instruction_pointer
W<«=> DI Word_pointer, im allgemeinen zur Benutzung frei.
D: <=} DS E: <=) ES S: <=) SS ©: <=) CS
Alle Segmentregister werden beim Booten auf den Wert des Codesegments C: gesetzt
und muessen, wenn sie "verstellt" werden, wieder auf C: zurueckgesetzt werden.
Assemblerdefinitione werden in FORTH mit code eingeleitet und mit der Sequenz
Next end-code beendet:
Code sp! { addr -- ) DS mov D pop Next end-code
15.2 Registeroperationen
Returnstack
Code rp@ ( -- addr) Dpush RDmov Next end-code
Code rp! ( addr -- } DR mov D pop Next end-code
Code rdrop Rine Rüince Next end-code restrict
Code ?>r (16b --) Rdec Rdec DR) mov D pop
Next end-code restrict
Code rv (--16b) Dpush R)Dmov Rince Rinc
Next end-code restrict
Code r@ ( -- 16b ) D push R) Dmov Next end-code
Code execute ( acf -- ) DW mov D pop
W) jmp end-code
Code perform ( addr --) DW mov D pop
W)Wmov W) jmp end-code
\ : perforn (addr --) ® execute ;
Segmentregister
Code ds@ ( -- ddr) Dpush D:Dmov Next end-code
15.3 Besonderheiten im volksFORTH83
Nachfolgend sind einige interesante Besonderheiten beschrieben:
Der Assembler
FORTH-Geselischaft e.V. PC-volksFORTH83 rev. 3.81
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
NEXT ist ein Makro, sog. in-line code; wenn NEXT kompiliert wird, werden die
in NEXT enthaltenen Mnemnonics in die Definition eingetragen:
Assembler also definitions
: Next lods AW xchg W) jmp
there tnext-link @ T , H tnext-link ! ;
Das Wort EI hinterläßt durch here die Adresse von NEXT auf dem Stack. Diese
Adresse wird in das Codefeld von NOOP geschrieben, so daß ein explizites NEXT
unnötig wird.
t Code ei sti here Next end-code
Code noop here 2- ! end-code
Create recover Assembler
Rdec Rdec IR) mov Ipop Next
end-code
RECOVER soll nie ausgeführt werden, nur die Adresse dieser Routine ist für den
TargetCompiler von Interesse:
se 6 T recover # call ] end-code H ;
In ähnlicher Form findet sich dann die endgültige Form von ;c: für das Target-
System wieder:
ı ca recover # call last off end-code ® ] ;
15.4 Glossar
assembler ee)
ist das Vokabular, das die Assembler-Worte enthält. Die Ausführung
dieses Wortes nimmt ASSEMBLER als context in die Suchreihenfolge
mit auf.
code <name> (==)
leitet eine Assembler-Definiton ein und schaltet die Suchreihenfolge auf
das Vokabular Assembler .
Als Beispiel:
Code sp® ( -- addr ) D push S D mov Next end-code
end-code We
beendet eine Assembler-Definition.
- 169 - Der Assembler
FORTH-Gesellschaft e.V, PC-volksFORTH83 rev. 3.81
Label <name> (ie)
( -- addr )
legt eine benannte Marke an und liefert eine Adresse zurück:
Code exit
Label exit R)Imov Rince Rinc Next end-code
Code unnest exit here 2- ! end-code
Code ?exit ( flag -- )
DDor D pop exit 0= ?] [Ü Next end-code
Code Ö=exit ( flag -- )
DDor Dpop dexit 6= not ?] }] end-code
\: exit ( flag -- ) IF rärop THEN ;
»label <name> (=)
( -- addr )
kann als temporäre Konstante betrachtet werden, die sich mit clear
löschen läßt. Ein von >label zurückgelieferter Wert wird als Literal
kompiliert.
Beispiel: Assembler ö
nop 5555 # jnp here 2- »label >cold
nop 5555 # jmp here 2- >label >restart
code, (==)
beendet den high level Teil eines defining words und leitet dessen
Assembler-Teil ein. Wird benutzt in der Form:
: (name) <Create) ... ;code ... end-code
c ==)
leitet den high level Teil einer Assembler-Definition ein. Das Wort wird
typisch im Handhaben einer Fehlersituation eingesetzt, da dann
Geschwindigkeit keine Rolle mehr spielt. Als Beispiel:
I : stackfull ( -- ) depth $20 > Abort" tight stack"
reveal last? IF dup heap? IF name) ELSE 4- THEN
(forget
THEN
true Abort" dictionary full" ;
Code ?stack u'dpUD) Amov SAsub CS
?[ $100 # A add CS ?[ ;c: stack£full ; Assembler ]? ]?
u'soUD) Amov Ainc Ainc SA sub
CS not ?[ Next ])? ;c: true Abort" stack empty" ;
\: ?stack sp® here - $100 u< IF. stackfull THEN
\ sp@ sO @ u> Abort" stack empty" ;
Der Assembler 1b.»
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
15.5 Kontrollstrukturen im Assembler
benutzt in der Form, wobei ce ein condition code ist:
cc IF ... THEN
Als Beispiel:
Code dup ( 16b -- 16b 16b ) D push Next end-code
Code ?dup ( 16b -- 16b 16b / false )
DDor 0= not ?[ D push ]? Next end-code
a
benutzt in der Form:
cc IF ... ELSE ... THEN
benutzt in der Form:
BEGIN ... REPEAT
Als Beispiel:
Code 1+ (nl -- n2) [E Diünc Next
Code 2+ (nl --n2) [ÜE Diänc swap ])
Code 3+ (nl -- n2) [Ü Dinc .swap ]]
Code 4+ (nl --n2) [E Diäine swap ]]
I Code 6+ (nl -- n2) Dince Dinc 1] end-code
Code 1- (nl -- n2) [Ü Dodec Next
Code 2- (nl -- n2) [Ü Ddec swap ]]
II ce ]]?
benutzt in der Form:
BEGIN ... cc UNTIL
I ce? 1%
benutzt in der Form:
BEGIN ... cc WHILE ... REPEAT
15.6 Beispiele aus dem volksFORTH
pop
Code ärop {16b6-) D pop Next end-code
=.162* Der Assembler
FORTH-Gesellschaf:
t e.V,
PC-volksFORTH83 rev. 3.81
Code ! (1
Next
Code +!
DW mov
6b addr -- )
end-code
{ 16b addr --
A pop AW) add D pop Next
D W nov
)
push
Code 2dup ( 32b -- 32b 32b )
SW mov
Dpush W)
push Next
\ : 2dup ( 32b -- 32b 32b ) over over ;
Code over
AD xchg
Code@ (a
Next
Code c@ (
DW mov
Code c! (
DW mov
Code £flip
\ &_ £flin
Code negate
\ : negate
Code and
A pop
Code or
A pop
Code ctoggl
DW mov
( 16b1 16b2 -- 16b1 16b2 16bi )
D pop D push
ddr -- 16b )
end-code
addr -- &b )
W) D- mov
16b addr -- )
Apop A-W
{ 16b1 -- 16b1'
DW nov
mov
0 # D+ mov Next
) mov D pop
xchg
) D- D+ xchg
( 16b1 -- 16b1' ) $100 um* or
(nl --n2)
{nl --n2)
( 16b1 16b2 --
AD and Next
( 16b1 16b2 --
ADor Next
( 16b1 16b2 --
neg
Dneg Next
not 1+ ;
and
16b3 )
end-code
or
16b3 )
end-code
16b3 ) not swap not and not
xor
e (8b adär -- )
A pop A-W
) xor D pop
W) pop
end-code
A push Next
W) Dmov
end-code
end-code
end-code
r
Der Assembler
= 1637 =
FORTH-Gesellschaft e.V,
Code xeor
( 16b1 16b2 -- 1653
A pop
ADxor Next
\ : etoggle ( 8b addr -- )
under c@ xor swap c!
PC-volksFORTH83 rev. 3.81
)
end-code
add
Code + (n1in2 --n3) Apop AD add Next end-code
sub
Code - (nin2--n3)
Apopp DAsub AD xchg Next end-code
ar» {1m 13] negate + ;
com
Code not ( 16bl -- 16b2 ) D com Next end-code
inc
Code nip ( 16bl 16b2 -- 16b2 ) Sine Since Next end-code
\:nip swap drop ; 5
Code 2drop ( 32b -- ) S inc Sine Dpop Next end-code
\ : 2drop ( 32b -- ) drop drop ;
sal
Code pick (n-- 16b.n )
Dsall DWmov SWadd W) Dmov Next end-code
\ : pick (n-- 16b.n ) 1+ 2% sp@ +@;
std rep byte movs cld
Code roll (n--)
AIxcho Dsal DCmov DImov SIadd
I)Dmov IWmov Idec Winc std
rep byte movs cld A I xchg S inc S$S inc Next
end-code u
\: 261 - (nn =)
\ dup >r pick sp@ dup 2+ r) 1+ 2* cmove> drop ;
Code -roll (n -- ) Alxchog Dsal DC mov
SW mov D pop S I mov $ dec S dec
rep byte movs DW) mov D pop A I xchg Next
end-code
\.:-roll (n-- ) >r dup sp@ dup 2+
\ dup 2+ swap r@ 2* cmove r) 1+ 2* + ! ;
- 164 -
Der Assembler
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
16. Der Multitasker
Ein wichtiger Aspekt der FORTH-Programmierung ist das Multitasking.
So wie man ein Programm in einzelne, unabhängige Module oder Worte aufteilt, so
sollte man es auch in einzelne, unabhängige Prozesse aufteilen können. Das ist in
den meisten Sprachen nicht möglich.
Das volksFORTH83 besitzt einen einfachen, aber leistungsfähigen Multitasker. Er
ermöglicht die Konstruktion von Druckerspoolern, Uhren, Zählern und anderen
einfachen Tasks, kann aber auch für Aufgaben eingesetzt werden, die über einen
Druckerspooler hinausgehen.
Als Beispiel soll gezeigt werden, wie man einen einfachen Druckerspooler kon-
struiert. Das Programm für einen Druckerspooler lautet:
$FO $100 Task background
: spool background activate 1 160 pthru stop ;
multitask spool
Normalerweise würde PTHRU den Rechner "lahmlegen", bis die Screens von 1 bis
100 ausgedruckt worden sind. Bei Aufruf von SPOOL ist das nicht so; der Rech-
ner kann sofort weitere Eingaben verarbeiten. Damit alles richtig funktioniert,
muß PTHRU allerdings einige Voraussetzungen erfüllen, die dieses Kapitel er-
klären will.
Das Wort TASK ist ein definierendes Wort, das eine Task erzeugt. Eine Task be-
sitzt übrigens Userarea, Stack, Returnstack und Dictionary unabhängig von der sog.
Konsolen- oder Main-Task.
Im Beispiel ist $FO die Länge des reservierten Speicherbereichs für Returnstack und
Userarea, $100 die Länge für Stack und Dictionary, jeweils in Bytes. Der Name der
Task ist.in diesem Fall BACKGROUND .
MULTITASK sagt. dem Rechner,:.daß in Zukunft womöglich noch andere Tasks außer
der Konsolentask auszuführen sind. Es schaltet also den Taskwechsler ein. Bei
Ausführen von SINGLETASK wird der Taskwechsler abgeschaltet. Dann wird nur
noch die gerade aktive Task ausgeführt.
Der neue Task tut nichts, bis sie aufgeweckt wird. Das geschieht durch das Wort
SPOOL .. Bei Ausführung von SPOOL geschieht. nun folgendes:
Die Task BACKGROUND wird aufgeweckt und ihr wird der Code hinter ACTIVATE
(nämlich 1 100 PTHRU STOP ) zur Ausführung übergeben. Damit ist die Ausführung
von SPOOL beendet, es können jetzt andere Worte eingetippt werden. Die Task
jedoch führt unverdrossen 1 100 PTHRU aus, bis sie damit fertig ist. Dann stößt
sie auf STOP und hält, an. Man sagt, die Task schläft. Will man die Task
während des Druckvorganges anhalten, z.B. um Papier nachzufüllen, so tippt man
BACKGROUND SLEEP ein. Dann wird BACKGROUND vom Taskwechsler übergangen.
Soll es weitergehen. so tippt man BACKGROUND WAKE ein.
Der Multitasker - 165 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Häufig möchte man erst bei Aufruf von SPOOL den Bereich als Argument angeben,
der ausgedruckt werden soll. Das geht wie folgt:
: newspool ( from to -- ) 2 background pass pthru stop ;
Die Phrase 2 BACKGROUND PASS funktioniert ähnlich wie BACKGROUND ACTIVATE ,
jedoch werden der Task auf dem Stack zusätzlich die beiden obersten Werte ( hier
from und to ) übergeben. Um die Screens 1 bis 188 auszudrucken, tippt man jetzt
ein:
1 100 newspool
Somit entspricht BACKGROUND ACTIVATE gerade der Phrase ® BACKGROUND PASS .
16.1 Implementation
Der Unterschied dieses Multitaskers zu herkömmlichen liegt in seiner kooperativen
Struktur begründet. Damit ist gemeint, daß jede Task explizit die Kontrolle über
den Rechner und die Ein/Ausgabegeräte aufgeben und damit für andere Tasks ver-
fügbar machen muß. Jede Task kann aber selbst "wählen", wann das geschieht. Es
ist klar, daß das oft genug geschehen muß, damit alle Tasks. ihre Aufgaben
wahrnehmen können.
Die Kontrolle über den Rechner wird durch das Wort PAUSE aufgegeben. PAUSE
führt den Code aus, der den gegenwärtigen Zustand der gerade aktiven Task rettet
und die Kontrolle des Rechners an den Taskwechsler übergibt. Der Zustand einer
Task besteht aus den Werten des Interpreterpointers (IP) , des Returnstackpointers
(RP) und des Stackpointers (SP).
Der Taskwechsler besteht aus einer geschlossenen Schleife. Jede Task enthält einen
Maschinencodesprung auf die nächste Task, gefolgt von der Aufweckprozedur. Dort
befindet sich die entsprechende Instruktion der nächsten Task. Ist die Task ge-
stoppt, so wird dort ebenfalls ein Maschinencodesprung zur nächsten Task ausge-
führt. Ist die Task dagegen aktiv, so ist der Sprung durch einen 1-Byte Call auf
einen Vektor ersetzt worden, der die Aufweckprozedur auslöst. Diese Prozedur lädt
den Zustand der Task (bestehend aus SP RP und IP} und setzt den Userpointer
(UP), so daß er auf diese Task zeigt.
SINGLETASK ändert nun PAUSE so, daß überhaupt kein Taskwechsel stattfindet,
wenn PAUSE aufgerufen wird. Das ist in dem Fall sinnvoll, wenn nur eine Task
existiert, nämlich die Konsolentask, die beim Kaltstart des Systems "erzeugt"
wurde. Dann würde PAUSE unnötig Zeit damit verbrauchen, einen Taskwechsel
auszuführen, der sowieso wieder auf dieselbe Task führt.
Das System unterstützt den Multitasker, indem es während vieler Ein/Ausgabe-
operationen wie KEY, TYPE und BLOCK usw. PAUSE ausführt. Häufig reicht
das schon aus, damit eine Task (z.B. der Druckerspooler) gleichmäßig arbeitet.
- 166 - Der Multitasker
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Tasks werden im Dictionary der Konsolentask erzeugt. Jede besitzt ihre eigene
Userarea mit: einer Kopie der Uservariablen. Die Implementation des Systems wird
aber durch die Einschränkung vereinfacht, daß nur die Konsolentask Eingabetext
interpretieren bzw. kompilieren kann. Es gibt z.B. nur eine Suchreihenfolge, die im
Prinzip für alle Tasks gilt. Da aber nur die Konsolentask von ihr Gebrauch macht,
ist das nicht weiter störend.
Der Multitasker beim volksFORTH ist gegenüber z.B. dem des polyFORTH verein-
facht, da volksFORTH ist kein Multiuser-System ist. So besitzen alle Terminal-Ein-
heiten (wir nennen sie Tasks) gemeinsam nur ein Lexikon und einen Eingabepuffer.
Es darf daher nur der OPERATOR (wir nennen ihn Main- oder Konsolen-Task)
kompilieren.
Es ist übrigens möglich, aktive Tasks mit FORGET usw. zu vergessen. Das ist
eine Eigenschaft, die nicht viele Systeme aufweisen! Allerdings geht das manchmal
auch schief... Nämlich dann, wenn die vergessene Task einen "Semaphor" (s.u.)
besaß. Der wird beim Vergessen nämlich nicht freigegeben und damit ist das zuge-
hörige Gerät blockiert.
Schließlich sollte man noch erwähnen, daß beim Ausführen eines Tasknamens der
Beginn der Userarea dieser Task auf dem Stack hinterlassen wird.
16.2 Semaphore und Lock
Ein Problem, daß bisher noch nicht erwähnt wurde, ist die Frage, was passiert,
wenn zwei Tasks gleichzeitig drucken (oder Daten von der Diskette lesen) wollen?
Es ist klar: Um ein Durcheinander oder Fehler zu vermeiden, darf das immer nur
eine Task zur Zeit. Programmtechnisch wird das Problem durch "Semaphore" gelöst:
Variable disp disp off
: newtype disp lock type disp unlock ;
Der Effekt ist der folgende: Wenn zwei Tasks gleichzeitig NEWTYPE ausführen, so
kann doch nur eine zur Zeit TYPE ausführen, unabhängig davon, wie viele
PAUSE in TYPE enthalten sind. Die Phrase DISP LOCK schaltet nämlich hinter
der ersten Task, die sie ausführt, die "Ampel auf rot" und läßt keine andere Task
durch. Die anderen machen solange PAUSE ,„, bis die erste Task die Ampel mit
DISP UNLOCK wieder auf grün umschaltet. Dann kann eine (!) andere Task die
Ampel hinter sich umschalten usw. .
Übrigens wird die Task, die die Ampel auf rot schaltete, bei DISP LOCK nicht
aufgehalten, sondern durchgelassen. Das ist notwendig, da ja TYPE ebenfalls
DISP LOCK enthalten könnte (Im obigen Beispiel natürlich nicht, aber es ist
denkbar).
Der Multitasker = 187 +
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
Die Implementation sieht nun folgendermaßen aus, wobei man sich noch vor Augen
halten muß, daß jede Task eindeutig durch den Anfang ihrer Userarea identifizier-
bar ist:
DISP ist ein sog. Semaphor; er muß den Anfangswert ® haben!
LOCK schaut sich nun den Semaphor an: Ist er Null, so wird die gerade
aktive Task (bzw. der Anfang ihrer Userarea) in den Semaphor ein-
getragen und die Task darf weitermarschieren.
Ist der Wert des Semaphors gerade die aktive Task, so darf sie natürlich auch
weiter. Wenn aber der Wert des Semaphors von dem Anfang der Userarea der akti-
ven Task abweicht, dann ist gerade eine andere Task hinter der Ampel aktiv und
die Task muß solange PAUSE machen, bis die Ampel wieder grün, d.h. der
Semaphor null ist. UNLOCK muß nun nichts anderes mehr tun, als den Wert des
Semaphors wieder auf Null setzen. BLOCK und BUFFER sind übrigens auf diese
Weise für die Benutzung durch mehrere Tasks gesichert: Es kann immer nur eine
Task das Laden von Blöcken von der Diskette veranlassen.
Eine Bemerkung bzgl. BLOCK und anderer Dinge: °
Wie man dem Glossar entnehmen kann, ist immer nur die Adresse des zuletzt mit
BLOCK oder BUFFER angeforderten Blockpuffers gültig, d.h. ältere Blöcke sind, je
nach der Zahl der Blockpuffer, womöglich schon wieder auf die Diskette ausgelagert
worden.
Auf der sicheren Seite liegt man, wenn man sich vorstellt, daß nur ein Blockpuffer
im gesamten System existiert. Nun kann jede Task BLOCK ausführen und damit
anderen Tasks die Blöcke "unter den Füßen" wegnehmen. Daher sollte man nicht die
Adresse eines Blocks nach einem Wort, das PAUSE ausführt, weiter benutzen,
sondern lieber neu mit BLOCK anfordern.
Das Beispiel
line ( block -- )
block c/l bounds DO I c@ emit LOOP ;
ist falsch, denn nach EMIT stimmt der Adressbereich, den der Schleifenindex
überstreicht, womöglich gar nicht mehr.
.line ( block -- )
c/l1 0 DO dup block I + c®@ emit LOOP drop ;
ist richtig, denn es wird nur die Nummer des Blocks, nicht die Adresse seines
Puffers aufbewahrt.
x .line ( block -- ) block c/l type ;
- 168 - Der Multitasker
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ist falsch, da TYPE ja EMIT wiederholt ausführen kann und scemit die von
BLOCK gelieferte Adresse in TYPE ungültig wird.
: >type ( addr len -- ) pad place pad count type ;
ist multitasking-sicher, wenn ein String vom BLOCK geholt wird.
.line ( block -- ) block c/l >type ;
ist deshalb richtig, denn PAD ist für jeden Task verschieden.
16.3 Glossar
activate ( Taddr -- ) -tasker.scr-
aktiviert die Task, die durch Taddr gekennzeichnet ist, und weckt sie
auf.
Vergleiche SLEEP , STOP, PASS, PAUSE, UP@, UP! und WAKE.
lock ( semaddr -- ) -kernel.scr-
Der Semaphor (eine VARIABLE ), dessen Adresse auf dem Stack liegt,
wird von der Task, die LOCK ausführt, blockiert.
Dazu prüft LOCK den Inhalt des Semaphors. Zeigt der Inhalt an, daß
eine andere Task den Semaphor blockiert hat, so wird PAUSE ausge-
führt, bis der Semaphor freigegeben ist. Ist der Semaphor freigegeben, so
schreibt LOCK das Kennzeichen der Task, die LOCK ausführt, in den
Semaphor und sperrt ihn damit für alle anderen Tasks. Den FORTH-Code
zwischen semaddr LOCK ... und ... semadär UNLOCK kann also immer nur
eine Task zur Zeit ausführen.
Semaphore schützen gemeinsame Ressourcen (z.B. den Drucker) vor dem
gleichzeitigen Zugriff durch verschiedene Tasks.
Vergleiche UNLOCK und RENDEZVOUS .
multitask O-=1) -tasker.scr-
schaltet das Multitasking ein.
Das Wort PAUSE ist dann keine NOOP-Funktion mehr, sondern gibt die
Kontrolle über die FORTH-Maschine an eine andere Task weiter.
pass {n®.. nr-1 Taddr r -- ) -tasker.scr-
aktiviert die Task, die durch Taddr gekennzeichnet ist, und weckt sie
auf. r gibt die Anzahl der Parameter n® bis nr-1 an, die vom Stack der
PASS ausführenden Task auf den Stack der durch Taddr
gekennzeichneten Task übergeben werden. Die Parameter n® bis nr-1
stehen dieser Task dann in der gleichen Reihenfolge auf ihrem Stack zur
weiteren Verarbeitung zur Verfügung.
Vergleiche ACTIVATE .
Der Multitasker = 18891 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
pause 35) -kernel.ser-
ist eine NOOP-Funktion, wenn der Singletask-Betrieb eingeschaltet ist;
bewirkt jedoch, nach Ausführung von MULTITASK , daß die Task, die
PAUSE ausführt, die Kontrolle über die FORTH-Maschine an eine andere
Task abgibt.
Existiert nur eine Task, oder schlafen alle anderen Tasks, so wird die
Kontrolle unverzüglich an die Task zurückgegeben, die PAUSE aus-
führte. Ist mindestens eine andere Task aktiv, so wird die Kontrolle von
dieser übernommen und erst bei Ausführung von PAUSE oder STOP in
dieser Task an eine andere Task weitergegeben. Da die Tasks ringförmig
miteinander verkettet sind, erhält die Task, die zuerst PAUSE aus-
führte, irgendwann die Kontrolle zurück. Eine Fehlerbedingung liegt vor,
wenn eine Task weder PAUSE noch STOP ausführt.
Vergleiche STOP , MULTITASK und SINGLETASK .
rendezvous ( semaddr -- ) -tasker.scr-
gibt den Semaphor (die VARIABLE ) mit der Adresse semaddr frei (siehe
UNLOCK ) und führt PAUSE aus, um anderen Tasks den Zugriff auf
das, durch diesen Semaphor geschützte, Gerät zu ermöglichen. Anschlie-
ßend wird LOCK ausgeführt, um das Gerät zurück zu erhalten. Dies ist
eine Methode, eine zweite Task nur an einer genau benannten Stelle lau-
fen zu lassen.
singletask (==) -tasker.scr-
schaltet das Multitasking aus.
PAUSE ist nach Ausführung von SINGLETASK eine NOOP-Funktion.
Eine Fehlerbedingung besteht, wenn eine Hintergrund-Task SINGLETASK
ohne anschließendes MULTITASK ausführt, da die Main- oder Terminal-
Task dann nie mehr die Kontrolle bekommt.
Vergleiche UP@ und UP!.
sleep ( Taddr -- ) -tasker.ser-
bringt die Task, die durch Taddr gekennzeichnet ist, zum Schlafen.
SLEEP hat den gleichen Effekt, wie die Ausführung von STOP durch
die Task selbst. Der Unterschied ist, daß STOP in der Regel am Ende
des Jobs der Task ausgeführt wird. SLEEP trifft die Task zu einem nicht
vorhersehbaren Zeitpunkt, so daß die laufende Arbeit der Task abgebro-
chen wird.
Vergleiche WAKE .
Der Multitasker
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
stop
Task
unlock
==) -tasker.scr-
bewirkt, daß die Task, die STOP ausführt, sich schlafen legt.
Wichtige Zeiger der FORTH-Maschine, die den Zustand der Task kenn-
zeichnen, werden gerettet, dann wird die Kontrolle an die nächste Task
abgegeben, deren Zeiger wieder der FORTH-Maschine übergeben werden, so
daß diese Task ihre Arbeit an der alten Stelle aufnehmen kann. PAUSE
führt diese Aktionen ebenfalls aus, der Unterschied zu STOP ist, daß
die ausführende Task bei PAUSE aktiv, bei STOP hingegen schlafend
hinterlassen wird.
Vergleiche PAUSE , WAKE und SLEEP.
( rlen slen <name> -- ) -tasker.scr-
ist ein definierendes Wort, das in der Form:
rlen slen Task (name)
benutzt wird. TASK erzeugt einen Arbeitsbereich für einen weiteren
Job, der gleichzeitig zu schon laufenden Jobs ausgeführt werden soll.
Die Task erhält den Namen <name>, hat einen Stack-Bereich der Länge
slen und einen Returnstack-Bereich der Länge rlen.
Im Stack Bereich liegen das Task-eigene Dictionary einschließlich PAD,
das in Richtung zu höheren Adressen wächst, und der Daten-Stack, der
zu niedrigen Adressen wächst. Im Returnstack-Bereich befinden sich die
Task-eigene USER-Area (wächst zu höheren Adressen) und der Return-
stack, der gegen kleinere Adressen wächst.
Eine Task ist ein verkleinertes Abbild des FORTH-Systems, allerdings
ohne den Blockpuffer-Bereich, der von allen Tasks gemeinsam benutzt
wird.
Zur Zeit ist es nicht zugelassen, daß Jobs einer Hintergrundtask kompi-
lieren. Die Task ist nur der Arbeitsbereich für einen Hintergrund-Job,
nicht jedoch der Job selbst.
Die Ausführung von <name> in einer beliebigen Task hinterläßt die
gleiche Adresse, die die Task “name selbst mit UP@ erzeugt und ist
zugleich die typische Adresse, die von LOCK „, UNLOCK und
RENDEZVOUS im Zusammenhang mit Semaphoren verwendet wird, bzw. von
ACTIVATE , PASS , SLEEP und WAKE erwartet wird.
( semaddr -- ) -kernel.scr-
gibt den Semaphor (die VARIABLE ), dessen Adresse auf dem Stack ist,
für alle Tasks frei. Ist der Semaphor im Besitz einer anderen Task, so
wartet UNLOCK mit PAUSE auf die Freigabe. Vergleiche LOCK und die
Beschreibung des Taskers.
Der Multitasker = 17 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
up@
up!
wake
User
forge
t
( -- Taddr ) -kernel.scer- "u-p-fetch"
liefert die Adresse Taddr des ersten Bytes der USER-Area der Task, die
UP@ ausführt (siehe TASK ). In der USER-Area sind Variablen und
andere Datenstrukturen hinterlegt, die jede Task für sich haben muß.
Vergleiche UP! .
(addr -- ) -kernel.ser- "uU-p-store"
richtet den UP (User Pointer) der FORTH-Maschine auf addr.
Vorsicht ist bei der Verwendung von UP! in Hintergrund-Tasks geboten.
Vergleiche UP@.
( Taddr -- ) -kernel.scr-
weckt die Task, die durch Taddr gekennzeichnet ist, auf.
Die Task führt ihren Job dort weiter aus, wo sie durch SLEEP angehal-
ten wurde oder wo sie sich selbst durch STOP beendet hat (Vorsicht!).
Vergleiche SLEEP , STOP, ACTIVATE und PASS.
) 83
ist ein definierendes Wort, benutzt in der Form:
User <name> ;
USER erzeugt einen Kopf für <name> im Dictionary und hält 2 Byte in
der Userarea frei (siehe UALLOT).
Diese 2 Byte werden für den Inhalt der Uservariablen benutzt und werden
nicht initialisiert. Im Parameterfeld der Uservariablen im Dictionary wird
nur ein Offset zum Beginn der Userarea abgelegt. Wird <name> ausgeführt,
so wird die Adresse des Wertes der Uservariablen in der Userarea auf
den Stack gegeben. Uservariablen werden statt normaler Variablen z.B.
dann benutzt, wenn der Einsatz des Multitaskers geplant ist und mindes-
tens eine Task die Variable unbeeinflußt von anderen Tasks benötigt
(Jede Task hat ihre eigene Userarea).
(--) 83
Wird in folgender Form benutzt:
FORGET <name)>
Falls <name> in der Suchreihenfolge gefunden wird, so werden <name>
und alle danach definierten Worte aus dem Dictionary entfernt. Wird
<name> nicht gefunden, so wird eine Fehlerbehandlung eingeleitet. Liegt
<name> in dem durch SAVE geschützten Bereich, so wird ebenfalls eine
Fehlerbehandlung eingeleitet. Es wurden Vorkehrungen getroffen, die es
ermöglichen. aktive Tasks und Vokabulare, die in der Suchreihenfolge
auftreten, zu vergessen.
Der Multitasker
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
block (u-- addr ) 83
addr ist die Adresse des ersten Bytes des Blocks u in dessen Blockpuffer.
Der Block u stammt aus dem File in ISFILE.
BLOCK prüft den Pufferbereich auf die Existenz des Blocks Nummer u,
Befindet sich der Block u in keinem der Blockpuffer, so wird er vom
Massenspeicher in einen an ihn vergebenen Blockpuffer geladen. Falls der
Block in diesem Puffer als UPDATEd markiert ist, wird er auf den Mas-
senspeicher gesichert, bevor der Blockpuffer an den Block u vergeben
wird. Nur die Daten im letzten Puffer, der über BLOCK oder BUFFER
angesprochen wurde, sind sicher zugreifbar. Alle anderen Blockpuffer
dürfen nicht mehr als gültig angenommen werden (möglicherweise exi-
stiert nur 1 Blockpuffer).
Vorsicht ist bei Benutzung des Multitaskers geboten, da eine andere Task
BLOCK oder BUFFER ausführen kann. Der Inhalt eines Blockpuffers
wird nur auf den Massenspeicher gesichert, wenn der Block mit UPDATE
als verändert gekennzeichnet wurde.
Der Multitasker . . = 379,2
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
17. Debugging-Techniken
Fehlersuche ist in allen Programmiersprachen die aufwendigste Aufgabe des Pro-
grammierers.
Für verschiedene Programme sind in der Regel auch verschiedene Hilfsmittel erfor-
derlich. Daher kann dieses Kapitel die Fehler-suche nicht erschöpfend behandeln.
Da aber Anfänger häufig typische Fehler machen, kann man gerade für diese
Gruppe brauchbare Hilfsmittel angeben.
Voraussetzung für die Fehlersuche ist immer ein übersichtliches und verständliches
Programm. In FORTH bedeutet das:
_ suggestive und prägnante Namen für Worte
sn starke Faktorisierung, d.h. sinnvoll zusammengehörende Teile eines
Wortes sind zu einem eigenen Wort zusammengefaßt. Worte sollten
durchschnittlich nicht mehr als 2 - 3 Zeilen lang sein !
- Übergabe von Parametern auf dem Stack statt in Variablen, wo
immer es möglich ist.
Guter Stil in FORTH ist nicht schwer, erleichtert aber sehr die Fehlersuche. Ein
Buch, das auch diesen Aspekt behandelt, sei unbedingt empfohlen : "In FORTH
denken" von Leo Brodie, Hanser Verlag 1986.
Sind die genannten Bedingungen erfüllt, ist es meist möglich, die Worte interaktiv
zu testen. Damit ist gemeint, daß man bestimmte Parameter auf den Stack legt und
anschließend das zu testende Wort aufruft. Anhand der hinterlassenen Werte auf
dem Stack kann man dann beurteilen, ob das Wort korrekt arbeitet.
Sinnvollerweise testet man natürlich die zuerst definierten Worte auch zuerst, denn
ein Wort, das fehlerhafte Worte aufruft, funktioniert natürlich nicht korrekt. Wenn
nun ein Wort auf diese Weise als fehlerhaft identifiziert wurde, muß man das Ge-
schehen innerhalb des Wortes verfolgen. Das geschieht meist durch "tracen".
17.1 Der Tracer
Allgemein wird man zuerst das fehlerhafte Wort isoliert testen wollen. Dazu legt
man ausgewählte Werte als Parameter für dieses Wort auf den Stack und beobachtet
die Verarbeitung dieser Werte innerhablb des Wortes.
Angenommen, Sie wollen das Wort -TRAILING auf Fehler untersuchen. Die
Funktion dieses Wortes ist das "Abschneiden" von Leerzeichen am Ende einer Zei-
chenkette:
= 174 = Debugging-Techniken
FORTH-Geseilschaft e.V. PC-volksFORTH83 rev. 3.81
: -trailing ( addri nl -- addri n2 )
2dup bounds ?DO 2dup + 1- c@ bl =
IF leave THEN 1- LOOP ;
Dabei könnten Sie dem Wort schon im Editor ein anderes Erscheinungsbild geben,
indem Sie z.B. die Schleifenanweisungen ?DO und LOOP bündig untereinander
schreiben, durch das Einfügen von Leerzeichen eine Gliederung schaffen oder die
IF... THEN-Anweisung auf einer eigenen Zeile isolieren.
Zum Testen des Wortes wird ein String benötigt. Sie definieren bitte:
Create teststring ," Dies ist ein Test E
Dabei haben Sie absichtlich einige zusätzliche Leerzeichen eingefügt.
Um die Werte auf dem Stack, meist Adressen, besser interpretieren zu können,
schalten Sie mit HEX die Zahlenbasis um und geben nun ein (Antwort des
Computers unterstrichen) :
hex ok
teststring .s 8686 ok
count .s 1B 8687 ok
-trailing .s 1B 8687 ok
Der Aufruf von TESTSTRING liefert Ihnen die Stringadresse (hexadezimal) 8686 und
das Wort COUNT berechnet Ihnen daraus die Länge der Zeichenkette und ihren
Beginn.: 1B 8687 (auch hexadezimal)
Beim Aufruf von -TRAILING stellen Sie an Hand der unveränderten Adressen zu
Ihrem Erstaunen fest, daß -TRAILING kein einziges Leerzeichen abgeschnitten
hat.
Spätestens jetzt sollten Sie am Rechner sitzen und den Tracer laden, wenn er noch
nicht im System vorhanden ist. Prüfen Sie dazu, ob es das Wort TOOLS im
FORTH-Vokabular gibt, dann ist der Tracer vorhanden. Denn der Tracer gehört zum
Vokabular Tools , dessen Quelltexte Sie auf Ihrer Diskette finden.
Mit dem Tracer können Sie Worte, die mit dem : definiert wurden, schrittweise
testen. Der Tracer läßt sich mit dem Wort TRACE starten, das seinerseits ein zu
tracendes FORTH-Wort erwartet. TRACE schaltet im Gegensatz zu DEBUG nach
Durchlauf des Wortes den Tracer automatisch mit END-TRACE wieder ab.
Um den Tracer zu benutzen, geben Sie nun folgendes ein:
teststring count
.S. „IB 8687 ok
tools trace -trailing
Es erscheint dieses Bild. wenn Sie nach dem Erscheinen einer jeden Zeile solange
die <CR>Taste drücken, bis wieder ok erscheint:
8658 66A 2DUP 1B 8687
865A AB2 BOUNDS 1B 8687 1B 8687
Debugging-Techniken = a5 =
FORTH-Gesellschaft e.V.
PC-volksFORTH83 rev. 3.81
865C A8O
8660 66A
8662 6E2
8664 789
8666 469
8668 2224
866A 91B
866C B34
8610 CFB
8678 AOD
(?DO
2DUP
+
1-
ce®
BL
?BRANCH
LEAVE
UNNEST
8687 86A2 1B 8687
1B 8687
1B 8687 1B 8687
86A2 1B 8687
86Al 1B 8687
20 1B 8687
20 20 1B 8687
FFFF 1B 8687
1B 8687
1B 8687
Betrachten Sie zuerst die Syntax von TRACE :
trace <(nanel)>
Hierbei ist <namel> das zu tracende Wort, wobei die vom Tracer zurückgelieferte
Information so aussieht:
addri addr2 <name2)
addri
addr2
<name2?>
Werte
Werte
ist eine Adresse im Parameterfeld von <namel>, nämlich die, in der
addr2 steht.
ist die KompilationsAdresse von <name2).
ist das Wort, das als nächstes ausgeführt werden soll !
sind die Werte, die gerade auf dem Stack liegen.
Wie deuten Sie nun das eben erhaltene Bild ? In der ersten Zeile, die der Tracer
beim Abarbeiten des zu untersuchenden Wortes
Sie:
8658 66A 2DUP
1B 8687
Hier ist 1B 8687 der Stackinhalt, wie er von
nämlich Adresse und Länge des Strings TESTSTRING. Natürlich können die Zahlen
bei Ihnen anders aussehen,
kompiliert wurde.
66A ist die Kompilationsadresse von
Auch diese Adressen können sich bei Ihnen geändert haben! Diese
so daß auch im Falle mehrerer Worte mit gleichem
-TRAILING .
Zahlen werden mit ausgegeben,
Namen eine Identifizierung möglich ist.
je nachdem, wohin
2DUP ,
-TRAILING angezeigt hat, finden
TESTSTRING COUNT geliefert wurde,
TESTSTRING und -TRAILING
8658 die Position von 2DUP in
Sehen wir uns die Ausgabe nun etwas genauer an.
Bei den ersten beiden Zeilen wächst der Wert ganz links immer um 2. Es ist der
Inhalt des Instructionpointers IP, der immer auf die nächste auszuführende Adresse
zeigt. Der Inhalt dieser Adresse ist jeweils eine Kompilationsadresse 66A bei 2DUP
usw.. Jede Kompilationsadresse benötigt zwei Bytes, daher muß der IP immer um 2
erhöht werden.
Immer? Nein, denn schon die nächste Zeile zeigt eine Ausnahme.
Das Wort
(?DO
finition von
-TRAILING
erhöht den IP um 4
stand doch nur
(?DO
! Woher kommt eigentlich (?DO , in der De-
DO .
ist ein von ?DO kompi-
Debugging-Techniken
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
liertes Wort, das zusätzlich zur Kompilationsadresse noch einen l6Bit-Wert be-
nötigt, nämlich für den Sprungoffset hinter LOOP , wenn die Schleife beendet ist.
Zwei ähnliche Fälle treten noch auf. Das IF aus dem Quelltext hat ein ?BRANCH
kompiliert. Es wird gesprungen, wenn der oberste Stackwert FALSE (=) ist. Auch
?BRANCH benötigt einen zusätzlichen 16Bit-Wert für den Sprungoffset.
Nach LEAVE geht es hinter LOOP weiter, es wird UNNEST ausgeführt, das
vom ; in -TRAILING kompiliert wurde und das gleiche wie EXIT bewirkt.
Damit ist das Wort -TRAILING auch beendet. Das hier gelistete Wort UNNEST
ist nicht zu verwechseln mit dem UNNEST des Tracers, siehe unten.m
Wo liegt nun der Fehler in unserer Definition von -TRAILING ?
Bevor Sie weiterlesen, sollten Sie die Fehlerbeschreibung, den Tracelauf und Ihre
Vorstellung von der korrekten Arbeitsweise des Wortes noch einmal unter die Lupe
nehmen.
Der Stack ist vor und nach -TRAILING gleich geblieben, die Länge des Strings
also nicht verändert worden. Offensichtlich wird die Schleife gleich beim ersten Mal
verlassen, obwohl das letzte Zeichen des Textes ein Leerzeichen war. Die Schleife
hätte also eigentlich mit dem vorletzten Zeichen weiter machen müssen.
Mit anderen Worten: Die Abbruchbedingung in der Schleife ist falsch! Sie ist genau
verkehrt herum gewählt. Ersetzt man = durch = NOT oder - ,so funktioniert
das Wort korrekt. Überlegen Sie bitte, warum auch - statt = NOT eingesetzt
werden kann. Tip: Der IF-Zweig wird nicht ausgeführt, wenn der oberste Stackwert
FALSE , also gleich NULL ist.
Der volksFORTH83-Tracer gestattet es, jederzeit Befehle einzu-geben, die vor dem
Abarbeiten des nächsten Trace-Kommandos ausgeführt werden. Das System wartet
nach einem Step auf eine Eingabe von der Tastatur, bevor der nächste Step ausge-
führt wird. .
Endet eine Zeile mit einem Leerzeichen vor dem <CR> , so erlaubt der Tracer die
Eingabe und Verarbeitung einer vollständigen Kommandozeile. Die Anforderung wird
wiederholt, wenn in dieser Zeile ein Eingabe-Fehler auftauchen sollte. Damit ist
__ jetzt ein etwas stressfreieres Ändern des Code bzw. des Stack während des Tracens
möglich.
So kann man z. B. Stack-Werte verändern oder das Tracen abbrechen. Ändern Sie
probehalber beim nächsten Trace-Lauf von -TRAILING durch Eingabe von NOT
das TRUE-Flag ($FFFF) auf dem Stack. bevor ?BRANCH ausgeführt wird und ver-
folgen Sie den weiteren Trace-Lauf. Sie werden bemerken, daß die LOOP ein
zweites Mal durchlaufen wird.
Wollen Sie das Tracen und die weitere Ausführung des getraceten Wortes ab-
brechen, so geben Sie restart ein. RESTART führt einen Warm-Start des
FORTHSystems aus und schaltet den Tracer ab. RESTART ist auch die Katastro-
phen-Notbremse, die man einsetzt, wenn man sieht, daß das System mit dem näch-
sten Befehl zwangsläufig im ComputerNirwana entschwinden wird.
Debusging-Techniken =
-ı
=
l
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
17.2 Debug
Beim Tracen mit TRACE - nomen est omen - haben wir das fehlerhafte Wort
isoliert zusammen mit ausgesuchten Parametern analysiert.
Im Gegensatz dazu bietet sich die Möglichkeit an, ein Wort in seiner Umgebung,
also in der Definition, in der es fehlerhaft arbeitet, zu untersuchen. Dazu dient
der Befehl DEBUG :
debug (name)
Hierbei ist <name> das zu tracende Wort.
17.2.1 Beispiel: EXAMPLE
Bleiben wir bei unserem Beispiel, geben Sie bitte eine Definition mit -TRAILING
ein. Dabei bietet sich zunächst die gleiche Sequenz wie oben an. Bitte definieren
Sie dieses Beispiel :
: example ( --)
teststring count
-trailing clearstack ;
Nun aktivieren Sie den Tracer mit :
debug -trailing
Zunächst geschieht noch gar nichts. DEBUG hat nur den Tracer "scharf" gemacht.
Rufen Sie nun mit EXAMPLE ein Wort auf, das <name> enthält, unterbricht der
Tracer die Ausführung, wenn er auf <name> stößt. Es erscheint folgendes, Ihnen
schon bekanntes Bild:
example
8658 66A 2DUP 1B 8687
865A AB2 BOUNDS 1B 8687 1B 8687
865C A80 (?DO 8687 86A2 1B 8687
8660 66A 2DUP 1B 8687
8662 6E2 + 1B 8687 1B 8687
8664 789 1- 86A2 1B 8687
Die Parameter sind unter diesen Bedingungen natürlich wieder die, die von
TESTSTRING und COUNT auf den Stack gelegt werden. Interessant ist aber hier
die Kontrolle, ob -TRAILING vielleicht falsche Parameter übergeben bekommt.
17.2.2 NEST und UNNEST
Nützlich ist auch die Möglichkeit, das Wort, das als nächstes zur Ausführung an-
steht, seinerseits zu tracen, bis es ins aufrufende Wort zurückkehrt.
- 178, - Debugging-Techniken
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Dafür ist das Wort nest vorgesehen. Allerdings beschränkt sich dieses Möglichkeit
auf Worte, die in Highlevel-FORTH geschrieben sind. Assemblercode läßt sich damit
nicht debuggen und Sie erhalten eine Meldung;
name) can't be debugged
Bitte tracen Sie unser Beispiel wieder mit TRACE EXANFLE :
Wenn Sie nun wissen wollen, was -TRAILING innerhalb des Beispiels macht, so
geben Sie bitte NEST ein, wenn -TRAILING als nächstes auszuführendes Wort
angezeigt wird.
Sie erhalten dann:
trace example
8669 8684 TESTSTRING
86B2 EEF COUNT 8686
86B4 8656 -TRAILING 1B 8687 nest
8653 66A 2DUP 1B 8687
865A AB2 BOUNDS 1B 8687 1B 8687
865C A8O ?DO 8687 86A2 1B 8687
8660 66A 2DUP 1iB 8687
8662 6E2 + 1B 8687 1B 8687
8664 789 1- 86A2 1B 8687
8666 469 Ce 86A1l 1B 8687
8668 2224 BL 20 1B 8687
866A 91B = 20 20 1B 8687
866C B34A ?BRANCH FFFF 1B 8687
8670 CFB LEAVE 1B 8687
8678 AOD UNNEST ı1B 8687
86B6 162E CLEARSTACK 1B 8687
8658 AOD UNNEST ok
Beachten Sie bitte, daß die Zeilen jetzt eingerückt dargestellt werden, bis der
Tracer automatisch in das aufrufende Wort zurückkehrt. .Der Gebrauch von NEST
ist nur dadurch eingeschränkt, daß sich einige Worte, die den ReturnStack mani--
pulieren, mit NEST nicht tracen lassen, da der Tracer selbst Gebrauch vom
ReturnStack macht. Auf solche Worte muß man den Tracer mit DEBUG ansetzen.
Wollen Sie das Tracen eines Wortes beenden, ohne die Ausführung des Wortes ab-
zubrechen, so benutzen Sie unnest .
Ist der Tracer geladen, so kommen Sie an das tief im System steckende UNNEST ,
einem Synonym für EXIT , das ausschließlich vom ; kompiliert wird, nicht mehr
heran und benutzen statt dessen das Tracer-UNNEST, das Sie eine Ebene im
Tracelauf zurückbringt.
Manchmal hat man in einem Wort vorkommende Schleifen beim ersten Durchlauf als
korrekt erkannt und möchte diese nicht weiter tracen. Das kann sowohl bei
DO...LOOPs der Fall sein als auch bei Konstruktionen mit BEGIN...WHILE...REPEAT
oder BEGIN...UNTIL. In diesen Fällen gibt man am Ende der Schleife das Wort
endloop ein. Die Schleife wird dann in Echtzeit abgearbeitet und der Tracer mel-
Debugging-Techniken - 199 -
FORTH-Geseilschaft e.V. PC-volksFORTH83 rev. 3.81
det sich erst wieder, wenn er nach dem Wort angekommen ist, bei dem ENDLOOP
eingegeben wurde.
Sollte statt dessen die Meldung: ENDLOOP COMPILE ONLY zu sehen sein, so ist das
Vokabular TOOLS nicht in der Suchreihenfolge . Haben Sie den Fehler gefunden
und wollen deshalb nicht mehr tracen, so müssen Sie nach dem Ende des Tracens
END-TRACE oder jederzeit RESTART eingeben, ansonsten bleibt der Tracer
"scharf", was zu merkwürdigen Erscheinungen führen kann; außer dem verringert
sich bei eingeschaltetem Tracer die Geschwindigkeit des Systems.
Beachten Sie bitte auch, daß Sie für die Worte DEBUG und TRACE das Voka-
bular TOOLS mit in die Suchreihenfolge aufgenommen haben. Sie sollten also nach
hoffentlich erfolgreichen Tracelauf die Suchordnung wieder umschalten, weil der
Befehl RESTART zwar den Tracer abschaltet, aber die Suchreihenfolge nicht zu-
rückschaltet.
Wenn man sich eingearbeitet hat, ist der Tracer ein wirklich verblüffendes Werk-
zeug, mit dem man sehr viele Fehler schnell finden kann. Er ist gleichsam ein
Mikroskop, mit dem man sehr tief ins Innere von FORTH schauen kann.
17.3 Stacksicherheit
Anfänger neigen häufig dazu, Fehler bei der Stackmanipulation zu machen. Er-
schwerend kommt häufig hinzu, daß sie viel zu lange Worte schreiben, in denen es
dann von unübersichtlichen Stackmanipulationen nur so wimmelt. Es gibt einige
Worte, die sehr einfach sind und Fehler bei der Stackmanipulation früh erkennen
helfen. Denn leider führen schwerwiegende Stackfehler zu "mysteriösen" System-
crashs.
In Schleifen führt ein nicht ausgeglichener Stack oft zu solchen Fehlern. Während
der Testphase eines Programms oder Wortes sollte man daher bei jedem Schleifen-
durchlauf prüfen, ob der Stack evtl. über- oder leerläuft. Das geschieht durch
Eintippen von :
: LOOP compile ?stack [compile] LOOP
: +LOOP compile ?stack [compile) +LOOP
: UNTIL compile ?stack [compile] UNTIL
: REPEAT compile ?stack [compile) REPEAT
: compile ?stack ;
immediate restrict
immediate restrict
immediate restrict
immediate restrict
Versuchen Sie ruhig, herauszufinden wie die letzte Definition funktioniert. Es ist
nicht kompliziert. Durch diese Worte bekommt man sehr schnell mitgeteilt, wann ein
Fehler auftrat. Es erscheint dann die Fehlermeldung
<name) stack full
wobei <name> der zuletzt vom Terminal eingegebene Name ist.Wenn man nun
überhaupt keine Ahnung hat. wo der Fehler auftrat, so gebe man ein:
: unravel
rdrop rdrcp rdrop \ delete errorhandlernest
cr ." trace dump on abort is :" cr
- FOR - Debugging-Techniken
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
BEGIN rp@ rö @ - \ until stack empty
WHILE r? dup 8 u.r space
2- @ >name .name cr
REPEAT (error ;
unravel errorhandler !
Sie bekommen dann bei Eingabe von 1 2 6 */ ungefähr folgenden Ausdruck :
trace dump on abort is:
E32 */MOD 1D8A EXECUTE
1E24 PARSER
20CD INTERPRET
20FA 'QUIT / division over£flow
__ 'QUIT INTERPRET PARSER und EXECUTE rühren vom Textinterpreter her.
Interessant wird es bei */MOD . Wir wissen, daß */MOD von */ aufgerufen
wird. */MOD ruft nun wieder M/MOD auf, in M/MOD gehts weiter nach
UM/MOD . Dieses Wort ist in Code geschrieben und "verursachte" den Fehler, indem
es eine Division durch Null ausführte.
Nicht immer treten Fehler in Schleifen auf. Es kann auch der Fall sein, daß ein
Wort zu wenig Argumente auf dem Stack vorfindet, weniger nämlich, als Sie für
dieses Wort vorgesehen haben. Diesen Fall sichert ARGUMENTS . Die Definition
dieses Wortes ist:
: arguments (n--)
depth 1- < abort" not enough arguments" ;
Es wird folgendermaßen benutzt:
: -trailing ( addr len) 2 arguments ... ;
wobei die drei Punkte den Rest des Quelltextes andeuten sollen.
Findet -TRAILING nun weniger als zwei Werte auf dem Stack vor, so wird eine
Fehlermeldung ausgegeben. Natürlich kann man damit nicht prüfen, ob die Werte
auf dem Stack wirklich für -TRAILING bestimmt waren.
Sind Sie als Programmierer sicher, daß an einer bestimmten Stelle im Programm eine
bestimmte Anzahl von Werten auf dem Stack liegt, so können Sie das ebenfalls
sicherstellen:
: isdepth (n--) depth 1- - abort" wrong depth" ;
ISDEPTH bricht das Programm ab, wenn die Zahl der Werte auf dem Stack nicht
gleich n ist, wobei n natürlich nicht mitgezählt wird. Es wird analog zu
ARGUMENTS benutzt. Mit diesen Worten lassen sich Stackfehler oft feststellen und
lokalisieren.
Debugging-Techniken = 1a >
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
17.4 Aufrufgeschichte
Möchte man wissen, was geschah, bevor ein Fehler auftrat und nicht nur, wo er
auftrat.- denn nur diese Information liefert UNRAVEL - so kann man einen
modifizierten Tracer verwenden, bei dem man nicht nach jeder Zeile <CR> drücken
muß:
> ==)
Does)» cr rdepth 2* spaces
dup 2- >name .name )r ;
Hierbei wird ein neues Wort mit dem Namen : definiert, das zunächst das alte
Wort : aufruft und so ein Wort im Dictionary erzeugt. Das Laufzeitverhalten die-
ses Wortes wird aber so geändert, daß es sich jedesmal wieder ausdruckt, wenn es
aufgerufen wird. Alle Worte, die nach der Redefinition, so nennt man das erneute
Definieren eines schon bekannten Wortes, des : definiert wurden, weisen dieses
Verhalten auf.
Beispiel:
Sa
» rechhe (--n) 123//;
RECHNE / / RECHNE division overflow
Wir sehen also, daß erst bei der zweiten Division der Fehler auftrat. Das ist auch
logisch, denn 2 3 / ergibt ©.
Sie sind sicher in der Lage, die Grundidee dieses zweiten Tracers zu verfeinern.
Ideen wären z.B.:
- Ausgabe der Werte auf dem Stack bei Aufruf eines Wortes
- Die Möglichkeit, Teile eines Tracelaufs komfortabel zu unterdrücken.
17.5 Dump
Einen Speicherdump benötigt man beim Programmieren sehr oft, mindestens dann,
wenn man eigene Datenstrukturen anschauen will. Oft ist es dann hinderlich,
eigene Worte zur womöglich gar formatierten Ausgabe der Datenstrukturen schreiben
zu müssen. In diesen Fällen benötigt man ein Wort, das einen Speicherdump aus-
gibt. Das volksFORTH besitzt zwei Worte zum Dumpen von Speicherblöcken sowie
einen Dekompiler, der auch für Datenstrukturen verwendet werden kann.
= 182 - Debugging-Techniken
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
dump
(addrn -- )
Ab addr werden n Bytes formatiert ausgegeben. Dabei steht am Anfang
einer Zeile die Adresse, dann folgen 16 Byte, die in der Mitte zur bes-
seren Übersicht getrennt sind und dann die Ascii-Darstellung. Dabei wer-
den nur Zeichen im Bereich zwischen $2® und $7F ausgegeben. Die Aus-
gabe läßt sich jederzeit mit einer beliebigen Taste unterbrechen oder mit
<Esc> abbrechen.
Mit PRINT läßt sich die Ausgabe auf einen Drucker umleiten.
Beispiel: print pad 40 dump display
Das abschließende DISPLAY sorgt dafür, daß wieder der Bild-schirm als
Ausgabegerät gesetzt wird.
— Möchte man Speicherbereich außerhalb des .FORTH-Systems dumpen, gibt es dafür
das Wort:
ldump
(laddrn --)
erwartet eine - doppelt lange - absolute Speicheradresse und wie oben
die Anzahl der auszugebenden Bytes. Die Ausgabe auf einen Drucker ge-
schieht genau so wie oben beschrieben.
17.6 Dekompiler
Ein Dekompiler gehört so zu sagen zum guten Ton eines FORTH Systems, war er
bisher-doch die einzige Möglichkeit, wenigstens. ungefähr den Aufbau eines Systems
zu durchschauen. Bei volks FORTH83 ist das anders, und zwar aus zwei Gründen:
Sie haben sämtliche Quelltexte vorliegen, und es gibt die VIEW-Funktion. Letztere
ist normalerweise sinn voller als der beste Dekompiler, da kein Dekompiler in der
Lage ist, z.B. Stackkommentare zu rekonstruieren.
Der Tracer ist beim Debugging sehr viel hilfreicher als ein Dekompiler, da er auch
die Verarbeitung von Stackwerten erkennen läßt. Damit sind Fehler leichter aufzu-
finden. r
Dennoch gibt es natürlich auch im volksFORTH einen Dekompiler, zum einen als zu-
ladbares Werkzeug und zum anderen in einfacher von Hand zu bedienender Form.
Der zuladbare Dekompiler SEE wird mit
include see.scr
geladen und in der Form
see (name)
benutzt. Daraufhin wird das Wort dekompilert.
Als ständig verfügbares Dekompiler-Werkzeug stehen im Vokabular TOOLS folgende
Worte zur Verfügung:
Debugging-Techniken - 183 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
N name ( addr -- addr' )
druckt den Namen des bei addr kompilierten Wortes aus und setzt addr
auf das nächste Wort,
L literal ( addr -- addr' )
wird nach LIT benutzt und druckt den Inhalt von addr als Zahl aus. Es
wird also nicht versucht, den Inhalt, wie bei N, als FORTH-Wort zu
interpretieren.
S string ( addr -- addr' )
wird nach ABORT" , ", ." und allen anderen Worten benutzt, auf die
ein String folgt. Der String wird ausgedruckt und addr entsprechend er-
höht, sodaß sie hinter den String zeigt.
C character ( addr -- addr' )
druckt den Inhalt von addr als Ascii-Zeichen aus und geht ein Byte
weiter. Damit kann man eigene Datenstrukturen ansehen.
B branch ( addr -- addr')
wird nach BRANCH oder ?BRANCH benutzt und druckt den Inhalt einer
Adresse als Sprungoffset und Sprungziel aus.
D dump ( addr n -- addr' )
dumped n Bytes. Wird benutzt, um selbstdefinierte Daten strukturen an-
zusehen.
Siehe auch DUMP und LDUMP.
Sehen wir uns nun ein Beispiel zur Benutzung des Dekompilers an. Geben Sie bitte
folgende Definition ein:
: test (n--)
12 = IF cr ." Die Zahl ist zwölf !" THEN ;
Rufen Sie das Vokabular TOOLS durch Nennen seines Namens auf und ermitteln
Sie die Adresse des ersten in TEST kompilierten Wortes:
' test >body
Jetzt können Sie TEST nach folgendem Muster dekompilieren:
n 80B0: 856 CLIT
c 80B2: 12
n 80B3: 92A =
n 80B5: B43 ?BRANCH
b 80B7: 1B 80D2
n 8059: ZBEI CR
n 80BB: 127E (."
s 80BD: 14 Die Zahl ist zwölf !
n 8002: 41C UNNEST
= 18 = Debugging-Techniken
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Die erste Adresse ist die, an der im Wort TEST die anderen Worte kompiliert
sind. Die zweite ist jeweils die Kompilationsadresse der Worte, danach folgen die
sonstigen Ausgaben des Dekompilers.
Probieren Sie dieses Beispiel auch mit dem Tracer aus: 29 trace test und achten
Sie auf die Unterschiede. Sie werden sehen, daß der Tracer aussagefähiger und
dazu noch einfacher zu bedienen ist.
Wenn Sie sich die Ratschläge und Tips zu Herzen genommen haben und noch etwas
den Umgang mit den Hilfsmitteln üben, werden Sie sich sicher nicht mehr vorstellen
können, wie Sie jemals in anderen Sprachen ohne diese Hilfsmittel ausgekommen
sind. Bedenken Sie bitte auch: Diese Mittel sind kein Heiligtum - oft wird Sie eine
Modifikation schneller zum Ziel führen. Scheuen Sie sich nicht, sich vor dem Be-
arbeiten einer umfangreichen Aufgabe erst die geeigneten Hilfsmittel zu pro-
grammieren.
17.7 Glossar
restart (==)
ermöglicht gegenüber den Versionen auf dem ATARI und dem C64 auf
Grund der Konstruktion ausschließlich den Ausstieg aus dem Single-Step-
Trace-Modus .
end-trace ai
dient lediglich dazu, um einen DEBUG-Befehl rückgängig zu machen.
Schaltet den Tracer ab, der durch "patchen" der Next-Routine arbeitet.
Die Ausführung des aufrufenden Wortes wird fortgesetzt.
next-link ( -- addr.)
addr ist die Adresse einer Uservariablen, die auf die Liste aller Next-
routinen zeigt. Der Assembler erzeugt bei Verwendung des Wortes NEXT
Code, für den ein Zeiger in diese Liste eingetragen wird. Die so ent-
standene Liste wird vom Tracer benutzt, um alle im System vorhandenen
Kopien des Codes für NEXT zu modifizieren.
Debugging-Techniken j85-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
18. Begriffe
18.1 Entscheidungskriterien
Bei Konflikten läßt sich das Standardteam von folgenden Kriterien in Reihenfolge
ihrer Wichtigkeit leiten:
1; Korrekte Funktion - bekannte Einschränkungen, Eindeutigkeit.
g, Transportabilität — wiederholbare Ergebnisse, wenn Programme zwi-
schen Standardsystemen portiert werden.
3. Einfachheit
Klare, eindeutige Namen - die Benutzung beschreiben - der statt
funktionaler Namen, z.B. [COMPILE] statt 'c, und ALLOT statt
dp+!..
5, Allgemeinheit
6 Ausführungsgeschwindigkeit
Ts Kompaktheit
8. Kompilationsgeschwindigkeit
9, Historische Kontinuität
10. Aussprechbarkeit
il; Verständlichkeit -— es muß einfach gelehrt werden können
18.2 Definition der Begriffe
Es werden im allgemeinen die amerikanischen Begriffe beibehalten, es sei denn, der
Begriff ist bereits im Deutschen geläufig. Wird ein deutscher Begriff verwendet, so
wird in Klammern der engl. Originalbegriff beigefügt; wird der Originalbegriff bei-
behalten, so wird in Klammern eine möglichst treffende Übersetzung angegeben.
Adresse, Byte (address, byte)
Eine 16bit Zahl ohne Vorzeichen, die den Ort eines 8bit Bytes im Bereich
<0...65.535> angibt. Adressen werden wie Zahlen ohne Vorzeichen mani-
puliert.
Siehe: "Arithmetik, 2er-komplement"
Adresse, Kompilation (address, compilation)
Der Zahlenwert, der zur Identifikation eines FORTH Wortes kompiliert
wird. Der Adressinterpreter benutzt diesen Wert, um den zu jedem Wort
gehörigen Maschinencode aufzufinden.
- 186 - Begriffe
FORTH-Gesellschaft e.V, PC-vclksFORTH83 rev. 3.81
Adresse, Natürliche (address, native machine)
Die vorgegebene Adressdarstellung der Computerhardware.
Adresse, Parameterfeld (address, parameter field) "pfa"
anzeigen
Die Adresse des ersten Bytes jedes Wortes, das für das Ablegen von
Kompilationsadressen ( bei :-definitionen ) oder numerischen Daten bzw.
Textstrings usw. benutzt wird.
(display)
Der Prozess, ein oder mehrere Zeichen zum aktuellen Ausgabegerät zu
senden. Diese Zeichen werden normalerweise auf einem Monitor angezeigt
bzw. auf einem Drucker gedruckt.
Arithmetik, 2er-komplement (arithmetic, two's complement)
Block
Die Arithmetik arbeitet mit Zahlen in 2er-Komplementdarstellung; diese
Zahlen sind, je nach Operation, 16bit oder 32bit weit. Addition und
Subtraktion von 2er-Komplementzahlen ignorieren Überlaufsituationen.
Dadurch ist es möglich, daß die gleichen Operatoren benutzt werden kön-
nen, gleichgültig, ob man die Zahl mit Vorzeichen ( -32.768...32,767 bei
16-Bit ) oder ohne Vorzeichen ( 8...65,535 bei 16-Bit) benutzt.
(block)
Die 1024 Byte Daten des Massenspeichers, auf die über Blocknummern im
Bereich 9...Anzahl_existenter_Blöcke-1 zugegriffen wird. Die exakte
Anzahl der Bytes, die je Zugriff auf den Massenspeicher übertragen wer-
den, und die Übersetzung von Blocknummern in die zugehörige Adresse
des Laufwerks und des physikalischen Satzes, sind rechnerabhängig.
Siehe: "Blockpuffer" und "Massenspeicher"
Blockpuffer (block buffer)
Ein 1824 Byte langer Hauptspeicherbereich, in dem ein Block vorüber-
gehend benutzbar ist. Ein Block ist in höchstens einem Blockpuffer ent-
halten.
Byte (byte)
Eine Einheit von 8bit. Bei Speichern ist es die Speicherkapazität von
8bits.
Begriffe
= 187,
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Kompilation (compilation)
Der Prozess, den Quelltext in eine interne Form umzuwandeln, die später
ausgeführt werden kann. Wenn sich das System im Kompilationszustand
befindet, werden die Kompilationsadressen von Worten im Dictionary ab-
gelegt, so daß sie später vom Adresseninterpreter ausgeführt werden
können. Zahlen werden so kompiliert, daß sie bei Ausführung auf den
Stack gelegt werden. Zahlen werden aus dem Quelltext ohne oder mit
negativem Vorzeichen akzeptiert und gemäß dem Wert von BASE umge-
wandelt.
Siehe: "Zahl", "Zahlenumwandlung", "Interpreter, Text" und "Zustand"
Definition (Definition)
Siehe: "Wortdefinition"
Dictionary (Wörterbuch)
Division,
Eine Struktur von Wortdefinitionen, die im Hauptspeicher des Rechners
angelegt ist. Sie ist erweiterbar und wächst in Richtung höherer Spei-
cheradressen. Einträge sind in Vokabularen organisiert, so daß die Be-
nutzung von Synonymen möglich ist, d.h. gleiche Namen können, in ver-
schiedenen Vokabularen enthalten, vollkommen verschiedene Funktionen
auslösen.
Siehe; "Suchreihenfolge"
floored (division, floored)
Ganzzahlige Division, bei der der Rest das gleiche Vorzeichen hat wie der
Divisor oder gleich Null ist; der Quotient wird gegen die nächstkleinere
ganze Zahl gerundet. Bemerkung: Ausgenommen von Fehlern durch Über-
lauf gilt: Ni N2 SWAP OVER /MOD ROT * + ist identisch mit Ni.
Siehe: "floor, arithmetisch"
Beispiele: Dividend Divisor Rest Quotient
10 7 3 1
-10 7 4 2
10 -1 -4 -2
-18 -2 -3 1.
Empfangen receive)
Falsch
Der Prozess, der darin besteht, ein Zeichen von der aktuellen Eingabe-
einheit zu empfangen. Die Anwahl einer Einheit ist rechnerabhängieg.
(false)
Die Zahl Null repräsentiert den "Falschzustand" eines Flags.
- 188 -
Begriffe
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Fehlerbedingung (error condition)
Eine Ausnahmesituation, in der ein Systemverhalten erfolgt, das nicht mit
der erwarteten Funktion übereinstimmt. Im der Beschreibung der einzelnen
Worte sind die möglichen Fehlerbedingungen und das dazugehörige Sys-
temverhalten beschrieben.
Flag (logischer Wert)
Eine Zahl, die eine von zwei möglichen Werten hat, falsch oder wahr.
Siehe: "Falsch" , "Wahr"
Floor, arithmetic
Glossar
Z sei eine reelle Zahl. Dann. ist der Floor von Z die größte ganze Zahl,
die kleiner oder gleich Z ist.
Der Floor von +9,6 ist ®
Der Floor von -9,4 ist -1
(glossary)
Eine umgangssprachliche Beschreibung, die die zu einer Wortdefinition ge-
hörende Aktion des Computers beschreibt - die Beschreibung der Seman-
tik des Wortes.
Interpreter, Adressen (interpreter, address)
Die Maschinencodeinstruktionen, die die kompilierten Wort-definitionen
ausführen, die aus Kompilationsadressen bestehen.
Interpreter, Text (interpreter, text)
Eine Wortdefinition, die immer wieder einen Wortnamen aus dem Quelltext
holt, die zugehörige Kompilationsadresse bestimmt und diese durch den
Adressinterpreter ausführen läßt. Quelltext, der als Zahl interpretiert
wird, hinter-läßt den entsprechenden Wert auf dem Stack.
Siehe: "Zahlenumwandlung"
“»Kontrollstrukturen (structure, control)
Eine Gruppe von Worten, die, wenn sie ausgeführt werden, den Programm-
fluß verändern. Beispiele von Kontrollstrukturen sind:
DO ... LOOP
BEGIN ... WHILE ... REPEAT
IF .. ELSE ... THEN
laden (load)
Das Umschalten des Quelltextes zum Massenspeicher. Dies ist die übliche
Methode, dem Dictionary neue Definitionen hinzuzufügen.
Begriffe - 7898-
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Massenspeicher (mass storage)
Speicher, der ausserhalb des durch FORTH adressierbaren Bereiches liegen
kann. Auf den Massenspeicher wird in Form von 1924 Byte großen Blök-
ken zugegriffen. Auf einen Block kann innerhalb des FORTH-Adressbe-
reichs in einem Blockpuffer zugegriffen werden. Wenn ein Block als ver-
ändert ( UPDATE ) gekennzeichnet ist, wird er letztendlich wieder auf
den Massenspeicher zurückgeschrieben.
Programm (program)
Eine vollständige Ablaufbeschreibung in FORTH-Quelltext, um eine be-
stimmte Funktion zu realisieren.
Quelltext (input stream)
Eine Folge von Zeichen, die dem System zur Bearbeitung durch den Text-
interpreter zugeführt wird. Der Quelltext kommt üblicherweise von der
aktuellen Eingabeeinheit (über den Texteingabepuffer) oder dem Massen-
speicher (über einen Blockpuffer). BLK , IN , TIB und #TIB
charakterisieren den Quelltext. Worte, die BLK ,„ >»IN ,„ TIB oder
#TIB benutzen und/oder verändern, sind dafür verantwortlich, die Kon-
trolle des Quelltextes aufrechtzuerhalten oder wiederherzustellen. Der
Quelltext reicht von der Stelle, die durch den Relativzeiger >IN ange-
geben wird, bis zum Ende. Wenn BLK Null ist, so befindet sich der
Quelltext an der Stelle, die durch TIB adressiert wird, und er ist #TIB
Bytes lang. Wenn BLK ungleich Null ist, so ist der Quelltext der Inhalt
des Blockpuffers, der durch BLK angegeben ist, und er ist 1024 Byte
lang.
Rekursion (recursion)
Der Prozess der direkten oder indirekten Selbstreferenz.
Screen (Bildschirm)
Ein Screen sind Textdaten, die zum Editieren aufbereitet sind. Nach Kon-
vention besteht ein Screen aus 16 Zeilen zu je 64 Zeichen. Die Zeilen
werden von ® bis 15 durchnumeriert. Screens enthalten normalerweise
Quelltext. können jedoch auch dazu benutzt werden, um Massenspeicher-
daten zu betrachten. Das erste Byte eines Screens ist gleichzeitig das
erste Byte eines Massenspeicherblocks; dies ist auch der Anfangspunkt
für Quelltextinterpretation während des Ladens eines Blocks.
= 199 = Begriffe
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Suchreihenfolge (search order)
Eine Spezifikation der Reihenfolge, in der ausgewählte Vokabulare im
Dietionary durchsucht werden. Die Suchreihenfolge besteht aus einem
auswechselbaren und einem festen Teil, wobei der auswechselbare Teil
immer als erstes durchsucht wird. Die Ausführung eines Vokabularnamens
macht es zum ersten Vokabular in der Suchreihenfolge, wobei das Voka-
bular, das vorher als erstes durchsucht worden war, verdrängt wird. Auf
dieses erste Vokabular folgt, soweit spezifiziert, der feste Teil der Such-
reihen-folge, der danach durchsucht wird. Die Ausführung von ALSO
übernimmt das Vokabular im auswechselbaren Teil in den festen Teil der
Suchreihenfolge. Das Dictionary wird immer dann durchsucht, wenn ein
Wort durch seinen Namen aufge-funden werden soll.
stack, data (Datenstapel)
Eine "Zuletzt-rein, Zuerst-raus" (last-in, first-out) Struktur, die aus
einzelnen 16bit Daten besteht. Dieser Stack wird hauptsächlich zum Ab-
legen von Zwischenergebnissen während des Ausführens von Wortdefini-
tionen benutzt. Daten auf dem Stack können Zahlen, Zeichen, Adressen,
Boole'sche Werte usw. sein. Wenn der Begriff "Stapel" oder "Stack" ohne
Zusatz benutzt wird, so ist immer der Datenstack gemeint.
stack, return (Rücksprungstapel)
Eine "Zuletzt-rein, Zuerst-raus" Struktur, die hauptsächlich Adressen von
Wortdefinitionen enthält, deren Ausführung durch den Adressinterpreter
noch nicht beendet ist. Wenn eine Wortdefinition eine andere Wortdefini-
tion aufruft, so wird die Rücksprungadresse auf dem Returnstack abge-
legt. Der Returnstack kann zeitweise auch für die Ablage anderer Daten-
benutzt werden.
String, counted (abgezählte Zeichenkette)
Eine Hintereinanderfolge von 8bit Daten, die im Speicher durch ihre
niedrigste Adresse charakterisiert wird. Das Byte an dieser Adresse
enthält einen Zahlenwert im Bereich <®...255>, der die Anzahl der zu
diesem String gehörigen Bytes angibt, die unmittelbar auf das Countbyte-
folgen. Die Anzahl beinhaltet nicht das Countbyte selber. Counted Strings
enthalten normalerweise ASCII-Zeichen.
String, Text (Zeichenkette)
Eine Hintereirıanderfolge von 8bit Daten, die im Speicher durch ihre
niedrigste Adresse und ihre Länge in Bytes charakterisiert ist. Strings
enthalten normalerweise ASCII-Zeichen. Wenn der Begriff "String" alleine
oder in Verbindung mit anderen Begriffen benutzt wird, so sind Text-
strings gemeint.
Begriffe
- 19er
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Userarea (Benutzerbereich)
Ein Gebiet im Speicher, das zum Ablegen der Uservariablen benutzt wird
und für jeden einzelnen Prozeß/Benutzer getrennt vorhanden ist.
Uservariable (Benutzervariable)
Eine Variable, deren Datenbereich sich in der Userarea befindet. Einige
Systemvariablen werden in der Userarea gehalten, sodaß die Worte, die
diese benutzen, für mehrere Prozesse/Benutzer gleichzeitig verwendbar
sind.
Vokabular (vocabulary)
Eine geordnete Liste von Wortdefinitionen. Vokabulare werden vorteilhaft
benutzt, um Worte voneinander zu unterscheiden, die gleiche Namen
haben (Synonyme). In einem Vokabular können mehrere Definitionen mit
dem gleichen Namen existieren; diesen Vorgang nennt man redefinieren.
Wird das Vokabular nach einem Namen durchsucht, so wird die jüngste
Redefinition gefunden.
Vokabular, Kompilation (vocabulary, compilation)
Das Vokabular, in das neue Wortdefinitionen eingetragen werden.
Wahr (true)
Ein Wert, der nicht Null ist, wird als "wahr" interpre-tiert. Wahrheits-
werte, die von Standard-FORTH-Worten errechnet werden, sind 16bit
Zahlen, bei denen alle 16 Stellen auf "1" gesetzt sind, so daß diese zum
Maskieren benutzt werden können.
Wort, Definierendes (defining word)
Ein Wort, das bei Ausführung einen neuen Dictionary-Eintrag im Kompi-
lationsvokabular erzeugt. Der Name des neuen Wortes wird dem Quelltext
entnommen. Wenn der Quelltext erschöpft ist, bevor der neue Name er-
zeugt wurde, so wird die Fehlermeldung "ungültiger Name" ausgegeben.
Beispiele von definierenden Worten sind: : CONSTANT CREATE
Wort, immediate (immediate word)
Ein Wort, das ausgeführt wird, wenn es während der Kompilation oder
Interpretation aufgefunden wird. Immediate Worte behandeln Sondersitua-
tionen während der Kompilation.
Siehe z.B. IF LITERAL ." usw.
— 1I2M- Begriffe
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Wortdefinition (word definition)
Wortname
Eine mit einem Namen versehene, ausführbare FORTH-Proze-dur, die ins
Dictionary kompiliert wurde. Sie kann durch Maschinencode, als eine
Folge von Kompilationsadressen oder durch sonstige kompilierte Worte
spezifiziert sein. Wenn der Begriff "Wort" ohne Zusatz benutzt wird, so ist
im allgemeinen eine Wortdefinition gemeint.
(word name)
Der Name einer Wortdefinition. Wortnamen sind maximal 31 Zeichen lang
und enthalten kein Leerzeichen. Haben zwei Definitionen verschiedene
Namen innerhalb desselben Voka-bulars, so sind sie eindeutig auffind-
bar, wenn das Vokabular durchsucht wird.
Siehe: "Vokabular"
Zahl (number)
Wenn Werte innerhalb eines größeren Feldes existieren, so sind die
höherwertigen Bits auf Null gesetzt. 16bit Zahlen sind im Speicher so ab-
gelegt, dass sie in zwei benachbar-ten Byteadressen enthalten sind. Die
Bytereihenfolge ist rechnerabhängig. Doppeltgenaue Zahlen (32bit) werden
auf dem Stack so abgelegt, daß die höherwertigen 16bit (mit dem Vor-
zeichenbit) oben liegen. Die Adresse der niederwer-tigen 16bit ist um
zwei größer als die Adresse der höherwertigen 16bit, wenn die Zahl im
Speicher abgelegt ist.
Siehe: "Arithmetik, 2er-komplement" und "Zahlentypen"
Zahlenausgabe, bildhaft (pictured numeric output)
Durch die Benutzung elementarer Worte für die Zahlenaus-gabe ( z.B. <#
# #5 #)> ) werden Zahlenwerte in Textstrings umgewandelt. Diese De-
finitionen werden in einer Folge benutzt, die ein symbolisches Bild des
gewünschten Ausga-beformates darstellen. Die Umwandlung schreitet von
der niedrigstwertigen zur höchstwertigen Ziffer fort und die umgewandel-
ten Zeichen werden von höheren gegen niedrigere Speicheradressen abge-
legt.
Zahlenausgabe, freiformatiert (free field format)
Zahlen werden in Abhängigkeit von BASE umgewandelt und ohne füh-
rende Nullen, aber mit einem folgenden Leerzei-chen, angezeigt. Die An-
zahl von Stellen, die angezeigt werden, ist die Minimalanzahl von Stellen
- mindestens eine - die notwendig sind, um die Zahl eindeutig darzu-
stellen.
Siehe: "Zahlenumwandlung"
Begriffe
= 119355
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Zahlentypen (number types)
Alle Zahlentypen bestehen aus einer spezifischen Anzahl von Bits. Zahlen
mit oder ohne Vorzeichen bestehen aus bewerteten Bits. Bewertete Bits
innerhalb einer Zahl haben den Zahlenwert einer Zweierpotenz, wobei das
am weitesten rechts stehende Bit (das niedrigstwertige) einen Wert von
zwei hoch null hat. Diese Bewertung setzt sich bis zum am weitesten
links stehenden Bit fort, wobei sich die Bewertung für jedes Bit um eine
Zweierpotenz erhöht. Für eine Zahl ohne Vorzeichen ist das am weitesten
links stehende Bit in diese Bewertung eingeschlossen, sodaß für eine
solche 16bit Zahl das ganz linke Bit den Wert 32768 hat. Für Zahlen mit
Vorzeichen wird die Bewertung des ganz linken Bits negiert, sodaß es bei
einer 16bit Zahl den Wert -32768 hat. Diese Art der Wertung für Zahlen
mit Vorzeichen wird 2er-komplementdarstellung genannt.Nicht spezifi-
zierte, bewertete Zahlen sind mit oder ohne Vorzeichen; der Programm-
kontext bestimmt, wie die Zahl zu interpretieren ist.
Zahlenumwandlung (number conversion)
Zeichen
Zahlen werden intern als Binärzahlen geführt und extern durch graphi-
sche Zeichen des ASCII Zeichensatzes darge-stellt. Die Umwandlung zwi-
schen der internen und externen Form wird unter Beachtung des Wertes
von BASE durchge-führt, um die Ziffern einer Zahl zu bestimmen. Eine
Ziffer liegt im Bereich von Null bis BASE-1. Die Ziffer mit dem Wert Null
wird durch das ASCII-zeichen "8" (Position 3/0, dezimalwert 48) darge-
stellt. Diese Zifferndarstellung geht den ASCII-code weiter aufwärts bis
zum Zeichen "9", das dem dezimalen Wert neun entspricht. Werte, die jen-
seits von neun liegen, werden durch die ASCII-zeichen beginnend mit "A",
entsprechend dem Wert zehn usw. bis zum ASCII-zeichen """, entsprechend
einundsiebzig, dargestellt.Bei einer negativen Zahl wird das ASCII-Zeichen
"-" den Ziffern vorangestellt. Bei der Zahleneingabe kann der aktuelle
Wert von BASE für die gerade umzuwandelnde Zahl dadurch umgangen
werden, daß den Ziffern ein "Zahlenbasisprefix" vorangesteilt wird. Dabei
wird durch das Zeichen "%" die Basis vorübergehend auf den Wert zwei
gesetzt, durch "&" auf den Wert zehn und durch "$" oder "h" auf den
Wert sechzehn. Bei negativen Zahlen folgt das Zahlenbasisprefix dem
Minuszeichen. Enthält die Zahl ein Komma oder einen Punkt, so wird sie
als 32bit Zahl umgewandelt.
(character)
Eine 8bit Zahl, deren Bedeutung durch den ASCII-Standard festgelegt ist.
Wenn es in einem größeren Feld gespeichert ist, so sind die höherwerti-
gen Bits auf Null gesetzt.
- 194 -
Begriffe
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Zustand
(mode)
Der Textinterpreter kann sich in zwei möglichen Zuständen befinden: dem
interpretierenden oder dem kompilierenden Zustand. Die Variable STATUS
wird vom System entsprechend gesetzt, und zwar enthält sie bei der
Interpretation eine False-flag, bei der Kompilation eine True-flag.
Siehe: "Interpreter, Text" und "Kompilation”
Begriffe
= 195 —
FORTH-Gesellschaft e.\V. PC-volksFORTH83 rev. 3.81
Indexverzeichnis
DABEI Eee nennen rer ern eaneeT 110, 140
(decode.
(diskerror
(error ...
(expect..
(fsearch
(key...
(key? ..
(more...
- 196 - Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
MI nenn een kumn: 151
+LOOP ... er 43
+print
a uvcse ..6, 114, 182
..55, 57, 156
»asciz.
DDOG Yen innen een ee ee
»expect.
Ylabel...
»mark ...
DL EEE RE EL 68
FAISKERLOR nme HERE fänlree\ ee yrehteeeegee
Indexverzeichnis = IRA
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
[FCB]
[Method]
\
-— j58 Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Anne era ef 29
Abbruchbedingung ..
DOT a ee RENTE ee ee
RT ende neun iunurheteeiitgek
abSsimkeunr
accumulate ...
activate ......
address...
Adressinterpreter .. ah
AGREBTAUTDI ne en ehe ehe ...107
AGAIN ee eeriinaebles 45
Alias
align
all-buffers
allot
allotbuffer...
DIES ER ne
and
SPIDER rn ren BIN I TTURTERTER TI
APPUKAUON: re Te ne 88
Team ...63
areakol....... +68
arguments .. .181
ASCHSGOGER. Sesam tan rn Te essen. een teen 69
ISChZ a rn TR ETT E 80, 103
ASSEMmbIlen. een er ren Rn Zn ....194, 144, 168
SESIene. Mana een nn 93
Associative: ...56
DRS anna 65
attächt... >78
attribut. 104
b/bik ..... .94
b/buf..... .94
b/seg ..... SE ae een ee een TI Tee Eee ıll
BERKER. een REN 62
BALICHSBlle, nennen „107
BedingtesKoMpPIIENUN 8, ee elemente 4
BELCH In een mann nennen ee Ia#6
BEGIN .... ..44
BELL nenn 1.262
BEtrIC HEs väter ern 153
BERWEENL nasse nn ea tee erneuern 49
Bildschirm ............ ..63, 73
BilASchirtmausgabern an energie er ee 64
Bildschirmseite... enaseennenn eneegeaehenennen Re 63
DIE neun Ererheeteneinheenee 62
DEREK nenne Tenen e eneeeeeeee 109
Dann .93, 150
DURING ae ernennen een En Manage ee 94
DIOCKS et .95, 136, 173, 187
DIOCKSbÜT er... ernennen ee ee Eee 187
BlOCKBEId... een een .... 136
BIOSCK AD): mine tg een ER TETETTeITeTAI TE 7ı
bounds .... ..44, 78
BÜMER.. adsense Re ee NR Tee“ 95
DI ee ae TIERE RE 152
Indexverzeichnis 7938 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
187
capacities
capacity ..
COPA 4... nennen ernennen en ee
capitalize
character.
charout..
BlöBT „un
clearstack
Colon-Definition .. de ;
Solondefinition. enunnanneuzunn nee mm 41
compilation. ..188, 192
BORD enge euere e en 154
Constant .. „113
conteXt.... ..133
convert. +
convey .. .100
EOUNTFBITE: un nn
COUuNted nun nennseeeweenennneneenneenee een ennenenns
counted String ... ei
counted StFINBS .....ueesesensesesenensnsnsnsnnnnsensnnnensenensestsnnsnsnensnnennnnnnnsnnusnennennnnnen
Countfeld, as am am 1110001010111 Be U un
CSWaP .... BETRETEN eretereleu ital 109
ctoggle .. i
=.200 ,- Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.8]
CHTOTEN Yan ansehen enneeeneeeereeeeeneeeeTeeeeeTg en eELE 65
CUTOIK nennen 65
GUN ON ee een een heine rturne nr RER ee een eine 133
TURSDADE, nennen sun nenne ee were TTLTITERIEE 65
GUTS OT er RA ansehen einatmen r rer eee aeeeesehn erregen 65
CURSORHOSILIONL....nnenununnenuenen nen «69,68
custom-remove. r42
One ecnessienunseininnniehmnneiessiegtenhieee nee rege u
IR Mae unseeeeiende ...34
d= ..34
d.... ...66
d.r 67
d< .34
= .34
GO eiennailasenaneninnenennei ee een 34
GRDSER nee en ee a esse antrae use 34
Datei
Anlegen. nem en 15
EN RER RERREE cc 15
Datei-Steuerblock . 84
Dateivariable ........ 84
Datenformat ....... «0
Datenstrukturen.
Datentyp ............
debug .......
decode...
Dalai
defining word
Definition
definitions ....
DeKompiler ...en.a. een en en ea EN.
UT ten nase ers enleei rapie en een Eee ee EEE
delete...
GERINE Te anne eneinene sense
GELRACH nannten
DictHonary u... &5
DIEVIONANSDOIDLER, „moment seen EEE EEE ae 68
digit? .... „81
ÜRTGR ea ner anne nnlannaiae sanierte ernennen ERIET ES SEE Tee 99
direct .... say 195
DITEEROTY rpineieannnin see ee ee ee 85
DIREKEZUSTIFT. nennen nenne ea 87
USDIAY „ou N 187
DIVISION... umnassenernegene nennen ein ee een EEE ER EEE ern ee ee 188
DOESN near nenasanuneinuseh seine Teer ee EEE EERETETE 121, 156
drop
Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
DRUCRENSPOBLER anna nennen nennen 165
Druckersteuerung
Start des Compilers.....
Tastenbelegung ...........
Smit are
empty-buffers. ei
enipty-kKeysunue ungen
emptybuf
end-code
endloop En 5
Entwieklungssysten... oo un
OR 9 na III III FERN.
ETASE ann
error condition..
ELLI ia
EITOr# en
errorhandler .......rnen se
erweiterten Adreßraum....neenee.
Escape aan Bereien
ERTL Een ei aan anna ns
BREcUTLIon VER nn
ERISTET iin
extend.......
F83-NUMBER?.
Faktorisierung
Fakultäten
Fallunterscheidung.
fblock@....
EFGB ss sie
felose ...........
Fehlercode.... u
PERTETSUCHE nein en anne ent esse
FELD
TRBEE una aaa ker aa IH 10H 15T aIdTkEkNSc UI. CE
EIER erde Te er Te EEE Tee
figFORTH. . nie
DIIORR Rn rennen En ERTL TITTEN
12021 Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Eile-Interfäce res serien ae 84
file ink u.
file? cc...
FORTH-Screen ..
Er LEERE TEETSOT ERLERNTE TERENN 192
TTEEHUNTET. 200 een nee een erarbeiten nalen een reines enejeelsge zeige 98
freset ........ „181
DEOINS er EEE a EEE EEE eh an eo ern te kennen an e khnceiuggeiye 189
fromfile ... 116,91
TSEARERE. re ennumnneenae ten ennee anne Pennes se TEL T ER ETaE Eee naerRe Sas een rende 194
fseek .... .182
fswap ... url
DEI DER raenieeinn mn ee TEE TEN EEE REES Ha nee namen arrkeenia ne 98
SOLE nee
Fünkblonstaste as. mean enenae nennen een TREE EER TER EEET TREE 59
dee 69
gets „121
SIODa N ee ee en u sedtnsnch seta ehe sehegehsussseeen 35
Glossar
BOBIT=S WORTEN. een el ee RE Tears uiesnnaeraune nee 33
Arithmetischer Eunktionen 7... ee edenereeeanedenseneennesnedseenen ernennen 29
ASSEMDIEL.....sereeoslemeenen nenne ...168
MUSATUCKEN! VON ISOTEENS uni nenee haste sun enuenun ensure nenne 25
DEDUEEINSR een een nalen ten nen sera he seen sen Sehen Se Fer eeeee 185
KONDROLSTROKLURENE ee ee nen ee seems esemenubeeenneraiieenenengenwegiee 41
Logik-undr Vergleichen. m er ee 32
Multitasker.................. ...169
Speicheroperationen .. et
Stackoperationen ....... 36
Derminal-VO nen anne san n denen eneenneen nennen een 62
VEKtOLISTEHUNE- Bene hauen he ende ern see een ae een yo Tea EER Es 128
VOKaDUWAar.. nennen samen nase ane en nee ann nalen eier en eeeironte 133
SIOSSATY „ucuccuies
GOTOXY..
Na ee ee nee ee he ene tee ee
Da Ole nn eenn eiEn SRTERRENET RT EHI Rh afarelıhanesiie
Handle-Nummer
Indexverzeichnis = 208 =
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Handlenummer .............
have. a Ai
headerless words.
Heap...
heap?
help
here
hide, su
high-Byte..
high-word uns:
KIA. „unannemnenemennene
Usa
De nme aeeufänete
immediate ............
immediate word...
immediate-BE uses; ...137
INNE" CHAR nennen nannten nennen 169
include .......... 27, 94
INGEX neuere 26,
INAITECL BIT. 137
INPUT ame au 68, 127
input stream .. nennen Taeie 198
INT DU nennt ee ERTEILT EL IRDIT TEN TEL TEE ETTILTTELRER 48, 82
Input: a. u 127, 129
inputkol .....eccn... ER ERERETIERE ER 63
Instructionpointer .. ae 146, 176
Instruktionszeiger .. Kenssnssssunensensersnnennne 146
INTEL-Prozessor..... RENTEN DEUNER 197
INTELDIEN anna en 12, 152
Interpreter ......cceessesennsssenseensnenensnrennnn nee aan 153, 189
IP sen: ee 146, 176
BE ne ET EEE EEE LEITERN 128
IS-FEPEH resaun nam eann a a 01 II DL. 46
isdepth ....
isfile ....
isfile®@..
ee nmeseisgealee
Kaltstartwerte == y
kernel .. nenn ee ee 123
key..... 69, 117
KENNE. Dennsis ninendereenemennsim nass arte UT BRETT TRETEN ET TEE 117
keyboard.
KIIENE,. nennen 101
Kommandozeile 177
Kommentare „sauer
Kompilationsadresse .............. Kaiser e 185
Kompilationsvokabular Een nase SET 133
Konsolentask .....uuresnsesenenennensenennnennensnnensenenensnsenenensnensnensssesnensenene era aa 165
lallocate..
- 204 .- Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
Linefeed ..
INK en
Linkfeld .. 137
TO hrs oezenlees 143
a SEN
IST RN ee selektieren 132
listing ... 25
BIER ln ee Te en eisernen ee 155
Literatur
Allgemeines über FORTH ... mir
Kontrollstrukturen.......... 59
NO ee rleährkeserstetene 111
VO er esteniäte 93, 150, 189
sa 103, 152
leadfrom .....
loadscreen ..
JOCHMr ee et een
ION ns ren
LOOR Aus
Low-Byte ...
low-word
ST er a ee tere 66
ltype 74, 112
einen las ee 34
TE On ee 34
MARER. en ee TE ET TETE SETI ehaer nee enssne une see 93
makefile .... ..86, 93
MAREVIEWAR Dee ENTE TEN su feeneeelnneeneete 131
N KO ee ee een 160
mass storage... „190
MALEN rs TO:
a RR ee ee N Teenie 119
TR Eee ae reed EN ReIE Neschinatn.en scale ne ereumneninerelelen 30
PA en hama ..85, 90
MELACO DIA ae 123
MONO TER ene eigen 21
Methodsiu. 22... mm ehren 121
a 90
Mod el
Module.. ..165
More ..... „86, 94
TON TS 108
MSAOS rer eat 88
Indexverzeichnis - 205 -
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
MSDOS-Fileinterface............ecnsssensseesesssenenssnnessnnnssnnenssnensaenunnansnnnsennnnnnnnnnen 88
mülbtask seen ..165, 169
Multitasking .......... nn +78, 165
notfound .. een kenn
NUDEBYEE =nsstesentunuartersa areas BraENteTRE TEL EETEEETTETTTTERLETÄTTERE TEE TETTET ER TEIRE 808
nullstring? .. 78, 76
number ......
number? 81, 82
Of ren 122
DIE nn
„197
OT uukeskaresreenautendiein ...189
ON 134
Onlyforthynsesseense „134
OBEN nee ..101
Operator...... ....66
OPENATONEN euere Ben a III 121
origin
OUt Of range .eeeeeeenaesenenenensnsnnunensnensnsensnsesensnensenenensnsnsnsestsensnssnsansessssnsnssnnnen
output ......... > RER, 73
Output: ....... 130
outputkol .... zur . u
OVERn..n..r Er mise nenn hueersieire ee 37
PADsncs „67, 68, 118
Page ....... as = 20, 26, 64
Parameter ee mnsienenwrrnimasemanaen ...96, 196, 138
Parameterfeld 138, 139, 146
path er 15, 26, 89
PAUSE eeeennennseesssssensnnennnnnnnennsnersennenennnnnunnnnnnnnneseneenennnnnnnnnnnn 64, 69, 73, 179
DON nice rTeansITrEe eure 67
PC®@ .......
perform
Peripheriebaustein „ss... ana 67
Pfad ..
- 286-— Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3,81
DIACE. rat nt en rn ee NET T 110
DEE nenn 25
DOT ee ee en ee 67
positional CASE ... &
POSENKSNOBATLIOND ne 7
BREV an nett KERN IE I Rn 98
PEINE ..66
DRINLET zitieren 66
Prorrstn aeun Er 113, 199
Befehlsteil. ee Basen 213
Datenteil... a er
prompt..... Er 158
Prozesur sn air 6
Prozedurvariable.. 2
PROZESSEN et nen re ulaieshinirisekimee een 165
pthru....
Puffer 128
DE ensure 39
PUSTIR On ee ee 109
DHUAIa. are
GIET aukaeerenn 1 72,82
BEQUTSO. ana 69
recursive
Register... .. ...158
Registerbelegung ... u ...158
Registeroperationen er ee erinnern 159
Rekursion. nme FR „59, 190
TE VE een 142
rendezvous ..
RERBEAT ...
TESLAT Lin
BESTOLENAGEO) variieren 64
BESTrICH nee Di ne een 155
BOWIENSTOLCANET An er hen een ben nee bee ne nee 41
REBUEN= Bastei een Tee 62
REIEURNBCODELSE AM anne 107
RE BBEMSIKRG Ki neuen ee ee me Re. warnen .39, 47, 191
Retunnstackpolnter.niee nt en ...146
TR aan ...143
RINSDURLETAI IE een enge Men Rare 126
roll.. OT
TODE EN
Indexverzeichnis ER
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ROW: nenne BETT EEE Er ETTLINGEN. 65
RP. .146
ED mn nahe engen near mean Bd
PD: aa 1111111 a a aa 100 5) aaa hl ı1k 5Ä SICH. 39
runtime library
Dinner IE
ee ale Fr ann Een ne ee ine nee ren
save
save-buffers
SAVERLE. aneeaneneernTeRUmmEnSERmTIRRTE En Rn en 102
savesystem. ....88
SaVEeVided...unsmemernenennanenenennemenennnneenennennenenen nennen 64
Scan III 71
Scancode ......uescessenasensnunsennsnnnennnensnennssensennssnennenssnnsnessenssnnsnnssenansssnensersensnennn 69
Schleifenindex su 0 42, 43
Schleifenrumpf .......zcesesesensesenenennennsnnenennenen en ersehen 42
Schleifenvariable . „119
Schrittweite ....... PR IH. 43
STE nstunnaiiieiseieienenigeeenihezungnern 25, 47
Seren. ..198
screen files... rl
Screen-Files
BERN Denkens sangen
SEATch,.n
search order
SER eeeeaennensnnnnnnnenunsnennunsnensennssnnennneunsennsnennensseennennenennnsnennensnennsnnnennen en
SEGMENT aan 3
Segmentäadresse ......ncuesnensusnsussnnennsnensnenennnensnnennnnennenenennensnensnnesnnnnnnnnensnne nen 107
Segmentrezistar nun a dl 9dkUiCCC——— 197
Semaphore ........ ..167
SETPABE nee Br 63
Shadow-Konzept.......... za .16
Shadow-Screens .........
SHOW. rasen
SHOWLOEER nn be IT LIU
N een ran Äeen
singletask &
SKID. Minen Teer nr aheeen
Brenn er erreE
source.
SDAGES umschauen
Spaltennummer..
SPAN .ncccneneneeenenenn
Speicheradressen ...
Stack...
Stacknotation ........
Stackoperationen...
Stackpointer ...........
Standard-Prolog ....
standard! „une
-.208 - Indexverzeichnis
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev, 3.81
SteVEranWeIsUNngeNn ans een er reaeeeeee
Steuerzeichen .........
string literal.....
Stringvariable ...
Stringvergleich ... N:
BIEDFEINBRTBIER ne nn nennen
SIWAD, Messer seen ns ea ee na ae nrene
Synonymdeklaration .
DIE EIER. en errieen EReaimuaäaRe nen
Systemverhalten
ANDPASSEHR nee Eee nn 123
beeinflussen
Taskwechsler..
Tastendruck ...
Teilstrings ..
TENMINAL nun en Men Tresen irre tekeikegen insg testen
MOXtZMienpreterensnue enter nung garten enter Eee Eee
THEN er... szene
unnest.
unravel ..
UNTIL...
up®........
Indexverzeichnis =m2093#=
FORTH-Gesellschaft e.V. PC-volksFORTH83 rev. 3.81
ÜSERANER anne EEE 192
Uservariable.... is 142,-192
DU essen] 33
VAarIabIa uncut ka a Ta alt CKICECEn 114
Vektor ya:
vektorielle Programmausführung sen een 124
Vektorisierfüng..usssesnensenenenennenaneneennenennnen nennen mean nennen een een
Verlassen des volksFORTH ..
WAGe0d. san. En
Videokarte....neneuusesssnenensennenunnennrnnnenensununnnennnernesenennsnssnnnesenannsnsnsnsnnnsenenennnnnn
VIEW anmnan
voc-iNkK..
Vocabularvy ses nn
WORS ummnssceineeenteiinteunnscemeeinn nenne een 15, 26
Vokabular 132
VokabMET-KONZEdE.. nennen nennen ee een 8
Vorwärts-Referenzen.
WOLTTEZISTET uruauussnaanan anna ran aa a0 1 ıctkaıuUrT RL LUAAI
WOTLLYDEN .eeeceenenasessensnnnnsnnnsannnnennennensennennensnnnnnennennensensensnenssnnsnnenn ze
KOT name
Zahleneingabe .
Zähler .............
Zeichenattribut
Zeichenkette....... ae ä
Zeichenketten. u.
ZENENENGEL nen eier
Zeilennummer ....
Zugriffsmethode
=. 210r® Indexverzeichnis