VolksForth/doc/cbm/vf-cbm-380-manual-de.sidecar.txt
Philip Zembrod b03438394a Replace vf-cbm-380-manual-de.pdf with text-annotated version made by OCRmyPDF,
alongside with sidecar.txt file containing the text annotation.
2024-08-01 22:25:11 +02:00

15304 lines
320 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

| | ultraFORTH8S j ic) 1985 bE/ks/re/we FORTH-Gesellschaft ev ]
En I
| ultraFORTH83 rev 3.8 )
| HANDBUCH
für Fommodore
616/116 an. » oe Plus 4
Did 3 X 1128
Handbuch zum ultraFORTH83 rev 3.8
2. Auflage 1.11.1987
Die Autoren haben sich in diesem Handbuch um eine vollständige
und akkurate Darstellung bemüht. Die in diesem Handbuch enthal-
tenen Informationen dienen jedoch allein der Produktbeschrei-
bung und sind nicht als zugesicherte Eigenschaften im Rechts-
sinne aufzufassen. Ewaige Schadensersatzansprüche gegen die
Autoren - gleich aus welchem Rechtsgrund - sind ausgeschlossen,
soweit die Autoren nicht Vorsatz oder grobe Fahrlässigkeit
trifft. 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 Quellen-
angabe sowie Einsendung eines Belegexemplars an die Autoren.
(c) 1985,1986,1987,1988
Claus Vogt, Bernd Pennemann, Klaus Schleisiek, Georg Rehfeld,
Dietrich Weineck - Mitglieder der Forth Gesellschaft e.V.
Unser Dank gilt der gesamten FORTH-Gemeinschaft, insbesondere
Mike Perry, Charles Moore und Henry Laxen.
| ultraFORTH83 ic) 1985 bo/ks/re/ue FORTH- Inhalt Seite 3
Seite
4
Inhalt
E Do bpeiks/re/we
FORTH-Gesellsc
ultraFORTH83
15
15
19
21
21
22
24
25
27
27
27
27
28
43
45
45
46
47
50
51
53
53
55
58
60
61
63
ultraFORTH8I
INHALTSVERZEICHNIS
Teil 1 - Erläuterungen
Prolog : Über das ultraFORTH83 .
Hardware-Anforderungen
Die ersten Schritte in ultraFORTH83
Die nächsten Schritte...
Anpassen der Speicherbelegung
Erstellen eines eigenen Arbeitssystems
Umgang mit den Disketten
Zur Druckerbenutzung auf dem C16
ultraFORTH83 für Kassettenrekorder
Änderungen seit rev. 3.5
Schwer erkennbare Ursachen von System-Crashs
Was tun bei Fehlern ?
1) Dictionarystruktur des ultraFORTH83
1) Struktur der Worte
2) Vokabular-Struktur
2) Die Ausführung von Forth-Worten
1) Aufbau des Adressinterpreters beim 6502
2) Die Funktion des Adressinterpreters
3) Verschiedene Immediate Worte
3) Die Does> - Struktur
4) Vektoren und Deferred Worte
1) deferred Worte
2) >interpret
3) Variablen
4) Vektoren
5) Der Heap
6) Der Multitasker
1) Anwendungsbeispiel : Ein Kochrezept
2) Implementation
2a) Die Memorymap des ultraFORTH83
3) Semaphore und "Lock"
4) Eine Bemerkung bzgl. BLOCK und anderer Dinge
7) Debugging - Techniken
1) Voraussetzungen für die Fehlersuche
2) Der Tracer
3) Stacksicherheit
4) Aufrufgeschichte
5) Der Dekompiler
8) Anpassung des ultraFORTH83 an andere Rechner
ic) 1985 bp/ks/re/we Formızd Inhalt Seite 5]
Seite 6 Inhalt an mn UltraFORTHEI
Teil 2 - Glossare
71 Notation
73 Arithmetik
= */ */mod + - -1 / /mod 0 1 1+ 1- 2 2%
2+ 2- 2/7 3 3+ 4 abs max min mod negate u/mod
umax umin
76 Logik und Vergleiche
0<£ 0<> 0= 0> < = > and case? false not or
true u u> uwithin xor
78 Speicheroperationen
! +1 @ c! c@ cmove cmove> count ctoggle erase
fill move off on pad place
80 32-Bit-Worte
d0= d+ d< dabs dnegate extend m* m/mod ud/mod
um* um/mod
82 Stack
-roll -rot .s 2dup 2drop 2swap ?dup clearstack
depth drop dup nip over pick roll rot s0 swap
sp! sp@ under
84 Returnstack
»r push r> rp! r0O r@ rdepth rdrop rpe@
85 Strings
» # #> #s /string <# accumulate capital
capitalize convert digit? hold nullstring? number
number? scan sign skip
88 Datentypen
s ; Alias Constant Defer Input: Is Output: User
Variable User Vocabulary
9 Dictionary - Worte
' (forget , name allot c, clear dp empty
forget here hide last name> origin reveal save
uallot udp >body >name
93 Vokabular - Worte
also Assembler context current definitions Forth
forth-83 Only Onlyforth seal toss words voc-link
vp
95 Heap - Worte
?head hallot heap heap? |
96 Kontrollstrukturen
+LOOP ?DO ?exit BEGIN bounds DO ELSE execute I
IF J LEAVE LOOP perform REPEAT THEN UNTIL WHILE
ultraFoRTHBZ
ic) 1985 bp/ks/re/ne FOR Inhalt Seite 7]
99 Compiler - Worte
ö Ascii compile Does> immediate Literal
recursive restrict [ ['] [compile]
101 Interpreter - Worte
( +load +thru --) >in >»interpret blk find
interpret load name notfound parse quit source
state thru word ] \ \\ \needs
104 Fehlerbehandlung
(error ?pairs ?stack abort Abort" diskerr Error"
errorhandler warning
105 Sonstiges
"abort "cold '"quit 'restart (quit status bye
cold end-trace noop r# restart scr
108 Massenspeicher
>»drive all-buffers allotbuffer b/blk b/buf bik/drv
block buffer convey copy core? drive drv? empty-
buffers file first flush freebuffer limit offset
prev r/w save-buffers update
111 c64-spezifische Worte
1541r/w ?device bus! bus@ busclose busin businput
busoff busopen busout bustype c64at c64at? c64cr
c64decode c64del c64emit c64expect c64init c6Akey
c64key? c64page c64type con! curoff curon derror?
diskclose diskopen findex getkey i/o index ink-
pot keyboard printable? readsector writesector
L17 Multitasking
's activate lock multitask pass pause rendezvous
singletask sleep stop Task tasks unlock up@ up!
wake
121 Input und Output Worte
#bs #cr #tib -trailing . "ch se Yeiberlcr:sat
at? base bl c/l col cr d. d.r decimal decode
del emit expect hex input key key? list 1/s
output page query row space spaces span
standardi/o stop? tib type u. u.r
126 Nachtrag
Create Create: exit order
127 cC64- und C16-spezifische Worte
(drv (64 (16 C) c64fkeys
128 Tools
cpush endloop nest trace' unnest unbug
Seite 5 Inhalt W am UltraFORTHBE
129 Kassettenversion
\IF (rd .rd T7T>c autoload binary bload bsave c>7
cload commodore compress csave derr? device
expand floppy id" loadramdisk A" ramR/W rd
rdcheck rddel rdnew rduse restore" saveramdisk
store supertape tapeinit
133 Massenspeicher-Utilities
2disk1551 copy2disk copydisk formatdisk savesystem
Teil 3 - Definition der verwendeten Begriffe
136 Entscheidungskriterien
139 Definition der Begriffe
Teil 4 - Editor
149 C64 Full Screen Editor
Anhang
167 Graphik Glossary
175 Der 6502-Assembler
PushA Push0A Push Next xyNext Puta Pop Poptwo
RP UP SP IP W N setup wcmp ram rom sys
181 Abweichungen des ultraFORTH83 von "Starting Forth".
193 Abweichungen des ultraFORTH83 von "Forth Tools and Appli-
cations".
195 Targetcompiler-Worte
197 Meldungen des ultraFORTH83
203 Index der im Handbuch erklärten Forthworte
ultraFoRTN83
ic} 1985 bp/ks/re/me FORTH-G Inhalt | Seite 9]
VERZEICHNIS DER ABBILDUNGEN
Ts Struktur der Worte
16 Das Countfeld
16 Eine Alias-Definitions
18 Struktur einer :-Definition
20 Das Dictionary
22 Beispiel für die Ausführung eines Wortes durch den
Adreßinterpreter
25 Die Does>-Struktur
28 Ein INPUT: - Vektor
43 Ein namenloses Wort
48 Speicherbelegung einer Task
48 Userareas von Tasks
49 MEMORYMAP DES ULTRAFORTH83
149 Editorbildschirm
156 Funktionstastenbelegung beim C64-Editor
[Seite 18 Inhalt E bp/ks/re/we FORTH-Gesellsc ultraFORTH83
ultraFoRTH83
ic} 1988 bp/ks/re/ue
Prolog : über das ultraFORTH83
ultraFORTH83 ist eine Sprache, die in verschiedener Hinsicht
ungewöhnlich ist. Einen ersten Eindruck vom ultraFORTH83 und
von unserem Stolz darüber soll dieser Prolog vermitteln.
ultraFORTH83 braucht nicht geknackt oder geklaut zu werden. Im
Gegenteil, wir hoffen, daß viele Leute das ultraFORTH83 mög-
lichst schnell bekommen und ihrerseits weitergeben.
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 lassen sich bedauerlicherweise ver-
schiedene Anbieter die einfache Adaption des figFORTH an
verschiedene Rechner sehr teuer bezahlen. Hinzu kommt, daß das
im Jahr 1979 erschienene figFORTH heute nicht mehr so aktuell
ist, weil mit der weiten Verbreitung von Forth eine Fülle von
eleganten Konzepten entstanden ist, die teilweise im Forth-
Standard von 1983 Eingang gefunden haben. Daraufhin wurde von
H.Laxen und M.Perry das F83 geschrieben und als Public Domain
verbreitet.
Dieses freie 83-Standard-Forth mit zahlreichen Utilities ist
recht komplex, es wird auch nicht mit Handbuch geliefert.
Insbesondere gibt es keine Version für C64- und Apple-Computer.
Der C64 spielt jedoch in Deutschland eine große Rolle.
Wir haben ein Forth für verschiedene Rechner entwickelt. Das
Ergebnis ist das ultraFORTH83, eines der besten Forthsysteme,
das es gibt.
Nachdem Version 3.5 für den C64 erhältlich war, wurde es auf
andere Rechner (Atari ST, Schneider CPC, CP/M-Computer, IBM PC
und Kompatible) übertragen und weiter entwickelt.
Eine Anpassung an die anderen "kleinen" Commodore-Rechner wie
Cc16, C116 und Plus4 wurde oft vermißt, denn eine andere
einfache, billige und trotzdem gute Sprache für diese Rechner
existiert anscheinend nicht. Tatsächlich gibt es bis jetzt
(November '87) außer dem eingebauten BASIC nur noch drei
Assembler (mit spezifischen Schwächen) und einen BASIC-Compi-
ler. ultraFORTH83 kann diese preiswerten Rechner etwas attrak-
tiver machen. Bei der Entwicklung wurde darauf geachtet, daß
die im C16-System vorhandenen Funktionen zusammen mit ultra-
FORTH83 nutzbar bleiben.
Das Ergebnis:
._ I/O-Routinen und Interrupt-Handling des Betriebssystens
sind integriert
- Kernal/Betriebssystem sind unter ultraFORTH83 voll
nutzbar
= Monitor kann vom ultraFORTH83 aus aufgerufen wer-
den.
= Grafik (bisher nicht nutzbar, ev. möglich)
= Basic (bisher nicht nutzbar, ev. möglich)
- +4-Software (bisher nicht überprüft)
Während der Anpassungsarbeiten wurde auch die Version für den
c64 gründlich überarbeitet und präsentiert sich nun deutlich
verbessert. Stark verbessert wurden u.a. der Tracer und
Seite ii
Erläuterungen ultraFORTH83
FORTH-Gesellsc
Seite _12
SAVESYSTEM . Natürlich sollten die beiden Versionen so ähnlich
wie irgend möglich sein, um die Portabilität und Wartbarkeit zu
verbessern. Das Ergebnis haben Sie vielleicht schon bemerkt: es
gibt nur einen Satz Disketten und nur einen Quelltext für beide
Rechner. Rechnerspezifische Teile konnten in den gemeinsamen
Quelltext integriert werden.
Das ultraFORTH83 enthält auf allen Rechnern : Multitasker, Heap
(für namenlose Worte), Dekompiler, Assembler und Editor. An
vielen Stellen des Systems wurden Zeiger und sog. deferred
Worte benutzt, die eine einfache Umgestaltung des Systens für
verschiedene Gerätekonfigurationen ermöglichen. Besonderes
Augenmerk wurde auf einen extrem schnellen Blockpuffer-Mecha-
nismus gerichtet, damit effiziente Massenspeichermanipulationen
möglich werden.
Für den C64 gibt es außerdem Graphik, Sprites, Turtlegraphik
und eine Menge Demoprogramme, für den C16 eine Kassetten-
schnittstelle mit Schnelllader.
Noch einmal : Ihr dürft und sollt diese Disks an eure Freunde
weitergeben.
Aber wenn sich jemand erdreistet, damit einen Riesenreibach zu
machen, dann werden wir ihn bis an das Ende der Welt und seiner
Tage verfolgen !
Denn: Wir behalten uns die kommerzielle Verwertung des
ultraFORTH83 vor !
Mit diesem Handbuch ist die Unterstützung des ultraFORTH83 noch
nicht zuende. Die VIERTE DIMENSION, Vereinszeitschrift derForth
Gesellschaft e.V. c/o. Rainer Mertins
Antilopenstieg 6a
2000 HAMBURG 54
dient als Plattform.
Wenn euch das ultraFORTH83 gefällt, so schickt uns doch eine
Spende von ca DM 20,- „ denn die Entwicklung des ultraFORTH83
sowie des Handbuchs war teuer ( allein einige hundert DM an
Telefonkosten), und der Preis, den wir verlangen, deckt nur die
Unkosten.
Schickt uns bitte auch Programme, die fertig oder halbfertig
sind, Ideen zum ultraFORTH83, Artikel, die in der Presse
erschienen sind (schreibt selbst welche !) „ kurz: Schickt uns
alles, was entfernt mit dem ultraFORTH83 zu tun.hat.
Und natürlich : Anregungen, Ergänzungen und Fehler im Handbuch
und ultraFORTH83
Für die Autoren des ultraFORTH83 :
Bernd Pennemann, Treitschkestr. 20, 1000 Berlin 41
ultraFORTHEZ Einstieg
ce) 1985 bp/ksyre/ue
Seite 13.1
Hardware-Anforderungen
Das ultraFORTH83 für C16/C64 läuft auf folgenden Rechnern:
c16, C116 mit 16 Kbyte Gar nicht. Sorry !!
Cc16, C116 mit 32 Kbyte Nur mit Diskettenlaufwerk
C16, C116 mit 64 Kbyte oder Plus 4 Mit Diskettenlaufwerk oder
Kasettenrekorder?.
Cc64, SX64 Mit Diskettenlaufwerk, Kas-
settenrekorder nicht auspro-
biert?.
c128 Im cC64 Emulationsmodus mit
Diskettenlaufwerk.
i Die Ursprungsversion des C16 mit 16kB ist nicht ultraFORTH83-
fähig, da allein der FORTH-Kern den Speicher von $1000 bis
$4BOO0O belegen würde.
Der Umbau dieser Rechner auf 64kB kostet im Selbstbau ca.
30DM, fertig gekauft ab 60DM und lohnt sich eigentlich immer.
Eine ROM-Version, die mit den 16 KByte Speicher des cC16
auskäme, befindet sich in der Überlegung. Ein Mäzen, der uns
einen anständigen Arbeitslohn dafür bezahlt, könnte das ganze
sehr beschleunigen.
Die Benutzung eines Diskettenlaufwerkes ist allerdings insbe-
sondere für das Arbeiten mit Forth sehr zu empfehlen.
Einstieg ultraFORTH83
FORTH-Gesellsch
Seite 13,2
Die ersten Schritte in ultraFORTH83
Diese Beispielssitzung soll die ersten Schritte bei der
Benut-
zung des ultraFORTH83 etwas erleichtern.
Starten des Systems
Als erstes sollten Sie Ihren Rechner aus- und wieder einschal-
ten, um ihn in einen definierten Ausgangszustand zu versetzen.
Sollten Sie an einem C16 oder C116 sitzen und nun in der
Einschaltmeldung etwas über so ca. '14000 bytes free' lesen,
müssen wir Sie enttäuschen: Ihr Rechner ist zu klein. ultra-
FORTH83 benötigt mindestens 32 Kbyte. Nähere Informationen
hierzu finden Sie im Kapitel über "Hardware-Anfc.cerungen".
Als nächstes schalten Sie bitte Ihr Floppylaufwerk ein. Falls
Sie kein Floppylaufwerk haben, so müssen Sie sicu „ins beschat-
fen, denn zumindest für die erste Sitzung brauchen Sie eins {wo
wollen Sie denn sonst Ihre Disketten reinschieben, Sie Schlawi-
ner!). Jene Leser und Leserinnen, die später mit Kasset.>n"z-
korder arbeiten möchten, sollten nach dieser Beispielssitzung
nochmal die 'Kassetten-Beispielssitzung' durchexerzieren, bevor
Sie sich auf den mühevollen Weg des Hinüberkopierens der
Quelltexte von den Disketten machen.
Nun wird die erste Diskette eingeschoben. Achten Sie darauf,
daß der Klebestreifen sicher auf der Schreibschutzkerbe klebt.
Das Inhaltsverzeichnis der Diskette wird von BASIC aus mit:
LOAD "$",8
LIST
angezeigt. Sie bekommen nun mehrere Files gelistet, von denen
sie das für Ihren Rechner bestimmte File laden sollten:
LOAD "<filename>",8
Hierbei sei gleich bemerkt, daß das Betriebsystem auf den
anderen drei Diskettenseiten keine Files findet, weil ultra-
FORTH83 seine eigene Diskettenverwaltung benutzt.
Wenn Sie sich das geladene Programm mit LIST anzeigen lassen
würden, erschiene nur eine einzige Zeile auf der 2>1ldschirm.
Aber tun Sie's lieber nicht, denn LIST z:rstört manche
Programme. Geben Sie lieber RUN ein.
Es erscheint jetzt - evtl. na:h einer Demonstration - die
Einschaltmeldung "ultraFORTH83 rev 3.3". Drücken Sie ın paar-
mal <Return> ; das System quittie ** etzt jeden Tasıendruck mit
ok .
Den Befehlsumfang des ultraFORTH83 können Sie sich mit
words <Return>
anzeigen lassen.
ultraFORTH6Z
Einstieg
Erster Einstieg
Als nächstes wird ein Miniprogramm (in
kompiliert. Dazu geben wir ein :
Forth Wort genannt)
: test .” hallo " ; <Return>
Achten Sie bitte darauf, die Zeile unverändert einzugeben.
Insbesondere ist das Leerzeichen zwischen ." und hallo
wichtig!
Das System antwortet bei korrekter Eingabe mit ok
Ihr soeben kompiliertes Wort können Sie jetzt durch Eintippen
seines Namens starten:
test <Return>
Es erscheint hallo ok auf dem Bildschirm. Als nächstes wollen
wir unser Miniprogramm erweitern :
: test BEGIN ." hallo” REPEAT ;
(Den Hinweis, daß <Return> zu drücken ist,
folgenden weg!) Es erscheint der Hinweis TEST exists und dann
ok Beim Ausführen dieses Wortes TEST erscheinen nun
unzählige hallo auf dem Bildschirm und alle Tastatureingaben
werden ignoriert - das System befindet sich in einer Endlos-
Schleife.
Das macht nichts: Am C64 werden jetzt die Tasten <run/stop> und
<restore> gleichzeitig gedrückt (am besten richtig draufrumhäm-
mern), bis das sinnlose hallo verschwunden ist.
Beim C16 wird stattdessen die <stop>-Taste zusammen mit dem
<reset>-Schalter gedrückt. Es meldet sich der Monitor, von dem
aus mit
lasse ich im
G1014
ein Warmstart des ultraFORTH83 ausgeführt werden kann (siehe
hierzu auch RESTART im Glossarteil des Handbuches). Nun
sollte mit WORDS überprüft werden, ob die beiden TEST noch
da sind.
Ein Inhaltsverzeichnis Ihrer Forth-Quelltextdisketten können
Sie sich mit
1 list
ausgeben lassen. Wenn Sie danach eine andere Diskette einlegen,
werden Sie feststellen, daß 1 LIST immer noch das Inhaltsver-
zeichnis der ersten Diskette zeigt . Das liegt daran, daß die
virtuelle Diskettenverwaltung des Forth (auch Blockmechanismus
genannt) einige Blöcke im Speicher vorrätig hält, um die
Diskettenzugriffe zu minimieren. Daher sollten Sie, um Kuddel-
Muddel zu vermeiden, unbedingt vor (!) jedem Diskettenwechsel
£flush
eingeben.
Einstieg ultraFöRTHö3
FORTH-Gesellsch
Seite 13.4
Probieren Sie nun mal
1 edit
Falls der Editor vorhanden ist, werden Sie zunächst aufgefor-
dert, ihr Kürzel (auch stamp genannt) einzugeben. Haben Sie
sich noch keines ausgedacht, so drücken Sie nur <Return>.
Anschließend erscheint der Screen.
Ist der Editor nicht vorhanden, so suchen Sie sich aus den
Forth-Inhaltsverzeichnissen den Editor-Loadscreen heraus. Sie
können ihn dann mit
<screen-Nummer> load
laden, wobei statt <screen-Nummer> die im Inhaltsverzeichnis
angegebene Nummer eingesetzt wird. Ihre Diskettenstation
sollte dann ca. 5 Minuten laufen, während die Nummern der
Screens ausgegeben werden, die gerade geladen werden. Sie
haben also genug Zeit, den folgenden Text in Ruhe zu lesen.
Starten Sie bitte anschließend den Editor, wie es oben besch-
rieben wurde. Sollte die Diskettenstation jedoch gleich wieder
zur Ruhe gekommen und ok ausgegeben worden sein, so haben sie
mit großer Wahrscheinlichkeit die von LIST erzeugte Zeilen-
nummer statt der screen-Nummer genommen. (Zumindest ist das bei
mir immer so.) Sie haben also einen falschen Screen geladen.
Hoffentlich nichts schlimmes.
Nun sollten Sie das Kapitel über den Editor lesen. Falls Sie
verzweifelt versuchen, ihn zu verlassen, dürfen Sie <rın/stop>
drücken.
Laden Sie nun nach Belieben Dinge, die Ihnen wichtig erscheinen
und schauen Sie sich mit dem Editor die Quelltextscree.> an.
Vor allem sollten Sie sich die sogenannten Loadscreens ansehen.
Sie enthalten in der Regel einige wichtige Definitionen, wie
z.B. Vokabulare. Ferner laden sie alle Screens, die zur
Applikation gehören. Man kann also dem Loadscreen ansehen,
welche Teile der Diskette zu dieser Applikation gehören. Am
Ende des Screens sind oft mit \\ (beim C16/64: zwei P£fundzei-
chen) wegkommentierte Forthworte wie SAVE zu finden. SAVE
bewirkt, daß das geladene Programm gegen Löschen geschützt ist.
Der Aufruf schadet nicht und außerdem schützt er vor "“ "wer
erkennbaren Ursachen von System-Crashs".
Das Laden einiger Programme wird mit Meldungen der "”,rm
?! CODE ?! abgebrochen. Sie bringt zum Ausdruck, daß vor dem
Laden der Anwendung erst der Assembler geladen werden muß.
Das ultraFORTH83 wird mit BYE verlassen (siehe Glossarteil).
Die Version für den C16 landet dabei im Monitor; ebenso wie
durch Drücken der <Run/Stop> und <Reset>-Taste. Die "normale"
Benutzung des Monitors verursacht keine Probleme bei einem an-
schließenden Warmstart des ultraFORTH83. Bei alleinigem Drücken
von <Run/Stop> ohne <Reset> gelangt man in das BASIC, von dem
aus mit SYS 4116 ein ultraFORTH83-Warmstart ausgeführt werden
kann. Das BASIC sollten Sie tunlichst nicht weiter benutzen, da
es dieselben Speicherbereiche wie das ultraFORTH83 benutzt und
ultraFORTHBZ Einstieg
12) 1985 bp/ksfrer/ue
der Rechner daher bald abstürzt.
Die Version für den C64 landet nach Eingabe von BYE sofort im
BASIC, von dem aus man mit SYS 2068 wieder in das ultra-
FORTH83 gelangt.
Die nächsten Schritte ..
Anpassen der Speicherbelegung
Es sei für C16/C116/Plus4-Benutzer mit 64 Kbyte RAM erwähnt,
daß ihre ultraFORTH83-Version nur 32 Kbyte Speicher benutzt.
Das prüfen Sie mit
limit u.
(Bitte den Punkt nicht vergessen). Wenn 32768 ausgegeben wird,
werden nur 32 KByte benutzt. Sie ändern das (wenn gewünscht)
mit
$£fd00 ' limit >body ! cold
Für die weitere Veränderung der Speicherbelegung finden sie
einen Screen 'relocate the System' im Lieferumfang, dem sie
auch seine Benutzung entnehmen. Eine Karte der Speicherbelegung
des ultraFORTH83 finden Sie auf Seite 49.
Den genannten Screen benötigen Sie auch, wenn Sie beim Laden
einer Applikation auf die Meldung "Dictionary full" stoßen.
Dann ist der freie Speicher zwischen here und sp@ er-
schöpft, in dem das System neu definierte Worte ablegt. Sie
müssen, um jetzt weiterarbeiten zu können, die zuletzt defi-
nierten Worte vergessen. Erscheint nach Drücken der <Return?-
Taste die Meldung "still full" ,„ so ist der Speicher immer
noch zu voll. Mit dem Wort BUFFERS , das Sie auf den
Quelltextdisketten finden, können Sie die Zahl der Blockpuffer
(unterhalb LIMIT ) verringern und damit gleichzeitig den
freien Platz oberhalb des Dictionary vergrößern. Mit weniger
als ca. 3 Puffern wird das Editieren von Quelltexten jedoch
sehr zeitraubend.
Im nächsten Abschnitt wird beschrieben, wie Sie das so verän-
derte System auf der Diskette speichern.
Erstellen eines eigenen Arbeitssystenms
Im folgenden beschreibe ich, wie Sie ein eigenes Arbeitssystem
(oder als. Spezialfall eine Stand-Alone-Anwendung) erzeugen
können. Damit ist ein System gemeint, das die Programme und
Hilfsmittel enthält, die Sie oft benötigen. Im Prinzip können
Sie diese natürlich nach Bedarf zu dem Kern hinzu kompilieren,
aber schneller geht es natürlich, wenn schon (fast) alles da
ist. Bei der Entwicklung von umfangreichen Anwendungen ist es
außerordentlich zeitsparend, wenn man ein System zur Verfügung
hat, das bereits die Teile der Applikation enthält, die
fehlerfrei sind. Übrigens erfolgen alle Ein-/Ausgaben DEZIMAL.
Wem das nicht gefällt: HEX eingeben !
Die meisten der für die Erzeugung eines Arbeitssystems notwen-
Einstieg ultraFoRTN&Z
reine FORTH-Gesellse
Seite 13.6
digen Schritte kennen Sie schon:
1.) Booten des nackten Forth-Kerns (FileName:' __ ultraFORTH__')
2.) Prüfen der Speicherbelegung. Die Differenz zwischen
here u. und
s0 @ u.
sollte mindestens ca. 1 kByte betragen. Wenn Sie alle
Quellen aller Diskettenseiten laden wollen, sollten Sie
schon mit 5-6 kByte rechnen.
ggf. Ändern der Speicherbelegung. (s. relocate-screen).
Laden der gewünschten Quellen. Da Sie als Anfänger/in
vermutlich noch nicht so recht wissen, was Sie eigentlich
brauchen, hier ein paar Beispiele: Editor, Assembler,
Tracer und evtl. die Kassettenversion.
Falls Sie den Assembler wirklich dauerhaft im System haben
wollen, sollten Sie nicht den 'transienten' Assembler
laden. Dieser verschwindet nämlich beim nächsten SAVE
wieder.
.) Auf jeden Fall müssen Sie SAVESYSTEM laden.
) Falls Sie möchten, daß Ihr zu erstellendes System bei jedem
Laden gleich irgendetwas ausführt (z.B. unzählige Male
mw
in
au
hallo ausdruckt), dann ist es jetzt nötig, "COLD oder
"RESTART umzudefinieren. Das nennt sich dann "Stand-Alone-
Anwendung".
7.) Aufruf von SAVESYSTEM
Als Beispiel wird hier ein Stand-Alone-System vorgestellt, das
permanent hallo druckt:
1.) neu Booten: LOAD "<filename>",8
RUN
2.) und 3.) entfällt da unsere Anwendung kaum Speicher braucht.
4.) Die 'Quelle' geben wir von Hand ein:
: test BEGIN ." hallo" REPEAT ;
5.) Nun SAVESYSTEM laden.
6.) Damit TEST sofort nach dem Laden ausgeführt wird, müssen
wir folgendes eingeben
' test Is 'cold
T:) savesystem hallo-system
Das File hallo-system können Sie jetzt immer laden, wenn Sie
mal wieder jemand brauchen, der hallo zu Ihnen sagt. Sonst
kann es leider nichts.
ultraFoRTHB3
Einstieg
ic) 1986 bp/ks/re/we
Umgang mit den Disketten
Nun sollten Sie - vermutlich haben Sie bereits einige System-
abstürze hinter sich - Sicherheitskopien Ihrer Disketten (Back-
Ups) erstellen. Falls Sie stolze(r) Besitzer(in) von zwei
Diskettenlaufwerken sind, laden Sie dazu am besten das Wort
COPY2DISK . Es braucht allerdings ca. eine halbe Stunde pro
Diskettenseite. Alle anderen kramen in ihren Diskettenkästen
nach dem schnellsten Kopierprogramm. Aber Achtung : Nicht alle
Kopierprogramme kopieren wirklich die ganze Diskette. Es
funktionieren z.B. 'Quickcopy' und 'sd.backup.xx', das bei
neueren Laufwerken von Commodore mitgeliefert wird. Grundsätz-
lich gilt: Wenn das Programm irgendwelche Filenamen wissen
will, ist es schlecht. Wenn es was von "allocated blocks' oder
"whole Disk' erzählt, ist es gut. (Wenn es was von 'wholy'
oder 'hole' Disk spricht, ist sein Englisch schlecht oder es
ist gar kein Kopierprogramm.) Wenn Sie nicht für jede Disket-
tenseite mindestens 4 Diskettenwechsel machen müssen, ist es
entweder ein Superprogramm oder es taugt nichts.
Wenn Sie neue Disketten für das Abspeichern von (Ihren eigenen)
Forth-Screens vorbereiten möchten, sollten Sie das Wort
FORMATDISK (im Lieferumfang enthalten) benutzen. Dadurch ist
Ihre Diskette vor dem Überschreiben mit Files geschützt. So
vorbereitete Disketten dürfen nicht mit dem Validate-Befehl
des Diskettenlaufwerkes aufgeräumt werden.
Zur Druckerbenutzung auf dem C16
Bisher habe ich nur den Treiber VC1526 getestet. Er funktion-
iert mit meinem Citizen-"100 DM"-Drucker, soweit im Zusammen-
hang mit diesem Drucker von "funktionieren" die Rede sein'kann.
Da die meisten mir bekannten C16-Besitzer diesen Drucker ver-
wenden, seien hier ein paar Hinweise zur Verringerung der
erheblichen Störeinstrahlung gegeben:
- Druckerkabel dick mit Aluminiumfolie umwickeln
- Diskettenlaufwerk bei Druckerbenutzung ausschalten und umge-
kehrt.
Andere Druckertreiber, die den Userport des C64 benutzen,
müßten angepaßt werden. Ich habe nichts angepaßt, da ich die
entsprechenden Drucker nicht besitze. Wenn jemand was anpaßt :
Bitte eine Diskette mit den Quellen schicken -- wird in Zukunft
von uns ”""WVeitet.
Seite 13.8
Einstieg ultraFoRTN83
FORTH-Gesellsc
ultraFORTH83 für Kassettenrekorder
Die Kassetten-Version ist für C16/C116 (mit 64kB) und Plus4
entwickelt worden, da Käufer dieser Billigrechner oft vor dem
Kauf des vergleichsweise teuren Diskettenlaufwerks zurück-
schrecken. Trotzdem sei noch einmal darauf hingewiesen, daß
ein Diskettenlaufwerk für ultraFORTH83 dringend zu empfehlen
ist, da einige (viel Speicher beanspruchende) Anwendungsfälle
mit Kassettenrekorder gar nicht zu bearbeiten sind und da vor
allem kleine Fehleingaben leicht zum Zerstören der selbst
geschriebenen - in der Kassetten-Version speicherresidenten -
Quellen führt. Also bitte wenigstens öfter abspeichern! Da
Kassettenrekorder ebenso wie Peripheriegeräte bestimmter Firmen
fürchterlich langsam sind (einer bekannten Heimcomputerfirma
wird nachgesagt, daß man mit ihren Geräten kein Programm
geladen kriegt, bevor es hoffnungslos veraltet ist) haben wir
uns aus Benutzer (innen) freundlichkeit von folgenden Ideen lei-
ten lassen:
- Ein Kassettenschnellader muß her! Supertape
- Wer schon 10 Minuten warten muß, soll wenigstens spazieren
gehen können, statt alle 17 Sekunden eine Taste drücken zu
müssen! Der Ladevorgang kann ebenso wie der Sicherungsvorgang
an einem Stück erfolgen. Diese Automatisierung erfordert
einige Fehler-Prüfungen, die hoffentlich alle funktionieren.
- Die (notgedrungen) speicherresidenten Quelltexte sollen
auch einen normalen Systemabsturz überleben!
- Die wertvollen Quelltexte sollen auch vor Bedienungsfehlern
sicher sein! Entgegen der üblichen Forth-Philosophie werden
viele Bedienungsfehler abgefangen.
Die Kassetten-Version besteht aus 4 Teilen:
- Dem ultraFORTH Kern
- Einer Ramdisk, die im Speicher ein Laufwerk simuliert.
- Einer Kassettenschnittstelle
- Dem Programm Supertape, einem Kassettenschnelllader, der mit
3600 baud ca.10 mal so schnell ist wie die Commodoreroutine.
Es wird von der Zeitschrift "c't" für alle gängigen Rechner
angeboten. Supertape ist bisher leider nur für C16-kompatible
Rechner angepaßt. Wir bedanken uns beim Heise-Verlag für die
freundliche Genehmigung, Supertape weiterzuverbreiten.
Für Hinweise, die zur Verbesserung der Benutzung oder zur
Aufdeckung von Fehlern dienen, wird zwar keine Belohnung
ausgesetzt, aber mein Dank wird Euch auf ewig verfolgen. Da ich
grade beim Danksagen sind, möchte ich mich nochmal bei Doerte
bedanken, die mich mit mit intensiven Gesprächen immer wieder
in die schnöde Realität zurückholte und trotz aller Eifersucht
den Rechner bisher nicht aus dem Fenster warf.
«c3 1985 bp/ks/re/ue | Einstieg h Seite 13.9 |
Eine Beispielssitzung
Sie befinden sich bereits in Forth und haben die
Kassettenversion geladen. Ansonsten laden Sie es erstmal von
Ihrer Diskette. Als erstes müssen wir einen Teil des Speichers
für die Ramdisk räumen. Er muß mindestens ca. 500 bytes lang
sein, empfehlenswert sind jedoch etwa 16 Kbyte. Anschließend
richten wir dort eine Ramdisk ein. Alle Blockzugriffe auf Drive
1 und folgende gehen dann in die Ramdisk.
Beispiel (für den C16) :
$c000 ' limit >body ! cold $c000 bis $FDOO werden
räumt (15 Kbyte)
.. eine Ramdisk erzeugt
ger
limit memtop rdnew
1 drive .. auf Drive 1 geschaltet
1 list .. und ein Screen gelistet.
supertape Aktuelles Gerät setzen
Für den C64 heißen die entsprechenden Adressen z.B. $9000
und $C000 statt $C000 und $FD0OO. Außerdem muß man COMMODORE
statt SUPERTAPE schreiben. Falls später einmal das System
abstürzt, können Sie es einfach neu laden, wobei die Ramdisk
bestehen bleibt. Voraussetzung ist natürlich, daß sie nicht
zerschossen wurde und das neu geladene System sie auch nicht
zerstört. Letzteres passiert z.B., wenn beim neuen System
LIMIT zu groß ist.
Vergleiche hierzu auch: RDUSE "COLD "RESTART
Wenn der Editor geladen ist, geben Sie ein:
2 edit
Sie können jetzt z.B. den folgenden Text eingeben wobei
Commodore-Benutzer/innen statt '\' ein Pfundzeichen eingeben:
\ Mein erster LadeScreen
savesystem erster Versuch"
id" meine kleine Ramdisk"”
saveramdisk
autoload on
savesystem Mit autoload"
saveramdisk
savesystem Mit autoload"
autoload off
saveramdisk
Wenn Sie nun mit <home> in die linke obere Ecke des Bildschirms
gehen und <ctrl> und <L> drücken, wird der beschriebene Screen
auf die Ramdisk zurückgeschrieben und geladen. Nun werden ca. 5
Minuten lang Daten auf dem Rekorder gesichert, wobei
Ausführung jeder der obigen Zeilen der Bildschirm kurz
leuchtet.
nach
auf-
ultraFoRTHB3
Seite 13.10
re/ne FORTH-Gesellzc
Sie haben (wenn alles glatt gegangen ist) auf ihrer Kassette:
erster Ver - ein Forthsystem (z.B. für Systemabstürze)
RD.meine kleine - Die Ramdisk mit dem geschriebenen Screen
Mit autolo - Ein Forthsystem mit Autoload
RD.meine kleine - Die Ramdisk mit dem geschriebenen Screen
Mit autolo - Ein Forthsystem mit Autoload
RD.meine kleine - Die Ramdisk mit dem geschriebenen Screen
Hierzu sei bemerkt:
Da Filenamen nur eine begrenzte Länge haben dürfen, fehlt bei
langen Namen der Rest.
Der Name einer Ramdisk beginnt immer mit "RD.".
- Es ist natürlich nicht nötig alles zweimal abzuspeichern,
aber sicherer.
- Die Forthsysteme bestehen (falls Supertape benutzt wird) im
Grunde genommen aus drei einzelnen Files (s.u.).
Die beiden identischen Systeme "Mit autoload" werden nach dem
Laden während des Kaltstarts die unmittelbar folgende Ramdisk
laden, sofern TAPEINIT als "RESTART installiert ist.
Dies prüfen Sie mit
'restart >body @ >name .name
und erzwingen es mit
tapeinit Is 'restart
Informationen über die aktuelle Ramdisk erhalten Sie mit: .RD
und RDCHECK
Wenn Sie Quelltexte von Diskette auf Kassette kopieren möchten,
benutzen Sie COPY und CONVEY (im Glossar nachlesen!!). Leider
passen nicht sonderlich viele Quelltextscreens in eine Ramdisk.
Pro Diskettenseite müssen Sie schon mit 2-6 Ramdisks & 20 kB
rechnen.
Die Kassettenversion ist neu und noch wenig getestet. Richten
Sie sich daher bitte auf mindestens 2-3 Tage ein, an denen Sie
ein Diskettenlaufwerk zur Verfügung haben sollten, um die
Bedienung erlernen und kopieren zu können. Teilen Sie uns bitte
(möglichst schriftlich) mit, welche Probleme Sie haben. Bevor
Sie völlig verzweifeln, rufen Sie mich lieber an (Claus Vogt
030 - 216 89 38), aber bitte nicht nachts um 3 Uhr...
ultraFoRTHBZ Einstieg
ic) 1985 bp/ks/re/ne
Die Ramdisk
Bei Ausführung von TAPEINIT wird das deferred Wort R/W mit
der Schreib-Leseroutine für die Ramdisks RAMR/W neu besetzt.
Daher müssen für die Benutzung der Ramdisk keine speziellen
Worte benutzt werden, denn Zugriffe auf Blöcke, die sich auf
Drive 1, 2, 3 etc. befinden, werden automatisch auf die Ramdisk
umgeleitet.
Einige Worte der Ramdisk sind im Vokabular RAMDISK .
Beim Lese-Zugriff auf einen nicht vorhandenen Block der Ramdisk
wird ein leerer Block geliefert.
Die Ramdisk benutzt zur Ablage der Blöcke im Speicher ein
komprimierendes Format: aufeinanderfolgende Leerzeichen werden
in ein Zeichen zusammengezogen, das wie folgt berechnet wird :
($7F+AnzahlDerLeerzeichen).
In diesem Format können keine Bytes, die größer als $7F sind,
abgelegt werden. Daher funktioniert die Ramdisk nur mit norma-
len Quelltexten.
Es kann zu Probleme führen, wenn Bytes, die größer als $80
sind, in den Ramdisk-Bereich geschrieben werden. Dann werden
beim nächsten Zugriff auf den beschädigten Block zuviele Bytes
an das System zurück übergeben. Dieses reagiert beim nächsten
FLUSH i.a. mit der Ausgabe no File und beim nächsten EMPTY-
BUFFERS mit Systemzusammenbruch. Ist man auf die Meldung no
File gestossen, so sollte COLD eingeben werden; die Ramdisk
bleibt dabei unverändert.
Zur Korrektur von Fehlern, muß man das Speicherformat der
Ramdisk kennen. Es ist auf den Shadows der Quelltexte beschrie-
ben. Da Fehlerkorrektur sehr mühsam ist, sollte die Ramdisk
lieber oft genug gesichert werden.
Blöcke, die nicht nur normalen Text, sondern auch
Graphikzeichen oder binäre Daten enthalten, müssen mit BINARY
deklariert werden. Sie belegen dann immer 1 kByte im Speicher.
Die Ramdisk ist voll, wenn weniger als 1 kByte frei ist.
ultraFoRTN83
Die Kassettenschnittstelle
Das aktuelle Gerät für alle Load/Save-Operationen kann mit den
folgenden Worten umgeschaltet werden :
COMMODORE SUPERTAPE (nur C16) FLOPPY
Speichern:
SAVESYSTEM sichert ultraFORTH-Bereich
SAVERAMDISK sichert Ramdisk
Laden:
LOADRAMDISK lädt Ramdisk
Ein mit SAVESYSTEM im COMMODORE-Format oder auf FLOPPY
gesichertes System wird wie gewohnt geladen.
Ein mit SAVESYSTEM im SUPERTAPE -Format gesichertes System
wird wie folgt geladen:
- Rechner aus- und wieder einschalten.
- MONITOR aufrufen.
- Mit dem Monitor-Befehl L wird Supertape geladen. Während der
Meldung PRESS PLAY ON TAPE können schon mal bis zu 8 Zeichen
im Voraus eingetippt werden. (z.B. um dann Kaffee trinken zu
gehen.)
- Den (im Filenamen versteckten) Monitorbefehl G#### abschicken
(z.B. mit <cursor-up> <cursor-up> <return)). Es werden zwei
weitere Teile des Systems geladen. Falls ein Ladefehler
aufgetreten ist, wird ein Monitor-Break erzeugt. Ansonsten
wird das ultraFORTH83 automatisch gestartet.
Es besteht die Möglichkeit nach Laden des Systems weitere
Prozesse automatisch auszulösen. Vgl.: AUTOLOAD "'RESTART "COLD
ultraFoRTH83
Einstieg
ic} 1985 bp/ksf/re/ue
(BLOAD (BSAVE
(64 (16 C)
CREATE:
INPUT: OUTPUT:
C6AFKEYS
FREEBUFFERS
(DRV
UNNEST
LIST
'COLD 'RESTART
COLD RESTART
CAPITALIZE
L
K
SAVESYSTEM
Änderungen seit rev. 3.5
wurden aus dem System entfernt.
sind hinzugekommen.
ist hinzugekommen.
wurden geändert, so daß sie jetzt mit ; statt
[ abgeschlossen werden. Damit ist die Syntax
natürlicher geworden und eine zusätzliche Feh-
lerprüfung möglich.
ist für die C16-Version hinzugekommen.
wurde korrigiert.
wurde sichtbar gemacht.
wird statt bisher EXIT von b kompiliert.
Diese Änderung wurde im Zusammenhang mit dem
neuen Tracer notwendig. Der automatische Dekom-
piler wurde ebenfalls entsprechend geändert.
kann jetzt mit jeder Taste angehalten und mit
<run/stop> abgebrochen werden.
wurden freigeräumt. Bisher zeigten diese defer-
red Worte auf Code, der systemabhängige Initia-
lisierungen durchführte.
wurden überarbeitet.
wurde so geändert, daß beide Commodore-Zeichen-
sätze vom System korrekt verarbeitet werden.
im manuellen Dekompiler wurde in
umbenannt, um Verwechselungen mit dem Wort L des
Editors vorzubeugen.
wurde vereinfacht. Es benutzt jetzt nur den
seriellen Bus und nicht mehr das Betriebssysten.
Zur Benutzung mehrerer Laufwerke ergaben sich Änderungen in
INDEX und im Editor.
Der Tracer wurde auf ein neues Konzept umgestellt und dadurch
in der Bedienung deutlich einfacher.
Eine Kassettenversion ist zum Lieferumfang hinzugekommen.
Das System kommt jetzt in DEZIMAL hoch!
Seite 13.13
ForTn-Geseizsch U ItraFoRTH83
Schwer erkennbare Ursachen von System-Crashs
Oft hängen System-Crashs mit Referenzen auf nicht mehr existie-
rende Worte zusammen. Beispiel:
: .blk blk @ ?dup IF . space THEN ;
".bik Is .status
cold
Das deferred Wort .STATUS referenziert jetzt .BLK . Nach
COLD (oder EMPTY oder FORGET .BLK ) ist -BLK gelöscht,
die Referenz existiert weiterhin.
Bei beiden Beispielen arbeitet das System erstmal wie gewohnt
weiter. Erst viel später (nach überschreiben des ehemaligen
Speicherbereichs von .BLK führt der Aufruf von .STATUS zu
undefinierten Reaktionen (i.a. System-Crashs).
Nach Belegung eines deferred Wortes SAVE eingeben
oder
aufpassen.
Was tun bei Fehlern ?
Wenn Ihr denkt, daß Ihr einen Fehler im ultraFORTH gefunden
habt, dann tut bitte folgendes:
- überprüft, ob die Ursache vielleicht in "Schwer erkennbare
Ursachen von Systemcrashs" beschrieben ist.
- Fahrt Euer System nochmal ganz neu hoch, bis Ihr die
minimale Konfiguration erreicht habt, bei der der Fehler noch
auftritt. Schreibt auf, was Ihr ladet.
- Hängt alle Zusatzgeräte ab, die gerade nicht benötigt werden.
- Schickt eine genaue Beschreibung an die Autoren des ultra-
FORTH83. Ggf. über die Forth-Gesellschaft in Hamburg.
- Schreibt dazu, welchen Rechner Ihr habt, (ggf. Zusatzausrüs-
tung) und welche Zusatzgeräte angeschlossen waren.
- Wenn die Programme, die den Fehler verursachten, länger als
ein oder zwei Screens sind, kopiert sie auf eine Diskette
und schickt sie mit.
- Beschreibt den Ladeprozeß der Fehler-Konfiguration so genau
wie möglich (am besten mit einem Lade-Screen, der alles
automatisch hochfährt).
- Schreibt dazu, wo Ihr den Fehler vermutet.
Wir tun unser bestes, aber versprechen können wir nichts.
| WltrarorThög Einstieg
Errata
Leider enthält ein Teil des Handbuches einige Fehler, die erst
bei einer vollstandigen Überarbeitung entfernt werden können:
S.28 Statt
: Input: keyboard c64key c64key? c64decode c6dexpect ["
muß es
"Input: keyboard c64key c64key? c64decode c64expect ;"
heißen. Das gilt analog für die Seiten 29, 36, 89 und 90.
S.63 Die Anschrift ist veraltet.
S.81 In der Erklärung von UM/MOD ist "division over£flow" durch
"/0" zu ersetzen.
s.111 Die Worte (BLOAD und (BSAVE wurden entfernt.
Alle Stellen im Handbuch, wo C64 steht, sind durch C64,C16,C116
und Plus 4 zu ersetzen.
Alle Stellen im Handbuch, wo serieller Bus steht, sind durch
serieller Bus (bzw.beim C16,C116 und Plus4 ggf. der parallele
Floppybus) zu ersetzen.
[Seite 14 | 14 Erläuterungen ==
FORTH-Gezellsc
ultraFORTH83
7 ultraFORTH83 F-— Erläuterungen Seite 15
1) Dictionarystruktur des ultraFÜRTH83
Das Forthsystem besteht aus einem Dictionary von Worten. Die
Struktur der Worte und des Dictionaries soll im folgenden
erläutert werden
1.1) Struktur der Worte
Die Forthworte 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:
a) "block"
Der Nummer des Blocks, in dem das Wort definiert wurde
siehe auch VIEW im Glossar ).
b) "link"
Einer Adresse (Zeiger) , die auf das "Linkfeld" des
nächsten Wortes zeigt.
ce) "count"
Die Länge des Namens dieses Wortes und drei
Markierungsbits.
d) "name"
Der Name selbst.
e) "code"
Einer Adresse (Zeiger) , die auf den Maschinencode zeigt.
der bei Aufruf dieses Wortes ausgeführt wird. Die Adresse
dieses Feldes heißt Kompilationsadresse.
— f) "parameter"
Das Parameterfeld.
Das Dictionary sieht dann so aus
co BGG geooG
Q ö 2 8
[_ Wert _] Wert _] Wort | kart _|]
o & 2 &
26066 20066
Wort 5
[ block ] link ] count | name | code | parameter .,., |
| Seite 16 [ ertäuterungen = FORTH-Gesellsc ultraFORTH83
1.1.1) Countfeld
Das count-Feld enthält die Länge des Namens (
1..31 Zeichen )
und drei Markierungsbits
[restrict | immediate | indirect | Länge |
Bit: 7 6b 5 4.8
Ist das immediate-Bit gesetzt, so wird das entsprechende _
Wort im kompilierenden Zustand unmittelbar ausgeführt,
und nicht ins Dictionary kompiliert (siehe auch
IMMEDIATE im Glossary)
Ist das restrict-Bit gesetzt, so kann das Wort nicht durch
Eingeben vom Terminal ausgeführt werden, sondern kann
nur in anderen Worten kompiliert werden. Gibt man es
dennoch im interpretierenden Zustand ein, so erscheint
die Fehlermeldung "compile only" ( siehe auch RESTRICT
im Glossary )
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 addi
und ergibt folgende Struktur im Speicher (Dictionary)
[ block | link ] $24 | ADDi | pointer |
&
{ andere Worte 3
ouoGd
[block' | link' | $82 | 1+ | code | parameter |
( Bei allen folgenden Bildern werden die Felder block link
count nicht mehr extra dargestellt.)
7 ultraFORTH83 EB -- — - Erläuterungen Seite 17
1.1.2) Name
Der Name besteht normalerweise aus ASCII-Zeichen. Bei der
Eingabe werden Klein- in Großbuchstaben umgewandelt. Daher
druckt WORDS auch nur groß geschriebene 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
eroß 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
1.1.3) Link
Über das link-Feld 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.
1.1.4) Block
Das block-Feld enthält die Nummer des Blocks, in dem das Wort
definiert wurde. Wurde es von der Tastatur aus eingegeben, so
enthält das Feld Null.
1.1.5) Code
Jedes Wort weist auf ein Stück Maschinencode. Die Adresse
dieses Code-Stücks ist im Code-Feld enthalten. Gleiche
Worttypen weisen auf den gleichen Code. Es gibt verschiedene
Worttypen, 2.B. :-Definitionen , Variablen , Constanten ,
Vokabulare usw. Sie haben jeweils ihren eigenen
charakteristischen Code gemeinsam.
Die Adresse des Code-Feldes heißt Kompilationsadesse.
Seite 18 | Erläuterungen E- sr UltraFORTHE3
1.1.6) Parameter
Das Parameterfeld enthält Daten, die vom Typ des Wortes
abhängen.
Beispiele
a) Typ "Constant"
Hier enthält das Paramterfeld des Wortes den Wert der
Konstanten. Der dem Wort zugeordnete Code liest den Inhalt
des Paramterfeldes aus und legt ihn auf den Stack.
b) Typ "Variable"
Das Parameterfeld 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 |
8
. &
E GG &
8 &
[ DUP | code | parameter | ®
ı BEOGGOGCO
&
[ EXIT | code | parameter |
Das Wort : hat den Namen TEST erzeugt.
EXIT wurde durch das Wort ; erzeugt
d) Typ "Code"
Worte vom Typ "Code" werden mit dem Assembler erzeugt.
Hier zeigt das Codefeld in der Regel auf das
Parameterfeld. Dorthin wurde der Maschinencode
assembliert. Codeworte im ultraFORTH können leicht
"umgepatcht" werden, da lediglich die Adresse im Codefeld
auf eine neue (andere) Maschinencodesequenz gesetzt werden
muß.
| ultraFORTH8I3 En Erläuterungen Seite 19
1.2) 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.
1.2.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 auswechselbare 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
gelegentlich den auswechselbaren Teil. Soll ein Vokabular
immer durchsucht werden, so muß es in den festen Teil
befördert 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 Vokabular, in das neue Worte einzutragen sind,
wird durch das Wort DEFINITIONS angegeben. Die
Suchreihenfolge kann man sich mit ORDER ansehen.
Beispiele
Eingabe : ORDER ergibt dann :
Onlyforth FORTH FORTH ONLY FORTH
Editor also EDITOR EDITOR FORTH ONLY FORTH
Assembler ASSEMBLER EDITOR FORTH ONLY FORTH
definitions ForthFORTH EDITOR FORTH ONLY ASSEMBLER
Zu : test ; ASSEMBLER EDITOR FORTH ONLY ASSEMBLER
[Seite 26 Erläuterungen = FORTH-Gesellsc ultraFORTH8S
1.2.2) Struktur des Dictionaries
Der Inhalt eines Vokabulars besteht aus einer Liste von
Worten, die durch ihre link-Felder miteinander verbunden sind.
Es gibt also genauso viele Listen wie Vokabulare. Alle
Vokabulare sind selbst noch einmal über eine Liste verbunden,
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 ® ® >» [Only] >» [Forth] ? ® Hul,_
% J u
[ Mort |
4 > &
Null Hull Hull
ultraFORTHB3
dcr 1905 borkerrerue Erläuterungen sie 1
2) Die Ausführung von Forth-Worten
Der geringe Platzbedarf übersetzter Forth-Worte rührt
wesentlich von der Existenz des Adresseninterpreters her.
Wie aus dem Kapitel 1.1.6 Absatz c) vielleicht klar wird,
besteht eine :-Definition aus dem Codefeld und dem
Parameterfeld. Im Parameterfeld steht eine Folge von Adressen.
Ein Wort wird kompiliert, indem seine Kompilationsadresse dem
Parameterfeld der :-Definition angefügt wird. Eine Ausnahme
bilden die Immediate Worte. Da sie während der Kompilation
ausgeführt werden, können sie dem Parameterfeld der
:-Definition alles mögliche hinzufügen.
Daraus wird klar, daß die meisten Worte innerhalb der
:-Definition nur eine Adresse, also 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.
2.1) Aufbau des Adressinterpreters beim 6502
Der Adressinterpreter besteht aus den folgenden Registern
IP W SP RP
Beim 6502 werden alle Register durch je zwei
Zeropage-Speicherzellen simuliert.
a) IP ist der Instruktionszeiger (englisch : Instruction
Pointer). Er zeigt auf die nächste auszuführende
Instruktion. Das ist beim ultraFORTH33 die
Speicherzelle, die die Kompilationsadresse des nächsten
auszuführenden Wortes enthält.
b) W ist das Wortregister. Es zeigt auf die
Kompilationsadresse des Wortes, das gerade ausgeführt
wird.
— c) SP ist der (Daten-) Stackpointer. Er zeigt auf das
oberste Element des Stacks.
d) RP ist der Returnstackpointer. Er zeigt auf das oberste
Element des Returnstacks.
| Seite 22 Erläuterungen = FORTH-Gesellse ultraFORTH83
2.2) Die Funktion des Adressinterpreters
NEXT ist die Anfangsadresse der Routine, die die Instruktion
ausführt, auf die IP gerade zeist.
Die Routine NEXT ist ei Teil des Adressinterpreters. Zur
Verdeutlichung der Arbeitsweise schreiben wir hier diesen Teil
in High Level:
Variable IP
Variable W
Next IPe e@ W!
2 IP +!
W perform ;
Tatsächlich ist NEXT jedoch eine Maschinencoderoutine, weil
dadurch die Ausführungszeit von Forth-Worten erheblich kürzer
wird. NEXT ist somit die Einsprungadresse einer Routine, die
diejenige Instruktion ausführt, auf die das Register IP zeist.
Ein Wort wird ausgeführt, indem der Code, auf den die
Kompilationsadresse 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.
2x dup + ;
Du 2X. ;
Ein Aufruf von
5 2%
von der Tastatur aus führt zu folgenden Situationen
a | 2. | docol | 2%] . | EXIT |
Do | 5 | | systen |
IP Stack Rstack
Fr ultraFORTH83 B--—— —-—--- Erläuterungen Seite 23
Nach der ersten Ausführung von NEXT bekommt man :
b) | 2. | docol | 2%] „ | EXIT |
7
addri
| 2* ] docol | DUP | + | EXIT | systen
o [5 anel
IP Stack Rstack
nn Nochmalige Ausführung von NEXT ergibt :
( DUP ist ein Wort vom Typ "Code" )
c) | 2% | docol | DUP | + | EXIT | 5 | systen
o 5 addri
Ip Stack Rstack
Nach der nächsten Ausführung von NEXT zeigt der IP auf
EXIT und nach dem darauf folgenden NEXT wird addri
wieder in den IP geladen :
d) | 2. | docol | 2#| . | EXIT |
2 [_18 | [system ]
IP .. Stack Rstack
e) 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 Textinterpreter zurück. Dessen Rückkehradresse
wird durch system angedeutet. Damit ist die Ausführung
von 2. beendet.
[Seite 24 Erläuterungen = Formeserenst UltraFORTHBS
2.3) Verschiedene Immediate Worte
In diesem Abschnitt werden Beispiele für immediate Worte
angegeben, die mehr als nur eine Adresse kompilieren.
a) Zeichenketten, die durch " abgeschlossen werden,
liegen als counted Strings im Dictionary vor.
Beispiel: abort" Test"
, liefert : ! (ABORT" ! 04! Tieıs'ttı
b) Einige Kontrollstrukturen kompilieren ?BRANCH oder
BRANCH , denen ein Offset mit 16 Bit Länge folgt.
Beispiel: 0< IF swap THEN -
liefert : ı 0< 1 ?BRANCH ı 4 | SWAP ı - ı
Beispiel: BEGIN ?dup WHILE @ REPEAT
liefert : ı ?DUP ; ?BRANCH ı 8 ı @ ı BRANCH | -10 ı
c) Ebenso fügen DO und ?DO einen Offset hinter das von
ihnen kompilierte Wort (DO bzw. (?DO . Mit dem
Decompiler können Sie sich eigene Beispiele anschauen.
d) Zahlen werden in das Wort LIT oder CLIT , gefolgt
von einem 16- oder 8-Bit Wert, kompiliert.
Beispiel: [ hex ] 8 1000
liefert : ı CLIT :ı $08 ı LIT ı $1000 ı
N ultraFORTHB3 Erläuterungen sie 51
3) Die Does>-Struktur
Die Struktur von Worten, die mit CREATE .. DOES> erzeugt
wurden, soll anhand eines Beispiels erläutert werden.
Das Beispielprogramm lautet :
Constant Create ,„ Does> @ ;
3 Constant drei
Der erzeugte Code sieht folgendermaßen aus:
Der jmp-Befehl tritt
bei 6502-Systemen
auf und wird bei
anderen Rechnern
sinngemäß ersetzt.
| DREI | code | 8883
&
PP DRDRDDH
| CONSTANT | docol | Create | , |] C;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
nn Stack und führt die auf jmp dodoes> folgende Sequenz von
Worten aus. ( Man beachte die Ähnlichkeit zu :-Definitionen).
Diese Sequenz besteht aus @ EXIT . Der Inhalt des
Parameterfeldes von DREI wird damit auf den Stack gebracht.
Der Aufruf von DREI liefert also tatsächlich 0003.
Statt des jmp dodoes> und der Sequenz von Forthworten 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.
[Seite 26 | Erläuterungen =
FORTH-Gesellsıc
ultraFORTH83
u ultraFORTH83 F.-— Erläuterungen Seite 77]
4) Vektoren und Deferred Worte
Das ultraFORTH83 besitzt eine Reihe von Strukturen, die dazu
dienen, das Verhalten des Systems zu ändern.
4.1) deferred Worte
Sie werden durch das Wort DEFER erzeugt. Im System sind
bereits folgende deferred Worte vorhanden:
en R/W COLD RESTART ABORT QUIT NOTFOUND .STATUS
DISKERR
Um sie zu ändern, benutzt man die Phrase:
<name> Is <namex>
Hierbei ist <namex> ein durch DEFER erzeugtes Wort und
<name> der Name des Wortes, das in Zukunft bei Aufruf von
<namex> ausgeführt wird. «
Wird <namex> ausgeführt bevor es mit IS winitialisiert wurde,
so erscheint die Meldung "Crash" auf dem Bildschirm.
Anwendungsmöglichkeiten von deferred Worten
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 gefunden wurden, anschließend in einer
Disk-Directory suchen lassen oder automatisch als
Vorwärtsreferenz vermerken.
Ändert man COLD , so kann man die Einschaltmeldung des
ultraFORTH83 unterdrücken und stattdessen ein Anwenderprogramm
starten, ohne daß Eingaben von der Tastatur aus erforderlich
sind ("Turnkey-Applikationen").
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.
4.2) >interpret
Dieses Wort ist ein spezielles deferred Wort, das für die
Umschaltung des Textinterpreters in den Kompilationszustand
und zurück benutzt wird.
4.3) Variablen:
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 der 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.
| Seite 28 Erläuterungen = in ultraFORTH83
4.4) Vektoren
Das ultraFORTH83 benutzt die indirekten Vektoren INPUT und
OUTPUT. Die Funktionsweise der sich daraus ergebenden
Strukturen soll am Bespiel 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 =
Parameterfeldadresse in die Uservariable INPUT . Von nun an
führen die Inputworte die ihnen so zugewiesenen Worte aus.
KEY führt also <NAMEl> aus usw...
Das Beispiel KEY? soll dieses Prinzip verdeutlichen:
:. key? input @ 2+ perform ;
Tatsächlich wurde KEY? im System ebenso wie die anderen
Inputworte durch das nicht mehr sichtbare definierende Wort
IN: erzeugt.
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.
Mit der Input/Output-Vektorisierung kann man 2.B. mit einem
Schlag die Eingabe von der Tastatur auf ein Modem umschalten.
Ein Beispiel für einen Inputvektor, der die Eingabe von der
Tastatur holt
Input: keyboard cb64key c64key? c64decode c64expect [
keyboard
ergibt :
input | pointer |
&
BSD Dmd
%
| KEYBOARD | code | c6dkey | c6dkey? | c6ddecode | chdexpect |
Sp 2 2 ir
ausgeführt von: key key? decode expect
u ultraFORTH83 re Erläuterungen sie
Die Druckeranpassung
Alle Ausgabebefehle (EMIT, TYPE, SPACE, etc) sind im
ultraFORTH83 vektorisiert, d. h. bei ihrem Aufruf wird die
Codeadresse eines zugehoerigen Befehls aus einer Tabelle ent-
nommen und ausgefuehrt. Im System enthalten ist eine Tabelle
mit Namen DISPLAY , die fuer die Ausgabe auf das Bildschirm-
Terminal sorgt. Dieses Verfahren bietet entscheidende Vortei-
le:
- Mit einer neuen Tabelle koennen alle Ausgaben auf ein
— anderes Geraet (2. B. einen Drucker) geleitet werden,
ohne die Ausgabebefehle selbst aendern zu muessen.
- Mit einem Wort ( DISPLAY , PRINTER ) kann das gesamte
Ausgabeverhalten geaendert werden. Gibt man 2. B. ein:
PRINTER 1 LIST DISPLAY
wird Screen 1 auf einen Drucker ausgegeben, anschliessend
wieder auf den Bildschirm zurueckgeschaltet. Man braucht
also kein neues Wort PRINTERLIST zu definieren.
Eine neue Tabelle wird mit dem Wort OUTPUT: erzeugt.
OUTPUT: CREATE ] DOES> OUTPUT! ;
OUTPUT: erwartet eine Liste von Ausgabeworten, die mit [ ab-
geschlossen werden muss. Beispiel:
OUTPUT: >PRINTER
PEMIT PCR PTYPE PDEL PPAGE PAT PAT? [
Damit wird eine neue Tabelle mit dem Namen >PRINTER ange-
legt. Beim spaeteren Aufruf von >PRINTER wird die Adresse
dieser Tabelle in die Uservariable OUTPUT geschrieben. Ab so-
fort fuehrt EMIT ein PEMIT aus, TYPE ein PTYPE usw. Die Rei-
henfolge der Worte nach OUTPUT: userEMIT userCR userTYPE
userDEL userPAGE userAT userAT? muss eingehalten werden.
Der folgende Quaeltext enthaelt die Anpassung fuer einen
epson-Drucker RX80 am C64, und zwar sowohl mit Interface
(ueber den seriellen Bus) als auch ohne. Im letzten Fall
wird eine centronics-Schnittstelle am Userport erzeugt. Die-
se Anpassung laeuft ohne Aenderungen mit allen uns bekannten
Druckern mit centronics-Schnittstelle, lediglich die Befehle
fuer die Steuercodes muessen gegebenenfalls angepasst wer-
den. °
Im Loadscreen (#40) muessen die Worte (s und (u wegkommen-
tiert werden, je nachdem, ob man ueber den seriellen Bus
oder den Userport drucken will. Zusaetzlich zu den reinen
Ausgaberoutinen (Screens 45 und 46) sind eine Reihe nuetz-
licher Worte enthalten, mit denen die Druckersteuerung sehr
komfortabel vorgenommen werden kann. Das Wort PTHRU ermoeg-
licht den Ausdruck von FORTH- Quelltexten in komprimierter
Form (6 Screens pro Seite), DOKUMENT erlaubt die uebersicht-
liche Darstellung von Screen und zugehoerigem Shadow neben-
einander.
[Seite 30 | 36 Erläuterungen = mad ultraFORTH83
LO
\ printer loadscreen 273jul8d5öre)
PFerebere
oT PODHrONEUNLWVPRSOSHUPUNMDMO
YBEgnaWPooaosnupummOo
Onlyforth hex
Vocabulary Print
Print definitions also
Create Prter 2 allot ( Semaphor)
Prter unlock
) ; immediate
(u ; immediate \ for user-port
: (s [compile] ( ; immediate
\: (s ; immediate \ for serial bus
\: (u [compile] ( ; immediate
(s 1 +tload )
02 OA +tthru
Onlyforth
clear
41
\ Buffer for the ugly SerBus 28julö5re)
100 ;ı Constant buflen
ı Variable Prbuf buflen allot Prbuf
i.2,2buf (,char:--)
Prbuf count + c! 1 Prbuf +! ;
ı 2 full? (--£) Prbuf c@ buflen
Ilias BDÜE zil-rc)
Prbuf count -trailing
4 O0 busout bustype busoff Prbuf off
p! (char --)
pause >r
r@ 0OC ( Formfeed ) =
IF r> >buf .buf exit THEN
r@ OA ( Linefeed ) =
r@ OD ( CarReturn ) = or full? or
IF .buf THEN r> >buf ;
off
3 ultraFORTHBZ ich 1985 borks/re/ue Erläuterungen
setzt order auf FORTH FORTH ONLY FORTH
fuer multitasking
Centronics-Schnittstelle ueber User-Port
(s Text bis ) wird ueberlesen
serielle Schnittstelle (wegkommentiert)
(u Text bis ) wird ueberlesen
lade den naechsten Screen nur fuer
seriellen Bus
unbrauchbare Koepfe weg
41
Beim seriellen Bus ist die Ausgabe jedes
einzelnen Zeichens zu langsam
Buffer fuer Zeichen zum Drucker
ein Zeichen zum Buffer hinzufuegen
Buffer voll?
Buffer ausdrucken und leeren
Hauptausgaberoutine fuer seriellen Bus
Zeichen merken
ist es ein Formfeed?
3a, Buffer ausdrucken incl. Formfeed
ist es ein Linefeed?
oder ein CR oder ist der Buffer voll?
ja, Buffer ausdrucken, CR/LF merken
[Seite _32 | 32 | Erläuterungen - ran UltraFORTH8S
12
0 \ p! etrl: ESC esc: 28jul8ö5re)
1
2 (u
5 p! \ char --
4 0ODD01 c! ODDOO dup c@ 2dup
5 4 or swap c! OFB and swap c!
6 BEGIN pause ODDOD c@ 10 and UNTIL ;
7 )
8
9 ı x etrl: (8b --) Create c,
A does> ( --) ce p!;
B
C 07 ctrl: BEL ı TE ctrl: DEL
D ı OD etrl: CRET ı 1B ctrl: ESC
E 0A ctrl: LF OC ctrl: FF
F j
10 | esc: 8b —) Create c,
14 does> \i --) ESC c@ p! ;
12
13 30 esc: 1/8" 31 esc: 1/10"
14 32 esc: 1/6”
15 54 esc: suoff
16 4E esc: +jump 4F esc: -jump
Lt
18
13
0 \ printer controls 28Jjulö5re)
1
2 ı : ESC2 ESC p!p!
3
4 gorlitz ( 8b --) BL ESC2 ;
5
6 3 ESC"I" (>86 =) 21 ESC2 ;
7
8 ! Variable Modus Modus off
9
A on: ( 8b --) Create c,
B does> ( --
C c@ Modus c@ or dup Modus c! ESC"!" ;
D
E ı 3 8fE: ( 8b --) Create OFF xor c,
F does> ( --) e
10 c@ Modus c@ and dup Modus ce! ESC"!" ;
11
12 10 on: +tdark 10 off: -dark
13 20 on: +wide 20 off: -wide
14 40 on: +tcursiv 40 off: -cursiv
15 80 on: +tunder 80 off: -under
16 ı 1 on: (12cpi
LT ı 4 on: (17cpi 5 off: 10cpi
18
ultraFORTHBIE Erläuterungen sie
Hauptausgaberoutine fuer Centronics
Zeichen auf Port , Strobe-Flanke
ausgeben
wartet bis Busy-Signal zurueckgenommen
wird
gibt Steuerzeichen an Drucker
Steuerzeichen fuer den Drucker
in hexadezimaler Darstellung
gegebenenfalls anpassen |!
gibt Escape-Sequenzen an Drucker
Zeilenabstand in Zoll
Superscript und Subscript ausschalten
Perforation ueberspringen ein/aus
Escape + 2 Zeichen
nur fuer Goerlitz-Interface
spezieller Epson-Steuermodus
Kopie des Drucker-Steuer-Registers
schaltet Bit in Steuer-Register ein
schaltet Bit in Steuer-Register aus
Diese Steuercodes muessen fuer andere
Drucker mit Hilfe von ctrl:, esc: und
ESC2 umgeschrieben werden
Zeichenbreite in characters per inch
eventuell durch Elite, Pica und Compress
ersetzen
(Seite 34 | Erläuterungen I
Ye dawhPeoo-nunmune ©
Helgallpoam-nupwm-QO
FORTH-Gesellsc
14
\ printer controls
ultraFORTH83
28Jjul85re)
l2cpi iüepi (12epi ;
17cpi 10cpi (17cpi ;
super 0 53 ESC2 ;
sub 1 53 ESC2 ;
lines ( #lines --) 43: ESC2 ;
"long ( inches --) O lines p! ;
american D 52 ESC2 5;
german 2 52 unca ;
: prinit
(s Ascii x gorlitz Ascii b gorlitza
\ Epson
Ascii e gorlitz
Ascii 2 gorlitz
Bseii t gorlitz
Ascii 1 gorlitz
u OFF DDO
oDDO2 d
Variable
normal
Modus
176"
off
oc
pri
c})a (
yascii @ I
dup 41 5B
dup Ci DB
dup DC EO
THEN ;
Variable
Variable
pemit
per GC
pdel
ppage
: pat
over
sol
up c@
»ascii >ascii
»ascii on
i10cpi
"long CRET ;
15
nter interface
8b0 -- 8b1)
F
uwithin IF 20
uwithin IF T7F
uwithin IF 0AO
pcol peol off
prow prow off
1 pcol
1 prow
=1L pool F!
e>a p!
RET LF
DEL
FF 0 prow |!
( zeile spalte
prow @ < IF ppage
4 or swap c!
on
american
or
and
xor
+1
+!
,
1
T
swap prow @ - 0 ?DO pcr LOOP
dup pcol < IF CRET pcol off
pcol @ - spaces ;
pat? prow @ pcol ®
ptype ( adr count --)
bounds ?DO I c® c>a p!
s
dup pcol +!
LOOP ;
)
suof
2
O8sep3ö5re)
exit THEN
exit THEN
THEN
0 pc
OO pcol !
HEN
oı \
THEN
| ultraFORTH83 ic} 1955 bp/ks/re/we
gegebenenfalls aendern
Aufruf 2.B.mit 66 lines
Aufruf 2.B mit 11 "long
Zeichensaetze, beliebig erweieterbar
Initialisierung ...
fuer Goerlitz-Interface
fuer Centronics: Port B auf Ausgabe
PA2 auf Ausgabe fuer Strobe
Flag fuer Zeichen-Umwandlung
schaltet Drucker mit Standardwerten ein
wandelt Commodores Special-Ascii in
ordinaeres ASCII
Routinen zur Druckerausgabe Befehl
ein Zeichen auf Drucker emit
CR und LF auf Drucker er
ein Zeichen loeschen (?!) del
Formfeed ausgeben page
Drucker auf zeile und spalte at
positionieren, wenn noetig,
neue Seite
Position feststellen at?
Zeichenkette ausgeben type
Erläuterungen sie]
| Seite 36 [ ertäuterungen = FORTH-Gesellrc ultraFORTH83
16
0 \ print pl 28julö5re)
1
2 ı Output: >printer
3 pemit pcr ptype pdel ppage pat pat? [
4
5
6
7 bemit dup c64emit pemit ;
8 ber c64cr per
9 btype 2dup c64type ptype ;
A bdel c64del pdel ;
B bpage c64page ppase ;
C bat 2dup c64at pat ;
D
E ! Qutput: >both
F bemit bcr btype bdel bpage bat pat? [
10
11 Forth definitions
12
13 : Printer
14 normal (u prinit ) >printer ;
15 : Both
16 normal >both ;
11
18
47
0 \ 2sers nsers thru ks 28Jjul8ö5re)
1
a Forth definitions
3
4 I: 2scrs ( blki1 blk2 --)
5 er LF 17cpi +twide tdark 15 spaces
6 over 3 .r 13 spaces dup 3 .r
7 -dark -wide cr b/blk 0 DO
8 er I c/l1/ 15 .r 4 spaces
9 over block I + C/L 1- type 5 spaces
A dup block I + GC/L 1- -trailing type
B G/L +LOOP 2Zdrop cr,
GC
D I: nsers ( bikl'n --ublk2) 2dup
E bounds DO I over I + 2scrs LOOP + ;
F
10 i-pthrurri £2roNMtOn>>)
41 Prter lock Output push Printer 1/8"
y2 1+ over - 1+ -2 and 6 /mod
13 ?dup IF swap >r
14 0 DO 3 nscers 2+ 1+ page LOOP r> THEN
15 ?dup IF 1+ 2/ nscrs page THEN drop
16 Prter unlock ;
17 °
u ultraFORTH83 F- —— —
erzeugt die Ausgabetabelle >printer
Routinen fuer Drucker
und Bildschirm gleichzeitig (both)
Ausgabe erfolgt zuerst auf Bildschirm
( Routinen von DISPLAY )
dann auf Drucker
( Routinen von >PRINTER )
erzeugt die Ausgabetabelle >both
Worte sind von Forth aus zugaenglich
legt Ausgabe auf Drucker
legt Ausgabe auf Drucker und Bildschirm
gibt 2 Screens nebeneinander aus
Screennummer in Fettschrift und 17cpi
formatierte Ausgabe der beiden Screens
gibt die Screens so aus: 1 3
2 4
gibt die Screens von from bis to aus
Ausgabegeraet merken und Printer ein
errechnet Druckposition der einzelnen
Screens und gibt sie nach obigem Muster
aus
Erläuterungen
[Seite 38 [ertäuterungen = FORTH-Gesellsc ultraFORTH83
45
\ Printing with shadows 28julöß5re)
Forth definitions
ı 2: 2scrs ( blki1 blk2 --)
er LF 17cpi +twide +dark 15 spaces
dup 3.r
-dark -wide cr b/blk 0 DO
er Ic/l1 / 15 ..r 4 spaces
dup block I + CG/L 1- type 5 spaces
over block I + C/L 1- -trailing type
C/L +LOOP 2drop cr;
I ı nsers ( blki n -- bIk2)
0 DO dup [ Editor ] shadow @ 2dup
u> IF negate THEN
+ over 2scrs 1+ LOOP ;
dokument ( from to --)
Prter lock Output push Printer
1/8" 1+ over - 3 /mod
?dup IF swap >r
0 DO 3 nscrs page LOOP r> THEN
?dup IF nscrs page THEN drop
Prter unlock ;
Prrerkerrerer
OQNDOTPUDH-HOHNFIUHNAW PODIUM PUMMO
49
0 \ 2sers nscrs thru ks 28Jjulö5re).
a
2 Forth definitions 40 ı Constant C/L
3
4 I: 2scrs ( blki1 bIk2 --)
5 pcr LF LF 10cpi +tdark 012 spaces
6 over 3 .r 020 spaces dup 3 .r
7 er 17cpi -dark
8 010 C/L * 0 DO cr over block I + C/L
8 6 spaces type 2 spaces
A dup block I + CG/L -trailing type
B C/L +tLOOP 2drop cr ;
G
D I oz nscers ( blki n -- bI1k2) under 0
E DO 2dup dup rot + 2scrs 1+ LOOP nip ;
F
10 : 64pthru ( from to --)
11 Prter lock >ascii push >ascii off
12 Output push Printer
13 1/6" 1+ over - 1+ -2 and 6 /mod
14 ?dup IF swap >r
LE 0 DO 3 nscers 2+ 1+ page LOOP r> THEN
16 ?dup IF 1+ 2/ nscrs page THEN drop
17 Prter unlock ;
E ultraFoRTH83 Erläuterungen sie 5]
wie 2scrs (mit Shadow)
wie nscrs (mit Shadow)
screen Shadow
scr+tl1 Shtl
wie pthru (mit Shadow)
Dasselbe nochmal fuer Standard-Forth
Screens mit 16 Zeilen zu 64 Zeichen
Siehe oben
Wie pthru fuer Standard-Screens
[Seite 48 Erläuterungen = FORTH-Gesellsc ultraFORTH83
4A
oO \ pfindex 11nov8ö5re)
1
2 Onlyforth Print also
3
4 pfindex ( from to --)
5 Prter lock Printer 0C "long
6 +jump findex cr page -jump
7 Prter uniock display ;
8
9
A
B
C
D
E
F
10
11
12
13
14
15
16
17
18
\ Printspool 28Jjulö5bre)
\needs tasks .( Tasker?!) abort
100 100 Task Printspool
spool ( from to --)
Printspool 2 pass
pthru
stop ;
endspool ( --)
Printspool activate
stop ;
Prrberpmf
SU POND-FOHBHEUMHPRO SU PUMHMO
a ultraFoRTH83 F- —— Erläuterungen sis
1A
Ein schnelles Index auf den Drucker
12" Papierlaenge
Perforation ueberspringen
4B
Drucken im Untergrund
Der Tasker wird gebraucht
Der Arbeitsbereich der Task wird erzeugt
Hintergrund-Druck ein
von/bis werden an die Task gegeben
beim naechsten PAUSE fuehrt die
Task pthru aus und legt sich dann
schlafen.
Hintergrund-Druck abbrechen
die Task wird nur aktiviert,
damit sie sich sofort wieder schlafen
legt.
FORTH-Gesellsc
[Seite 42 | Erläuterungen ==
ultraFORTH83
u ultraFORTH83 B- ——- Erläuterungen se
5) Der Heap
Eine der ungewöhnlichen und fortschrittlichen Konzepte des
ultraFORTH33 besteht in der Möglichkeit, Namen von Worten zu
entfernen, ohne den Rumpf zu vernichten.
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 aueh nicht mehr
im Dictionary auf. Man kann dem Quelltext sofort ansehen, 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 die Lesbarkeit gefördert.
Namen, die später eliminiert werden sollen, werden durch das
Wort ! gekennzeichnet. Das Wort ! muß unmittelbar vor dem
Wort stehen, das den zu eliminierenden Namen erzeugt. Der so
erzeugte Name wird in einem Speicherbereich abgelegt, der Heap
heißt. Der Heap kann später mit dem Wort CLEAR gelöscht
werden. Dann sind natürlich auch alle Namen, die sich im Heap
befanden, verschwunden.
Beispiel: ! Variable sum
1 sum !
ergibt
in heap! im Dictionary!
[SuM] nointer | code 8881
5250686805
Es werden weitere Worte definiert und dann CLEAR ausgeführt
clearsum ( -- ) 0 sum !;
add (n--) sum +! ;
— show (--) sum @ . ;
clear
liefert die Worte CLEARSUM ADD SHOW , während der Name
SUM durch CLEAR entfernt wurde; das Codefeld und der Wert
0001 existieren jedoch noch. (Das Beispiel solleine Art
Taschenrechner darstellen.)
Für C64-Benutzer ist zu beachten, daß das Zeichen | mit der
Tastenkombination " CBM_ - " erreicht wird und wie ein halber
punktierter Cursor aussieht.
FORTH-Gesellsc
[Seite 44 | Erläuterungen =
ultraFORTH83
ultraFORTH83
«cı 19884 bp/ks/re/me
6) Der Multitasker
Das ultraFORTH83 besitzt einen recht einfachen, aber leistungs-
fähigen Multitasker. Er ermöglicht die Konstruktion von
Druckerspoolern, Uhren, Zählern und anderen einfachen Tasks.
Als Beispiel soll gezeigt werden, wie man einen einfachen
Druckerspooler konstruiert. Dieser Spooler ist in verbesserter
Form auch im Quelltext des Multitaskers enthalten, hier wird er
aus didaktischen Gründen möglichst simpel- gehalten.
6.1) Anwendungsbeispiel: Ein Kochrezept
Das Programm für einen Druckerspooler lautet:
$80 $100 Task background
: spool background activate 1 100 pthru stop ;
multitask spool
Normalerweise würde PTHRU den Rechner "lahmlegen",
Screens von 1 bis 100 ausgedruckt worden sind. Bei Aufruf von
SPOOL ist das nicht so; der Rechner kann sofort weitere
Eingaben verarbeiten. Damit alles richtig funktioniert, muß
PTHRU allerdings einige Voraussetzungen erfüllen, die dieses
Kapitel erklären will.
Das Wort TASK ist ein definierendes Wort, das eine Task
erzeugt. Die Task besitzt übrigens Userarea, Stack, Returnstack
und Dictionary unabhängig von der sog. Konsolen- oder Main-
Task (siehe Bild). Im Beispiel ist $80 die Länge des reservier-
ten Speicherbereichs für Returnstack und Userarea ("rlen" im
Bild), $100 die Länge für Stack und Dictionary ("slen" im
Bild), jeweils in Bytes. Der Name der Task ist in diesem Fall
BACKGROUND . Die neue Task tut nichts, bis sie aufgeweckt
wird. Das geschieht durch das Wort SPOOL .
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 abgeschal-
tet. Dann wird nur noch die gerade aktive Task ausgeführt.
bis die
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 weiter-
gehen, so tippt man BACKGROUND WAKE ein.
Erläuterungen ultraFORTHBZ
re/ne FORTH-Gesellsc
Seite_46
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 -- )
background 2 pass pthru stop ;
Die Phrase BACKGROUND 2 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 100 auszudrucken, tippt man
jetzt ein:
1 100 newspool
Es ist klar, daß BACKGROUND ACTIVATE gerade der Phrase
BACKGROUND O0 PASS entspricht.
6.2) 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 verfü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 von Interpreterpointer (IP) , Return-
stackpointer (RP) und des Stackpointers (SP).
Der Taskwechsler besteht aus einer geschlossenen Schleife
(siehe Bild). Jede Task enthält einen Maschinencodesprung auf
die nächste Task ("jmp XXXX" im Bild), gefolgt von der
Aufweckprozedur ("jsr (wake" im Bild). Unter der Adresse, auf
die der Sprungbefehl zielt, befinden sich die entsprechenden
Instruktionen der nächsten Task. Ist diese Task gestoppt, so
wird dort ebenfalls ein Maschinencodesprung zur nächsten Task
ausgeführt. Ist die Task dagegen aktiv, so ist der Sprung durch
den (nichts bewirkenden) BIT-Befehl ersetzt worden. Darauf
folgt der Aufruf der Aufweckprozedur. Diese Prozedur lädt den
Zustand der Task (bestehend aus SP „a RP und IP) und setzt den
Userpointer (UP), so daß er auf diese Task zeigt.
SINGLETASK ändert nun PAUSE so, daß überhaupt kein Taskwech-
sel 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. STOP entspricht PAUSE ,„ jedoch mit dem Unterschied,
daß die leere Anweisung durch einen Sprungbefehl ersetzt wird.
ultraFoRTH63
Das System unterstützt den Multitasker,
Ein/Ausgabeoperationen wie KEY ,„ TYPE und BLOCK usw.
ausführt. Häufig reicht das schon aus,
der Druckerspooler) gleichmäßig arbeitet.
Erläuterungen
ic)
indem es während vieler
PAUSE
damit eine Task (z.B.
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 Einchränkung
vereinfacht, daß nur die Konsolentask Eingabetext interpretie-
ren bzw. kompilieren kann. Es gibt z.B. nur eine Suchreihen-
folge, die im Prinzip für alle Tasks gilt. Da aber nur die
Konsolentask von ihr Gebrauch macht, ist das nicht weiter
störend.
Es ist übrigens möglich, aktive Tasks mit FORGET
vergessen. Das ist eine Eigenschaft, die nicht viele
aufweisen!
USW; zu
Systeme
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 zugehö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.
6.2a) Die Memorymap des ultraFORTH83
Die Memorymap des ultraFORTH83 finden Sie auf S.49.
Der vom wultraFORTH83 benutzte Speicherbereich reicht von
ORIGIN bis LIMIT . Unterhalb von ORIGIN befinden sich die
Systemvariablen, der Bildschirmspeicher sowie ein einzeiliges
BASIC-Programm, welches das ultraFORTH83 startet. Oberhalb von
LIMIT befinden sich das Betriebssystemrom und I/O-Ports.
Unterhalb von LIMIT werden die Blockpuffer abgelegt;
1 Kbyte groß. Es werden beim Systemstart soviele Puffer
legt, wie zwischen LIMIT und RO passen.
Der Rest des Systems, zwischen ORIGIN und RO gelegen, teilt
sich in zwei Bereiche auf. Im oberen Bereich wachsen der
Returnstack (von oben, bei RO @ beginnend) und die Userarea
(von unten, bei UP@ beginnend) aufeinander zu.
Im unteren Bereich wachsen das Dictionary und der
plus Heap aufeinander zu. Wird mehr Platz auf dem Heap
benötigt, so wird der Datenstack automatisch nach unten ver-
schoben. Im Dictionary werden neue Worte abgelegt; dieser
Bereich des Systems wächst deshalb während der Kompilation am
schnellsten. Die Grenze zwischen Datenstack und Dictionary ist
daher die einzige, die vom System überwacht wird.
Die Bootarea schließlich enthält die Anfangswerte der User-
variablen, die während des Kaltstarts von dort in die Userarea
kopiert werden.
Das System belegt auch in der Zeropage Speicherzellen, unter
anderem mit dem Adreßinterpreter ("NEXT") und den Stackpointern
("RP" und "Sp") s
jeder
ange-
Datenstack
| Seite 48 Erläuterungen zz FORTH-Gesellsc ultraFORTHB3
| Speicherbelegung einer Task |
rd @e
Returnstack So
rp@ 5
au o rien
Userarea &
upe
Heap S
heap, sa
SB 89%
Stack
spß S slen
wre
here 9% ®
Dictionary &
Userareas
as 28 von
Tasks Task + 6
isr_(nwake Task! + 3
»999| jmp KRAK |9 © schlafend Task3 * 8
o &
$ BGE GAG
2 u zsza8
2° 8 Task2 +6
2 8 isr_(wake Task? * 3
9 9» bit XAXX 26 aktiv Task2 + 8
7 %
2 BGG G6GEHH
2 d az2ı203
oo 8 Taski +6
° 08 isr_(wake Taski + 3
2.99» bit KARX 4 aktiv Taski + 8
o E11
DOSE HGOHGH
a ultraFORTH83 ic} 1985 bp/ks/re/ue Erläuterungen Seite 43
Links in der Graphik sind die Forthworte
angegeben, die die entsprechenden Adres-
sen liefern.
c16 Der Assemblerprogrammierer kann den
Bereich von N bis $0076 benutzen.
SFFFF ®
Statt SYS(2064) steht SYS(4112).
ce4 Kernel
SEHBB LIMIT kann bis zu $FDOO betragen.
EHRIRERIEET In &FFFE,F steht ein Zeiger auf die
limit Interrupt-"Umleitung".
_ e Buffer
Buffer
; Buffer
f 3 # : unbenutzt
r
Returnstack ?
2
rp&@ 5
{rei rien
©
Userarea 5
upe #9 .
Heap
heap ® St ack-Under flow
sB 8 664 MHemorymap
stack
3
spe 3
trei
here 2 slen
65802 Zero-Pase
Fr Dictionary
509823 N
30921 u
Boot-Area 5 Zur
origin® SVYSC12A54) 5300893 Next
59907 SP
Bıldschırm
599906 Futfä
Kernel-Speıcher 09984 Ur
EEB2-Stack
8592 Zero-Page 0992 RP
[Seite 58 | ertäuterungen F-- FORTH-Gesellsc ultraFORTH83
6.3) Semaphore und "Lock"
Ein Problem, daß bisher noch nicht erwähnt wurde, ist: 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:
Create disp 0 ,
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. i
Ü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)
Die Implementation sieht nun folgendermaßen aus:
( Man muß sich noch vor Augen halten, daß jede Task eindeutig
durch den Anfang ihrer Userarea identifizierbar ist. )
DISP ist ein sog. Semaphor; er muß den Anfangswert 0
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 eingetragen 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 aktiven 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.
Ob TYPE , EMIT usw. ebenfalls gesichert sind, hängt von der
Implementation ab.
7 ultraFORTH83 E — Erläuterungen sie 30
6.4) 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 wordern. 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. Ein Beispiel:
line ( block -- )
block c/l bounds DO I c@ emit LOOP
ist FALSCH, denn nach EMIT stimmt der Adreßbereich, den der
Schleifenindex überstreicht, womöglich gar nicht mehr.
.line ( block -- )
c/1 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.
.line ( block -- ) block c/l type ;
ist FALSCH, da TYPE ja EMIT wiederholt ausführen kann und
somit die von BLOCK gelieferte Adresse in TYPE ungültig
wird.
>type ( adr len -- ) >r pad r@ cmove pad r> type
line -( block -—) block c/l >type
— ist RICHTIG, denn PAD ist für jeden Task verschieden.
Erläuterungen
Tee Toren UltraFORTHBE
Seite 52
In der Version 3.8 wurde das Wort LIST dahingehend geändert,
daß es, ähnlich wie INDEX , durch Drücken von Tasten angehal-
ten und abgebrochen werden kann. Das bringt gewisse Probleme
mit sich, wenn dieses Wort in einer Task (z.B. einem Drucker-
spooler) benutzt wird. In diesem Fall versucht sowohl die
Konsolen-Task als auch die das Wort LIST enthaltende Task
Eingaben von der Tastatur zu lesen. Tippt man einen Text ein,
so werden die einzelnen Zeichen zufällig auf die beiden Tasks
verteilt. Daher sollte jede Task (natürlich mit Ausnahme der
Konsolen-Task) ihren Eingabevektor so definieren, daß Sie keine
Eingaben erhalten kann.
Im folgenden wird gezeigt, wie ein Eingabevektor beschaffen
ist, der keine Eingaben erlaubt (siehe auch S. 28):
: halt ." Task gestoppt!” stop ; \ legt die Task völlig
\ still
Input: nul-Input halt false drop halt ;
\ statt : key key? decode expect
Für KEY könnte man auch immer ein bestimmtes (ungefährliches)
Zeichen zurückliefern. Die Entscheidung sollte aber beim Pro-
grammieren getroffen werden - wer weiß schon welches Zeichen
immer und überall ungefährlich ist. Bei EXPECT läßt sich
schwerlich eine bessere Lösung finden, da von EXPECT die
Variable SPAN verändert werden soll und es unangenehm werden
könnte, wenn zwei Tasks gleichzeitig an der gleichen Variablen
rumpfuschen. Jede Task, die jetzt am Anfang NUL-INPUT aus-
führt, bekommt keine Eingaben und wird schlimmstenfalls still-
gelegt.
Noch ein Hinweis : Eine Task sollte auf keinen Fall ABORT"
oder ein ähnliches Wort ausführen. In diesem Fall würde sich
diese Task wie die Konsolen-Task benehmen, was einen Systemab-
sturz zur Folge hat. Selbst wenn diese Fehlermöglichkeit
abgefangen und die Task angehalten wird, bleibt noch das
Problem, daß Semaphore noch auf diese Task "gelockt" sein
können und damit die Benutzung bestimmter Teile des Forth
blockiert bleibt!
ultraFORTH6Z
Erläuterungen
ic) 1985 bp/ks/re/ne
7) Debugging - Techniken
Fehlersuche ist in allen Programmiersprachen die aufwendigste
Aufgabe des Programmierers.
Für verschiedene Programme sind in der Regel auch verschiedene
Hilfsmittel erforderlich. 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.
Wenn Sie sich die Ratschläge und Tips zu Herzen nehmen und den
Umgang mit den Hilfsmitteln etwas ü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 Bearbeiten einer umfangreichen Aufgabe erst
die geeigneten Hilfsmittel zu verschaffen.
7.1) Voraussetzungen für die Fehlersuche
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
-) starke Faktorisierung, d.h. sinnvoll zusammengehörende
Teile eines Wortes sind zu einem eigenen Wort zusam-
mengefaßt. Worte sollten durchschnittlich nicht länger
als 2 - 3 Zeilen lang sein !
-) Übergabe von Parametern auf dem Stack statt in Variab-
len, überall wo das 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 :
"Thinking Forth" von Leo Brodie, Prentice Hall 1984.
Sind diese Bedingungen erfüllt, ist es meist möglich, die Worte
interaktiv zu testen. Damit ist gemeint, daß man bestimmte
Parameter auf dem Stack versammelt und anschließend das zu
testende Wort aufruft. Anhand der abgelieferten 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 Geschehen innerhalb des Wortes verfolgen.
Das geschieht meist durch "tracen".
ultraFORTH83
ers [Frltrungen
re/ne FORTH-Gesellsc
7.2) Der Tracer
Angenommen, Sie wollen folgendes Wort auf Fehler untersuchen:
(bitte tippen Sie ein, alle nötigen Eingaben sind fett und alle
Ausgaben des ultraFORTH83 sind unterstrichen dargestellt.)
: -trailing ( addri ni -- addri n2 )__compiling
2dup bounds ?DO 2dup + 1- c@ bl = _compiling
IF LEAVE THEN 1- LOOP ;__ok
Die Funktion dieses Wortes können Sie, wenn sie Ihnen unklar
ist, dem Glossar entnehmen. Zum Testen des Wortes wird ein
String benötigt. Sie definieren:
Create teststring ‚„"” Dies ist ein Test "ok
wobei Sie bitte absichtlich einige zusätzliche Leerzeichen
eingefügt haben. Sie geben nun ein :
teststring count .s_27 30160 ok
-trailing .s_27 30160 ok
und stellen zu Ihrem Erstaunen fest, daß -TRAILING kein
einziges Leerzeichen abgeschnitten hat. (Spätestens jetzt soll-
ten Sie den Tracer laden. Prüfen Sie, ob es das Wort DEBUG im
FORTH Vokabular gibt, dann ist der Tracer schon vorhanden.
Mit dem Tracer können Sie Worte schrittweise testen. Seine
Bedienung wird anhand des soeben definierten Wortes demon-
striert.
Sie geben ein:
debug -trailing__ok
Es geschieht zunächst nichts. DEBUG hat nur den Tracer
"scharf gemacht". Sobald -TRAILING ausgeführt werden soll,
wird der Tracer aktiv.
Nun fahren Sie fort:
teststring count .s_27 30160 _ok
-trailing
und erhalten folgendes Bild:
30071 5609 2DUP 27 30160
27 30160 ist der Stackinhalt, wie er von TESTSTRING COUNT
geliefert wurde, nämlich Adresse und Länge des Strings
TESTSTRING !.
(Für Fortgeschrittene : 5609 ist die Kompilationsadresse von
2DUP , 30071 die Position von 2DUP in -TRAILING .)
iDer genaue Wert dieser Zahlen ist systemabhängig.
ic} 19856 bp/ks/re/uwe
ultraFORTH83Z
Drücken Sie jetzt so lange <Return>, bis OK erscheint.
Insgesamt wird dabei folgendes ausgegeben :
debug -trailing teststring count .s_27 30160 ok
-trailing
30071 _5609 _2DUP 27 _30160
30073 _6819 _BOUNDS 27 30160 27 30160
30075 _6780 _(?DO 30160 30187 27 30160
30079 5609 _2DUP 27 30160
30081 5623 + 27 30160 27 30160
30083 5991 1- 30187 27 30160
30085 5066 _c®@ 30186 27 30160
30087 13375 __BL 32 27 30160
30089 6505 _= 32 3227 30160
30091 7044 ?BRANCH FFFF_27 30160
30095 7556 __LEAVE 27 30160
30103 4956 UNNEST 27 30160 ok
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 ( 5609 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 erhöht den IP um 4 ! Woher kommt eigentlich
(?DO ,„ in der Definition von -TRAILING stand doch nur ?DO .
(?DO ist ein von ?DO kompiliertes Wort, das zusätzlich zur
Kompilationsadresse noch einen 16-Bit-Wert benötigt, nämlich
einen Zeiger auf das zugehörige LOOP, das die Schleife beendet.
Zwei ähnliche Fälle treten noch auf. Das IF aus dem Quelltext
hat ein ?BRANCH kompiliert. Es wird gesprungen, wenn der
oberste Stackwert FALSE ( = 0) ist.. Auch ?BRANCH benötigt einen
zusätzlichen 16-Bit-Wert für den Sprungoffset.
Nach LEAVE geht es hinter LOOP weiter, es wird UNNEST
ausgeführt, das vom ; win -TRAILING kompiliert wurde und das
gleiche wie EXIT bewirkt, und damit ist das Wort -TRAILING auch
beendet. Das hier gelistete Wort UNNEST ist nicht zu verwech-
seln mit dem UNNEST des Tracers (siehe unten).
Wo liegt nun der Fehler in unserer Definition von -TRAILING ?
Um das herauszufinden, 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:
Erläuterungen
re/ue FORTH-Gesellsch ultraFoRTH83
Seite 56
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 -
statt = NOT eingesetzt werden kann. (Tip: der IF -Zweig wird
nicht ausgeführt, wenn der oberste Stackwert FALSE (also = 0)
ist.)
Der ultraFORTH83-Tracer gestattet es, jederzeit Befehle einzu-
geben, die vor dem Abarbeiten des nächsten Trace-Kommandos
ausgeführt werden. Damit kann man z. B. Stack-Werte verändern
oder das Tracen abbrechen. Ändern Sie probehalber beim nächsten
Trace-Lauf von -TRAILING das TRUE-Flag ($SFFFF) auf dem Stack
vor der Ausführung von ?BRANCH durch Eingabe von NOT auf 0
und verfolgen 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 abbrechen, so geben Sie RESTART ein. RESTART führt
einen Warm-Start des FORTH-Systems aus und schaltet den Tracer
ab. RESTART ist auch die Katastrophen-Notbremse, die man
einsetzt, wenn man sieht, daß das System mit dem nächsten
Befehl zwangsläufig im Computer-Nirwana entschwinden wird.
Nützlich ist auch die Möglichkeit, das Wort, das als nächstes
zur Ausführung ansteht, solange zu tracen, bis es ins aufru-
fende Wort zurückkehrt. Dafür ist das Wort NEST vorgesehen.
Wollen Sie also wissen, was BOUNDS macht, so geben Sie bitte,
wenn BOUNDS als nächstes auszuführendes Wort angezeigt wird,
NEST ein und Sie erhalten dann:
30071 5609 2DUP 27 30160
30073 6819 BOUNDS 27 _30160
6821 5364 OVER 27 _ 30160 27 30160
6823 5623 + 30160 27 30160 27 30160
6825 5259 SWAP 30187 30160 27 30160
6827 4956 UNNEST 30160 30187 27 30160
30075 __6780 _(?DO 30160 30187 27 30160
Beachten Sie bitte, daß die Zeilen jetzt eingerückt 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 Return-Stack manipulieren, mit NEST nicht
tracen lassen, da der Tracer selbst Gebrauch vom Return-Stack
macht. Auf solche Worte muß man den Tracer mit DEBUG ansetzen.
Wollen Sie das Tracen eines Wortes beenden, ohne die Ausführung
des Wortes abzubrechen, so benutzen Sie UNNEST .
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 abgearbeitet und
der Tracer meldet sich erst wieder, wenn er nach dem Wort
angekommen ist, bei dem ENDLOOP eingegeben wurde.
ultraFoRTH63
Erläuterungen
ic} 19385 bp/ks/re/uwe
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 Systens.
Der Tracer läßt sich auch mit dem Wort TRACE' starten, das
seinerseits ein zu tracendes Forth-Wort erwartet. Sie könnten
also auch im obigen Beispiel eingeben:
teststring count trace' -trailing
und hätten damit dieselbe Wirkung erzielt. TRACE' schaltet aber
im Gegensatz zu DEBUG nach Durchlauf des Wortes den Tracer
automatisch mit END-TRACE wieder ab.
Beachten Sie bitte auch, daß die Worte DEBUG und TRACE' das
Vokabular TOOLS mit in die Suchreihenfolge aufnehmen. Sie
sollten also nach - hoffentlich erfolgreichem - Tracelauf die
Suchordnung wieder umschalten.
Der Tracer ist ein wirklich verblüffendes Werkzeug, mit dem man
sehr viele Fehler schnell finden kann. Er ist gleichsam ein
Mikroskop, mit dem man tief ins Innere von Forth schauen kann.
Für die sehr neugierigen Forth'ler will ich noch Hinweise zur
Funktionsweise des Tracers geben.
Der Tracer modifiziert den Adressinterpreter (siehe Kap. 2) so,
daß er bei jedem ausgeführten Wort überprüft, ob während der
Ausführung dieses Wortes die weiter oben gezeigte Tabelle
ausgegeben werden soll oder nicht. Die einfachste Möglichkeit,
einfach immer die Daten auszudrucken, ist ausgesprochen unprak-
tisch, denn der Programmierer wird damit förmlich erschlagen.
Der "alte" Tracer (ultraFORTH83 rev. 3.5) gab die Daten nur
aus, wenn die Höhe des Returnstacks einem vorgegebenen Wert
entsprach. In der Regel war das nur in einem Wort der Fall,
schaffte aber Probleme, wenn Worte getraced wurden, die die
Höhe des Returnstacks änderten.
Der Tracer, der ab Version 3.8 enthalten ist, verwendet statt
dessen den IP. Zeigt der Interpreter in ein Intervall, daß z.B.
mit Hilfe des Wortes DEBUG gesetzt werden kann, wird die
Tracer-Information ausgegeben. Dadurch ist der Tracer wesent-
lich bedienungsfreundlicher; die Implementation war für uns
jedoch etwas knifflig...
Erläuterungen B-—- Tora UltraFORTHEI
Seite 58
7.3) Stacksicherheit
Anfänger neigen häufig dazu, Fehler bei der Stackmanipulation
zu machen. Erschwerend 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" Systemcrashs.
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 Schleifendurchlauf prüfen, ob
der Stack evtl. über- oder leerläuft.
Das geschieht durch Eintippen von :
LOOP compile ?stack L[compile] LOOP ; immediate restrict
+LOOP compile ?stack . [compile] +LOOP ; immediate restrict
UNTIL compile ?stack L[compile] UNTIL ; immediate restrict
REPEAT compile ?stack L[compile] REPEAT ; immediate restrict
= : compile ?stack ;
Versuchen Sie ruhig, herauszufinden wie die letzte Definition
£unktioniert. 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 rdrop rdrop \ delete errorhandler-nest
er ."” trace dump on abort is :" cr
BEGIN rp@e r0 @ - \ until stack empty
WHILE r> dup 8 u.r space
2- @ >name .name cr REPEAT
(error ;
unravel errorhandler !
Sie bekommen dann bei Eingabe von
10/
ungefähr folgenden Ausdruck :
ultraFoRTH83
Erläuterungen
ic) 1985 bp/ks/re/ue
trace dump is:
7871 ???
7928 UM/MOD
0 ???
8052 M/MOD
8065 /MOD
12312 EXECUTE
13076 INTERPRET
13199 'QUIT
/ aivison overflow
'QUIT INTERPRET und EXECUTE rühren vom Textinterpreter her.
Interessant wird es bei /MOD . Wir wissen nämlich, 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, bei einem Fehler ruft es aber DIVOVL auf. Dieses
Wort ist nicht sichtbar, daher erscheinen drei Fragezeichen.
Dieses Wort "verursachte" den Fehler, indem es ABORT" aufrief.
Nicht immer treten Fehler in Schleifen auf. Es kann auch der
Fall sein, daß ein Wort zu wenig Argumente auf dem Stack
vorfindet. Diesen Fall sichert ARGUMENTS . Die Definition
dieses Wortes ist:
: ARGUMENTS (in)
depth 1- < abort” not enough arguments” ;
Es wird folgendermaßen benutzt:
: -trailing ( adr len -—- ) 2 arguments a a Ye
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:
: is-depth ( n -- ) depth 1- - abort" wrong depth" ;
IS-DEPTH bricht das Programm ab, wenn die Zahl der Werte auf
dem Stack nicht 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.
Seite 60 1 Erläuterungen E— nu] UltrarORTHB3
7.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 <RETURN> drücken muß:
. 0.0.
se. .
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 dieses 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 :
1:
rechne ( --n) 1237//;
RECHNE
/
/ RECHNE division overflow
Wir sehen also, daß erst bei der zweiten Division der Fehler
auftrat. Das ist auch logisch, denn 2 3 / ergibt 0.
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.
ultraFORTH6Z
(ec) 1985 BE/Kkz/re/ue
7.5) Der 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 ultra-
FORTH-83 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 leicht
aufzufinden. ö
Dennoch gibt es natürlich auch im ultraFORTH83 Dekompiler,
und zwar sowohl einen vollautomatischen, der durch SEE <name>
gestartet wird, als auch einen einfachen, von Hand zu
bedienenden, der im folgenden näher beschrieben wird. Dieser
mamuelle Dekompiler erscheint uns wichtiger; er wird benutzt,
wenn der erzeugte Code von selbstgeschriebenen Worten unter-
sucht werden soll. In solchen Fällen ist ein Dekompiler
sinnvoll; der automatische versagt jedoch meistens, da er nur
Strukturen dekompilieren kann, für die er programmiert wurde.
Der manuelle Dekompiler befindet sich, wie der Tracer, im
Vokabular TOOLS. Folgende Worte stehen zur Verfügung.
N (name) ( addr -- addr' )
druckt den Namen des bei addr kompilierten Wortes aus und
setzt addr auf das nächste Wort.
K (konstante) ( 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 Forthwort 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 erhöht, sodaß sie hinter
den String zeigt.
[e (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 anzusehen. (s.a. DUMP und LDUMP)
Seite 6 Erläuterungen E-—-—- once UltraroRTHEE
Sehen wir uns nun ein Beispiel zur Benutzung des Dekompilers
an. Geben Sie bitte folgende Definition ein:
: test (n--)
12 = IF er ." Die Zahl ist zwolf !" 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
30198: 6154 CLIT ok
n
c 30200: 12 » .oR
n 30201: 6505 _ = ok
n 30203: 7044 ?BRANCH ok
b 30205: 27 30232 ok
n 30207: 16151 CR ok
n 30209: 9391 (." ok
s 30211: 20 Die Zahl ist zwolf _! ok
n 30232: 4956 UNNEST
drop
Die erste Adresse ist die, an der im Wort TEST die anderen
Worte kompiliert sind. Die zweite ist jeweils die Kompilations-
adresse der Worte, danach folgen die sonstigen Ausgaben des
Dekompilers.
Probieren Sie dieses Beispiel auch mit dem Tracer aus:
20 trace' test
und achten Sie auf die Unterschiede. Sie werden sehen, daß der
Tracer aussagefähiger und dazu noch einfacher zu bedienen ist.
KA ultraFORTH83 ESSEN FRE FREIE Erläuterungen
8) Anpassung des ultra-/ volksFORTH an andere Rechner
Die Hardware-Voraussetzungen für die Anpassung an einen
Rechner sind mindestens 24, besser noch 32 kBytes RAM.
Das ultraFORTH83 besteht aus zwei Teilen:
a) Einem Kern, der weitgehend rechnerunabhängig ist, aber
prozessorspezifische Teile enthält.
Dieser Kern enthält Stackmanipulatoren, Compiler usw.
Eine Teilmenge der Worte ist in Maschinensprache
geschrieben. Ihre Größe ist von Rechner zu Rechner
verschieden. Ist das ultraFORTH83 bereits auf einem
Rechner (z.2t. nur 6502) implementiert, so muß dieser
Teil nur marginal geändert werden.
b) Einem systemabhängigen Teil, der (weitgehend) in Forth
selbst geschrieben werden kann.
Er enthält Worte für Terminal- und
Massenspeichersteuerung. Anhand des C64 wird weiter
unten erklärt, welche Funktionen mindestens ausgeführt
werden müssen.
Vorgehensweise
-) Falls die Teile a) und b) geändert werden müssen, so
benötigen Sie einen Assembler, in Forth geschrieben,
und die Minimalversion (minimaler Anteil von
Maschinencode am Gesamtsystem) sowie Zugriff auf einen
Rechner, auf dem das ultraFORTH läuft (C64). Schreiben
Sie mir, falls Sie so etwas planen :
Bernd Pennemann / Eekboomkoppel 17 / 2000 Hamburg 62
-) Falls nur der Teil b) geändert werden muß, sollten Sie
als "Eichnormal" und Kommunikationsmittel Zugriff auf
einen C64 mit ultraFORTH haben. Sie können sich, wenn
Sie gute Kenntnisse in Forth haben, selbst das
ultraFORTH des C64 für Ihren Rechner umstricken. Für
— Fragen stehe ich natürlich zur Verfügung.
Einfacher, sicherer, aber langwieriger ist folgendes
Verfahren :
Sie erstellen anhand der C64-Quelltexte den
rechnerabhängigen Teil des ultraFORTH für Ihren
Rechner. Den Quelltext schicken Sie mir per
664-Diskette (oder Modem). Ich sende Ihnen ein
übersetztes und ggf. korrigiertes Forth-System auf
derselben Diskette zurück. Dieses System spielen Sie
dann vom C64 auf Ihren Rechner über, testen und
beseitigen Fehler. Daraus gewinnen Sie einen
verbesserten Quelltext, den Sie mir schicken usw.
Nach einigen Iterationen dürften Sie ein sicher
arbeitendes System besitzen.
Warum so kompliziert ?
Ihr ultraFORTH wird mit einem "Metacompiler" erzeugt.
Das geschieht auf dem C64. Dieser Metacompiler ist ein
Erläuterungen ultraFORTH83
/ref/we FORTH-Gesellsc
Seite 64
ziemlich kompliziertes Programm, daß man, um es
korrekt bedienen zu können, am besten selbst schreibt.
Außerdem verschenke ich solche Programme nicht
besonders gern.
Folgende Worte sind im Quelltext für das ultraFORTH auf dem
C64 an andere Rechner anzupassen:
G64KEY - liest ein Zeichen von der Tastatur ein. Bit 8
ist Null. Es wird gewartet, bis eine Taste gedrückt
wurde.
C64AKEY? - Liefert wahr (-1 = $FFFF) , falls eine Taste
gedrückt wurde. Das Zeichen wird nicht gelesen, d.h.
ein nachfolgendes (C64KEY liefert den Wert der
gedrückten Taste.
C64DECODE - kann unverändert übernommen werden.
C64EXPECT - kann unverändert übernommen werden.
C64EMIT - gibt ein Zeichen auf dem Bildschirm aus.
C6ACR - löst den Wagenrücklauf auf dem Bildschirm aus.
C64DEL - kann anfangs durch NOOP ersetzt werden. Löscht
das zuletzt gedruckte Zeichen und rückt den Cursor
„ech links.
C64PAGE - löscht den Bildschirm und positioniert den
Cursor links oben in der Ecke.
C64AT? - liefert Zeile und Spalte der Cursorposition.
Position 0 O0 ist links oben in der Ecke.
c64at - Positioniert den Cursor. Argumente sind Zeile und
Spalte.
C6ATYPE - Kann durch folgenden Text ersetzt werden :
c64type ( adr len -- ) bounds ?DO I c@ emit LOOP
b/blk - bleibt unverändert.
DRV? - liefert die Nummer des aktuellen
Diskettenlaufwerks. Kann durch eine Konstante ersetzt
werden.
E ultraFORTH83 F-——- — Erläuterungen se ss
DRVINIT - Initialisiert die Laufwerke nach dem Kaltstart.
Meistens durch NOOP ersetzt.
1541R/W - liest bzw. schreibt einen 1024 Bytes langen
Speicherbereich. Parameter sind die Adresse des
Speicherbereiches, ein Flag, das angibt, ob gelesen
oder geschrieben werden soll und die Blocknummer. Die
Blocknummer ist eine Zahl, die angibt, der wievielte
der 1024 Bytes langen Blöcke bearbeitet werden soll.
Dis Sunss Diskette wird dabei in solche Blöcke
eingeteilt.
Um später Files bearbeiten zu können, gibt es auch
—n einen noch unbenutzten File-Parameter.
Dieses Wort kann, wenn die anderen Worte
funktionieren, interaktiv von der Tastatur aus
eingegeben werden. Dafür ist es sinnvoll, eine
Diskette im Speicher zu simulieren. Den betreffenden
Speicherbereich, in dem die Simulation stattfindet,
» kann man dann mit dem Betriebssystem des Rechners auf
Diskette speichern.
Seite 66 [ ertäuterungen = FORTH-Gesellsc ultraFORTH83
N ultraFORTH83 B- —- —— Erläuterungen
[Seite 68 | Erläuterungen =
FORTH-Gesellsc
ultraFORTH83
Seite 69
Glossare
FOR
rev 3.5
Fr f
Syn
wre
ulttaFORTHMES3
ic) 1985 bp/ks/re/we
TON
KERLE
BINNEN
ra
©
2
pe
D2
=
Ein
eo
En
Je
nl
=
FORTH-Gesellsc
| Seite 78 Glossare K-
ultraFORTH83
ultraFORTH83
ic) 198E bp/ks/refue FORT Glossare Seite ri
Notation
Die Worte des ultraFORTH83 sind in Wortgruppen
zusammengefasst. Die Worte jeder Sachgruppe sind alphabetisch
sortiert. Die Wortgruppen sind nicht geordnet.
Worte werden in der in Kapitel 1 angegeben Schreibweise
aufgefuehrt. Wortnamen im Text werden gross geschrieben.
Die Wirkung des Wortes auf den Stack wird in Klammern
angegeben und zwar in folgender Form:
( vorher -- nachher )
vorher : Werte auf dem Stack vor Ausfuehrung des Wortes
nachher : Werte auf dem Stack nach Ausfuehrung des Wortes
In dieser Notation wird das oberste Element des Stacks immer
ganz rechts geschrieben. Sofern nicht anders angegeben,
beziehen sich alle Stacknotationen auf die spaetere
Ausfuehrung des Wortes. Bei immediate Worten wird auch die
Auswirkung des Wortes auf den Stack waehrend der Kompilierung
angegeben. ä
Worte werden ferner durch folgende Symbole gekennzeichnet:
C
Dieses Wort kann nur waehrend der Kompilation einer
:-Definition benutzt werden.
I
Dieses Wort ist ein immediate Wort, das auch im
kompilierenden Zustand ausgefuehrt wird.
83
Dieses Wort wird im 83-Standard definiert und muss auf
allen Standardsystemen aequivalent funktionieren.
U
Kennzeichnet eine Uservariable. Wird aufgrund eines
Missverstaendnisses nicht konsequent verwendet.
Weicht die Aussprache eines Wortes von der natuerlichen
englischen Aussprache ab, so wird sie in Anfuehrungszeichen
angegeben. Gelegentlich folgt auch eine deutsche Uebersetzung.
Die Namen der Stackparameter folgen, sofern nicht suggestive
Bezeichnungen gewaehlt wurden, dem nachstehendem Schema. Die
Bezeichnungen koennen mit einer nachfolgenden Ziffer versehen
sein.
| Seite 72 6lossare BE
Stack-Zahlentyp Wertebereich
not. in Dezimal
flag logischer Wert O=falsch, sonst=true
true logischer Wert -1 (als Ergebnis)
falselogischer Wert 0
b Bit 0..1
char Zeichen 0..127 (0..256)
8b 8 beliebige Bits nicht anwendbar
16b 16 beliebige Bits nicht anwendbar
n Zahl, bewertete Bits-32768..32767
+n positive Zahl 0..32767
u vorzeichenlose Zahl 0..65535
w Zahl, n oder u -32768..65535
addr Adresse, wie u 0..65535
32b 32 beliebige Bits nicht anwendbar
d doppelt genaue Zahl -2,147,483,648...
2,147,483,647
+d pos. doppelte Zahl 0..2,147,483,647
ud vorzeichenlose
doppelt genaue Zahl 0..4,294,967,295
sys 0, 1 oder mehr System-
FORTH-Gesellsc
ultraFORTH83
abhaengige Werte nicht anwendbar
minimale
Feldbreite
16 Bit
16
16
1
7
8
16
16
16
16
16
16
32
32
32
32
na
ultraFORTHB3
ug are For Blossare Seite 73]
* (wlw2 -— w3 ) 83
"mal", engl."times"
Der Werte wl wird mit w2 multipliziert. w3 sind die niederwertigen
16 Bits des Produktes. Ein Ueberlauf wird nicht angezeigt.
Arithmetik
*/ (niln2n3--n4) 83
"mal-durch", engl."times-divide"
Zuerst wird nl mit n2 multipliziert und ein 32-bit Zwischenergebnis
erzeugt. n4 ist der Quotient aus dem 32-bit-Zwischenergebnis und
dem Divisor n3. Das Produkt von nl mal n2 wird als 32-bit
Zwischenergebnis dargestellt, um eine groessere Genauigkeit
gegenueber dem sonst gleichwertigen Ausdruck nl n2 * n3 / zu
erhalten. Eine Fehlerbedingung besteht, wenn der Divisor Null ist,
oder der Quotient ausserhalb des Intervalls (-32768 .. 32767)'
liest.
*/mod (nln2n3-- n4n5) 83
"mal-durch-mod",engl."times-divide-mod"
Zuerst wird nl mit n2 multipliziert und ein 32-bit Zwischenergebnis
erzeugt. n4 ist der Rest und n5 der Quotient aus dem 32-bit-
Zwischenergebnis und dem Divisor n3. n4 hat das gleiche Vorzeichen
wie n3 oder ist Null. Das Produkt von nl mal n2 wird als 32-bit
Zwischenergebnis dargestellt, um eine groessere Genauigkeit
gegenueber dem sonst gleichwertigen Ausdruck nl n2 * n3 /mod zu
erhalten. Eine Fehlerbedingung besteht, wenn der Divisor Null ist,
oder der Quotient ausserhalb des Intervalls (-32768..32767) liegt.
+ (wlw2 -- w) 83
"plus"
wl und w2 addiert ergibt w3.
(wlw2 -- w3 ) 83
"minus"
w2 von wl subtrahiert ergibt w3 .
-1 (—--1)
Oft benutzte Zahlenwerte wurden zu Konstanten gemacht. Definiert in
der Form:
er n CONSTANT n
Dadurch wird Speicherplatz eingespart und die Ausfuehrungszeit
verkuerzt. Siehe auch CONSTAN .
/ (nln2--n3) 83
"durch",engl."divide"
n3 ist der Quotient aus der Division von nl durch den Divisor n2.
Eine Fehlerbedingung besteht, wenn der Divisor Null ist oder der
Quotient ausserhalb des Intervalls (-32768 .. 32767) liegt.
/mod (nln2--n3n4) 83
"durch-mod", engl."divide-mod"
n3 ist der Rest und n4 der ganzzahlige Quotient aus der Division
von nl durch den Divisor n2. n3 hat das selbe Vorzeichen wie n2
oder ist Null. Eine Fehlerbedingung besteht, wenn der Divisor Null
ist oder der Quotient ausserhalb des Intervalls (-32768 .. 32767)
liegt.
| Seite 74 | stossare I FORTH-Gesellsc ultraFORTH83
0 (-0)
Siehe -1 .
1 (--1)
Siehe -1 .
1+ (wl --w2) 83
"eins-plus", engl."one-plus"
w2 ist das Ergebnis von Eins plus wl. Die Operation 1 + wirkt
genauso.
1- (wl --w2) 83
"eins-minus", engl."one-minus"
w2 ist das Ergebnis von Eins minus wl. Die Operation 1 - wirkt
genauso.
2 (-- 2)
Siehe -1 .
2* (wl-—-w)
"zwei-mal", eng.1"two-times"
wl wird um ein Bit nach Links verschoben und das ergibt w2. In das
niederwertigste Bit wird eine Null geschrieben. Die Operation 2 *
wirkt genauso.
2+ (wl-- w) 83
"zwei-plus", engl."two-plus"
w2 ist das Ergebnis von Zwei plus wl. Die Operation 2 + wirkt
genauso.
2- (wl -—-w) 83
"zwei-minus", engl."two-minus"
w2 ist das Ergebnis von Zwei minus wl. Die Operation 2 - wirkt
genauso,
2/ (nl--n2) 83
"zwei-durch", engl."two-divide"
nl wird um ein Bit nach rechts verschoben und das ergibt n2 . Das
Vorzeichen wird beruecksichtigt und bleibt unveraendert. Die
Operation 2 / wirkt genauso.
3 (--3)
Siehe -1. -
3+ (w--w2)
"drei-plus", engl."three-plus"
w2 ist das Ergebnis von Drei plus wl. Die Operation 3 + wirkt
genauso.
4 (-4)
Siehe -1 .
abs (n-—-u) 83
"absolut", engl."absolute"
u ist der Betrag von n „ Wenn n gleich -32768 ist, hat u den selben
Wert wie n. Vergleiche auch "Arithmetik, Zweierkomplement".
max (nln2--n3) 83
"maximum"
n3 ist der Groessere der beiden Werte nl und n2. Benutzt die >
Operation. Die groesste Zahl fuer nl oder n2 ist 32767.
ultraFORTH83
min
mod
nezate
u/mod
umax
umin
cc» 1988 bprKeFre/we For) Glossare Boote 75]
(nin2--n3) 83
"minimum"
n3 ist der Kleinere der beiden Werte nl und n2, Benutzt die <
Operation. Die kleinste Zahl fuer nl oder n2 ist -32768.
(nln2--n3) 83
"mod"
n3 ist der Rest der Division von nl durch den Divisor n2. n3 hat
dasselbe Vorzeichen wie n2 oder ist Null. Eine Fehlerbedingung
besteht wenn der Divisor Null ist oder der Quotient ausserhalb des
Intervals (-32768 .. 32767) liegt.
(nl--n2) 83
n2 hat den gleichen Betrag, aber das umgekehrte Vorzeichen von nl.
n2 ist gleich der Differenz von Null minus nl.
( ul u2 -- u3 u4 )
"u-durch-mod", engl."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-
Zahlen (unsigned integer). Eine Fehlerbedingung besteht, wenn der Divisor
Null ist.
(ulu2 -—- u3)
"u-maximum"
u3 ist der Groessere der beiden Werte ul und u2. Benutzt die u>
Operation. Die groesste Zahl fuer nl oder n2 ist 65535.
(ulu2 -- u3)
"u-minimun"
u3 ist der Kleinere der beiden Werte ul und u2. Benutzt die u<
Operation. Die kleinste Zahl fuer nl oder n2 ist 0.
[seite 76 [_stossare = FORTH-Gesellsc ultraFORTN83
Logik und Vergleiche
0< C(n-- flag ) 83
"null-kleiner", engl."zero-less"
Wenn n kleiner als Null (negativ) ist, ist flag wahr. Dies ist
immer dann der Fall, wenn das hoechstwertigste Bit gesetzt ist.
Deswegen kann dieser Operator zu Test dieses Bits benutzt werden.
0<> (n-- flag)
Wenn n verschieden von Null ist, ist flag wahr.
O= (w-- flag ) 83
"null-gleich", engl."zero-equals"
Wenn w gleich Null ist, ist flag wahr.
0> (n-- flag ) 83
"null-groesser", engl."zero-greater"
Wenn n groesser als Null ist, ist flag wahr.
< (nln2-- flag) 83
"kleiner-als", engl."less-than"
Wenn nl kleiner als n2 ist, ist flag wahr.
ZB. -32768 32767 < ist wahr.
-32768 O< ist wahr.
= (wlw2 -- flag) 83
"gleich", engl."equals"
Wenn wl gleich w2 ist, ist flag wahr.
> C(nln2-- flag ) 83
"groesser-als", engl."greater-than"
Wenn nl groesser als n2 ist, ist flag wahr.
Z.B. -32768 32767 > ist falsch.
-32768 0> ist falsch,
and (nln2--n3) 83
nl wird mit n2 bitweise logisch UND verknuepft und das er2eibt n3.
oder ( 16bl 16b2 -- true
"case-frage", engl."case-question"
Vergleicht die beiden obersten Werte auf dem Stack. Sind sie
gleich, verbleibt TRUE auf dem Stack. Sind sie verschieden,
verbleibt FALSE und der darunterliegende Wert 16bl auf dem Stack.
Wird zB. benutzt in der Form:
KEY ASCII A CASE? IF „.. EXIT THEN
ASCII B CASE? IF ... EXIT THEN
case? ( 16bl 16b2 -- 16bl false )
)
DROP
Entspricht dem Ausdruck OVER = DUP IF NIP THEN.
false (0)
Hinterlaesst Null als Zeichen fuer logisch-falsch auf dem Stack.
not (nl--n2) 83 5
Jedes Bit von nl wird einzeln invertiert und das ergibt n2.
or (niln2--n3) 833
nl wird mit n2 bitweise logisch ODER verknuepft und das ergibt n3,
ultraFORTH83
truc
ud
uwithin
xor
blossare
ic} 19855 be/ks/rer/we FOR
(--1)
Hinterlaesst -1 als Zeichen fuer logisch-wahr auf dem Stack.
C(ulu2 -- flag) 583
"u-kleiner-als", engl."u-less-than"
Wenn ul kleiner als u2 ist, ist flag wahr. Die Zahlen u sind
vorzeichenlose 16-Bit-Zahlen. Wenn Adressen verglichen werden
sollen, muss U< benutzt werden. Sonst passieren oberhalb von 32K
eigenartige Dinge!
(ul u2 — flag )
"u-groesser-als", engl."u-greater-than"
Wenn ul groesser als u2 ist, ist flag wahr, sonst gilt das gleiche
wie fuer K ..
(nulu2-—- flag )
"u-within'"
Wenn ul kleiner oder saleich n ist und n kleiner u2 ist (ul<=n<u2),
ist flag wahr. Benutzt die U< Operation.
(nln2--n3) 83
"x.or"
nl wirc mit n2 bitweise logisch EXCLUSIV ODER verknuepft und ergibt
23%
Seite _78
Glossare ultraFORTH83
bpks/re/ue FORTH-Gesellsc
Speicheroperationen
Q
cnove
cmove>
count
ctoggle
( 16b adr —- ) 83
"store"
16b werden in den Speicher auf die Adresse adr geschrieben.
In 8-bitweise adressierten Speichern werden die zwei Bytes adr und
adr+l mit dem Wert 16b ueberschrieben. Der 6502 verlangt, das vom
16b Wert die niederwertigen 8b nach adr und die hoeerwertigen 8b
nach adr+1l geschrieben werden (lowbyte-highbyte-order).
(wladr -— ) 83
"plus-store'"
wl wird zu dem Wert w in der Adresse adr addiert. Benutzt die +
Operation. Die Summe wird in den Speicher in die Adresse adr
geschrieben. Der alte Speicherinhalt wird ueberschrieben.
( adr -—- 16b ) 83
"fetch"
Von der Adresse adr wird der Wert 16b aus dem Speicher geholt.
Dabei werden beim 6502 die niederwertigen 8b von adr und die
hoeerwertigen 8b von adr+l geholt und als 16b auf den Stack gelegt.
( 16b adr -- ) 83
"c-store"
Von 16b werden die niederwertigen 8b in den Speicher in die
Adresse adr geschrieben.
( adr -- &b ) 83
"c-fetch"
Von der Adresse adr wird der Wert 8b aus dem Speicher geholt.
( adrl adr2 u-- ) 83
"c-move'"
Beginnend bei adrl werden u Bytes zur adr2 kopiert. Zuerst wird das
Byte von adrl nach adr2 bewegt und dann aufsteigend fortgefahren.
Wenn u Null ist, wird nichts kopiert.
( adrl adr2 u -—- ) 83
"c-move-rauf", engl."c-move-up"
Beginnend bei adrl werden u Bytes zur adr2 kopiert. Zuerst wird das
Byte von adrl-plus-u-minus-1 nach adr2-plus-u-minus-1 bewegt und
dann absteigend fortgefahren. Wenn u Null ist, wird nichts kopiert.
Das Wort wird benutzt um Speicherinhalte auf hoehere Addressen zu
verschieben wenn die Speicherbereiche sich ueberlappen,.
( adrl -- adr2 +n ) 83
adr2 ist adrl+l und +n ist die Laenge des String. Das Byte mit der
Adresse adrl enthaelt die Laenge des String angegeben in Bytes. Die
Zeichen des Strings beginnen bei der Adresse adr+l. Die Laenge +n
eines Strings darf im Bereich (0 .. 255) liegen. Vergleiche auch
"String, counted".
( 8b adr -- )
"c-togale"
Fuer jedes gesetzte Bit in 8b wird im Byte mit der Adresse adr das
entsprechende Bit invertiert (dh. cin zuvor gesetztes Bit ist
danach zgeloescht und ein zuvor geloeschtes Bit ist danach gesetzt).
Fuer alle geloeschten Bits in n bleiben die entsprechenden Bits im
Byte mit der Adresse adr unveraendert. Der Ausdruck DUP C® ROT XOR
SWAP C! wirkt genauso.
ultraFORTH83 E- — ——— —- u blossare Seite 79
erase ( adr u -- )
Von adr an werden u Bytes des Speichers mit $00 ueberschrieben,. Hat
u den Wert Null, passiert nichts.
fill ; (adr usb -- )
Von adr an werden u Bytes des Speichers mit Sb beschrieben. Hat u
den Wert Null, passiert nichts,
move ( adrl adr2 u -— )
Beginnend bei adrl werden u Bytes nach adr? bewegt. Dabei ist es
ohne Bedeutung, ob ueberlappende Speicherbereiche aufwacrts oder
abwaerts kopiert werden, weil MOVE die passende Routine dazu
auswaehlt. Hat u den Wert Null, passiert nichts. Siehe auch CHOVE
und CMOVE> .
off ( adr — )
Schreibt der Wert FALSE in den Speicher mit der Adresse adr.
on ( adr -—- )
Schreibt der Wert TRUE in den Speicher mit der Adresse adr.
pad ( -- adr ) 83
adr ist die Startaddresse einer "scratch arca". In diesen
Speicherbereich koennen Daten fuer Zwischenrechnungen abgelegt
werden. Wenn die naechste verfuegbare Stelle fuer das Dictionary
veraendert wird, aendert sich auch die Startadresse von pad. Die
vorherige Startadresse von pad geht ebenso wie die Daten dort
verloren. pad erstreckt sich bis zum obersten Wert des Datenstack.
place ( adrl +n adr2 -- )
Bewegt +n Bytes von der Adresse adrl zur Adresse adr?-+1l und
schreibt +n in die Speicherstelle mit der Adresse adr?. “ird in der
Regel benutzt um Text einer bestimmten Laenge als Counted String
abzuspeichern. adr2 darf gleich, groesser und auch kleiner als adrl
sein.
| Seite 88 Glossare zen FORTH-Gesellsc ultraFORTH83
32-Bit-\Worte
dO= (d-- flag ) 83
"d=-null-gleich", enal."d-zero-equals"
Wenn d gleich Null ist, wird flag wahr.
d+ (dld2--d3) 83
"d-plus"
dl und d2 addiert ergibt d3.
d< ( di d2 -- flag ) 83
"d-kleiner-als", engl."d-less-than"
Wenn dl kleiner als d2 ist, wird flag wahr. Benutzt die <
Operation, jedoch fuer 32bit Vergleiche.
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
(di--d2) 83
"d-negate"
d2 hat den gleichen Betrag, aber ein anderes Vorzeichen als dl.
extend (n--d)
Der Wert n wird auf den doppelt genauen Wert d vorzeichenrichtig
erweitert.
m (nln2-d)
"m-mal", engl."m-times"
Der Wert nl wird mit n2 multipliziert. d ist das doppeltgenaue
vorzeichenrichtige Produkt.
n/mod (dnl-n2n3)
"m-durch-mod", engl."m-divide-mod"
n2 ist der Rest und n3 der Quotient aus der Division der
doppeltgenauen Zahl d durch den Divisor nl. Der Rest n2 hat
dasselbe Vorzeichen wie d oder ist Null. Eine Fehlerbedingung
besteht, wenn der Divisor Null ist oder der Quotient ausserhalb des
Intervalls (-32768 .. 32767) liegt.
ud/mod ( udl ul -- u2 ud2 )
"u-d-durch-mod", engl."u-d-divide-mod'"
u2 ist der Rest und ud2 der doppeltgenaue Quotient aus der Division
der doppeltgenauen Zahl udl durch den Divisor ul. Die Zahlen u sind
vorzeichenlose 16-Bit-Zahlen (unsigned integer). Eine
Fehlerbedingung besteht, wenn der Divisor Null ist,
um® ( ul u2 -—- ud ) 83
"u-m-mal", engl."u-m-times"
Die Werte ul und u2 werden multipliziert und als doppeltgenauer
Wert d abgelegt. UM ist die anderen multiplizierenden Worten
zugrundeliegende Routine. Die Zahlen u sind vorzeichenlose Zahlen.
© ultraFORTHB3
um/mod
Glossare
| Seite 81 |
ic} 1S85 bpks/re/ue FORT
(ud ul -- ı2u3) 3
"u-m-durch-mod", engl."u-m-divide-nod"
u2 ist der Rest und u3 der Quotient aus der Division von ud Jurch
den Divisor ul. Die Zahlen u sind vorzeichenlose Zahlen. Eine
Fehlerbedingung besteht, wenn der Divisor -!ull ist oder der
Quotient ausserhalb des Intervalls (0 .. 05535) licost.
UM/MOD ist die allen anderen dividierenden \lorten zusrur
Routine. Die Fehlermeldung "division overflow" wird auszereben,
wenn der Divisor liull ist.
ndelierende
ultraFORTN83
blossare
bRekSFTrefwe FORTH-Gesellsc
Stack
-roll ( 16bn...16bl 16b0 +n -- 16b0 16bn...16bl )
"minus-roll"
Das oberste Glied einer Kette von n Werten wird an die nte Position
gerollt. Dabei wird +n selbst nicht mitgezaehlt. 2 -ROLL wirkt wie
-ROT. O0 -ROLL veraendert nichts,
-rot ( 15bl 1652 16b3 -- 1663 16bl 16b2 )
"minus-rot"
Die drei obersten 16b Werte werden rotiert, sodass der oberste Wert
zum Untersten wird. Hebt ROT auf,
.s 0)
"punkt-s", engl."dot-s"
Gibt alle Werte die auf dem Stack liegen aus, ohne den Stack zu
veraendern. Oft benutzt um neue Worte auszutesten. Die Ausgabe der
Werte erfolet von links nach rechts, der oberste Stackwert zuerst.
2dup ( 32b -—- 32b 32b ) 83
"zwei-dup", engl."two-dup"
Der Wert 32b wird dupliziert.
2drop ( 32b — ) 33
"two-drop""
Der Wert 32b wird fallengelassen, dh. die beiden obersten Werte
werden vom Stack entfernt.
2swap ( 32bl 32b2 -- 32b2 32bl ) 83
"zwei-swap", engl."two-swap"
Die beiden obersten 32b Werte werden vertauscht.
?dup (16b -- 16b 16b )
oder ( 0 -- 0 )
"fragezceichen-dup", engl."question-dup"
Nur wenn der Wert 16b verschieden von Null ist, wird er verdoppelt.
clearstack ( -—- empty )
Loescht den Datastack, indem die Stack-Startadresse aus der
Uservariablen SO in den Datastackzeiger (stackpointer) geschrieben
wird,
depth (-n)
n ist die Anzahl der Werte die auf dem Stack lagen, bevor DEPTH
ausgefuehrt wurde.
drop ( 16b -- ) 83
Der \!ert 16b wird fallengelassen, dh. der oberste Wert wird vom
Stack entfernt, Siehe auch 2DROP,
ultraFORTH83
E «c} 1985 bp/ks/re/we FORT] Glossare Seite 83
dup ( 16b -- 16b 16b ) 83
Der Wert 16b wird verdoppelt. Siehe auch 2DUP.
nip ( 16bl 16b2 -- 1652 )
Der zweite Wert wird vom Stack entfernt. 16b2 ist der oberste und
16bl der zweite Wert auf dem Stack,
over ( 16b1 16b2 -- 16bl 16b2 16bl ) 33
Der Wert 16bl wird ueber 16b2 herueber kopiert.
pick ( 16bn..16b0 +n -- 16bn..16bC }!5bn ) &3
Der +nte Wert im Stack wird oben auf den Stack kopiert, Dabei wird
+n selbst nicht mitgezaehlt. O PICK wirkt wie DUP. 1 PICR wirkt wie
OVER.
roll ( 15bn 16bm..16b0 +n -- 15bm..16b0 16bn ) 383
Das +nte Glied einer Kette von n Werten wird nach oben auf den
Stack gerollt. Dabei wird +n selbst nicht mitgezaehlt.
rot ( 16bl 16b2 1663 -- 15b2 1663 1651 ) 583
Die drei obersten 16b Werte werden rotiert, sodass Jer unterste zun
obersten wird.
so ( -— adr )
adr ist die Adresse einer Uservariablen, in der die Startadresse
des Datastack steht. Der Ausdruck SO ? SP! wirkt wie CLRARSTACK und
leert den Stack.
swap ( 16b1 1652 -- 1652 16bl ) 83
Die beiden obersten 16b-Werte werden vertauscht.
sp! ( adr -—- )
"s-p-store"
Setzt den Datastackzeiger (engl."stack pointer") auf die Adresse
adr. Der oberste \lert im Datastack ist nun der, welcher in der
Speicherstelle bei adr steht.
sp® ( -- adr )
"s-p-fetch"
Holt die Adresse adr aus dem Datastackzeizer. Der oberste !!ert in
Stack stand in der Speicherstelle bei adr, bevor SP: aussefuehrt
Br wurde. Der Ausdruck SP@® © wirkt wie DUP.
under ( 16b1 16b2 -- 16b2 16bl 16b2 )
Eine Kopie des obersten !!ertes auf dem Stack wird unter den zweiten
Wert eingefuegt. Der Ausdruck SWAP OVER wirkt zcnauso.
blossare ultraFoRTH83
Seite 84 bPrksfre/ue FORTH-Gesellsc
Returnstack
>r ( 16b -- ) c,83
"auf-r", engl."to-r"
Der Wert 16b wird auf den Returnstack gelegt. Siehe auch R> .
push (adr — )
Der Inhalt aus der Adresse adr wird auf dem Returnstack bis zum
naechsten EXIT verwahrt und sodann nach adr zurueck geschrieben.
Dies ermoeglicht die lokale Verwendung von Variablen innerhalb
einer :-Definition. Wird zB. benutzt in der Form:
® WORT ... BASE PUSH HEX ... 5;
Hier wird innerhalb von WORT in der Zahlenbasis HEX gearbeitet, zB.
um ein Speicherbereich auszugeben (Hex-Dump). Das Wort ; fuehrt
EXIT aus. Nachdem WORT ausgefuehrt worden ist, besteht die gleiche
Zahlenbasis wie vorher.
r> ( -- 16b ) C,83
"r-von", engl."r-£rom"
Der Wert 16b wird von dem Returnstack geholt. Siehe auch »R .
rp! (adr -— )
"r-p-store"
Setzt den Returnstackzeiger (engl."return stack pointer") auf die
Adresse adr. Der oberste Wert im Returnstack ist nun der, welcher
in der Speicherstelle bei adr steht.
ro ( -- adr )
adr ist die Adresse einer Uservariablen, in der die Startadresse
des Returnstack steht.
r@ ( -- 16b ) C,83
"r-fetch"
Der Wert 16b ist eine Kopie des obersten Wertes im Returnstack,
rdepth (-—-n)
"r-depth"
n ist die Anzahl der Werte die auf dem Returnstack liegen.
rdrop (-) &
"r-drop"
Der Wert 16b wird vom Returnstack fallengelassen, dh. der oberste
Wert wird vom Returnstack entfernt. Der Datenstack wird nicht
veraendert.
rp@ ( -- adr )
"r-p-fetch"
Holt die Adresse adr aus dem Returnstackzeiger. Der oberste \ert im
Returnstack steht in der Speicherstelle bei adr. Ü in men
Strings
gu
3S
/string
ultraFORTH83
Glossare
ic} 1955 bp/ks/re/we FOR
( -- air ) GT
( text ( -- ) compiling
"string"
Liest den Text bis zum naechsten " und legt ihn als Counted
String im Dictionary ab. Kann nur bei der Kompilation verwendet
werden. Zur Laufzeit wird Startadresse des Counted String auf den
Stack gelegt. Benutzt in der Form:
: <name> N et)
( +dl —- +d2 ) 83
(1), engl."sharp";
Der Rest von +dl geteilt durch den Wert in BASE wird in ein ASCII
Zeichen umgewandelt und dem Ausgabestring in Richtung absteigender
Addressen hinzugefuegt. +d2 ist der Quotient und verbleibt auf dem
Stack zur weiteren Bearbeitung. Ueblicherweise benutzt zwischen <#
und iD.
( (1) Bisher gibt es keine verbindliche deutsche Aussprache, Das
Zeichen wird in der Notenschrift verwendet und dort in engl."sharp"
und in deutsch "kreutz" ausgesprochen. # wird auch oft statt Nr.
verwendet; zB. SCR#
( 32b -- adr +n ) 83
"sharp-zreater"
Am Ende der strukturierten Zahlenausgebe wird der 32b Wert vom
Stack entfernt. Hinterlegt werden die Adresse des erzeugten
Ausgabestrings und +n als die Anzahl Zeichen im Ausgabestring,
passend fuer TYPE.
(+d--00) &3
"sharp-s"
+d wird umgewandelt bis der Quotient zu Null geworden ist. Siehe
auch ?® „. Dabei wird jedes Zwischenergebnis in ein Ascii-Zeichen
umgewandelt und dem String fuer die strukturierte Zahlenausgabe
angefuegt. Wenn die Zahl von vorn herein den Wert Null hatte, wird
cine einzelne Null in den String gegeben. Wird ueblicherweise
benutzt zwischen <# und $ .
( adrl nl n2 -- adr2 n3 )
n2 ist cin Index, welcher in den String weist, der im Speicher bei
der Adresse adrl beginnt. Der String hat die Laenge nl. n3 ist
eleich nl-minus-n?2, wenn n2 kleiner als nl ist, und ad2 ist dann
adrl-plus-n?. n3 ist gleich Full, wenn n2 groesser oder gleich nl
ist, und adr2 ist dann adrl-plus-nl. Der Vergleich benutzt die
Operation U< „ Wird zB. benutzt, um die vorderen n Zeichen eines
String abzuschneiden.
(—) 83
"less-sharp"
Leitet die strukturierte Zahlenausgabe ein. Um eine doppelt genaue
Zahl in einen von rechts nach links aufgebauten Ascii-String
umzuwandeln, benutze man die lorte:
ED ds <# HOLD SIGN
| Seite 86 6lossare amızm FORTH-Gesellsc ultraFORTH83
accumulate ( +dl adr char -- +d2 adr )
Dient der Umwandlung von Ziffern in Zahlen. Multipliziert die Zahl
+dl mit BASE, um sie eine Stelle in der aktuellen Zahlenbasis nach
links zu ruecken, und addiert den Zahlenwert von char dazu. char
stellt eine Ziffer dar. adr wird nicht veraendert. lird zB. in
CONVERT benutzt. +n muss eine in der Zahlenbasis BASE gueltige
Ziffer darstellen.
capital ( charl -- char2 )
Die Zeichen im Bereich von a bis z werden in die Grossbuchstaben A
bis Z umgewandelt. Andere Zeichen werden nicht veraendert.
capitalize ( adr -- adr )
Wandelt alle Klein-Buchstaben im Counted String bei der Adresse adr
in Gross-Buchstaben um. adr wird nicht veraendert. Siehe auch
CAPITAL.
convert ( +dl adrl -- +d2 adr2 ) 83
Wandelt den Ascii-Text ab adrl+1l in eine Zahl mit der Zahlenbasis
BASE um. Der entstehende Wert wird in dl akkumuliert und als d2
hinterlassen. adr? ist die Adresse des ersten nicht umwandelbaren
Zeichens im Text.
digit? ( char -- digit true )
oder ( char -- false )
Prueft mit BASE ob das Zeichen char eine gueltige Ziffer ist. Ist
diese wahr, wird der Zahlenwert der Ziffer und TRUE auf dem Stack
hinterlegt. Ist char keine gueltige Ziffer, wird FALSE hinterlest.
hold ( char -- ) 83
Das Zeichen char wird in den bildhaften Ausgabestring eingefuest.
Ueblicherweise benutzt zwischen <# und #> .
nullstring? ( adr -- adr false )
oder ( adr -- true }
Prueft, ob der Counted String bei der Adresse adr ein String der
Laenge Null ist. Wenn.dies der Fall ist, wird TRUE hinterlest,
Sonst bleibt adr erhalten und FALSE wird obenauf gelegt.
number (adr--d)
Wandelt den Counted String mit der Adresse adr in die Zahl d um.
Die Umwandlung erfolgt entsprechend der Zahlenbasis in BASE. Eine
Fehlerbedingung besteht, wenn die Ziffern des String nicht in eine
Zahl verwandelt werden koennen,
ultraFORTH83
number?
scan
skip
Glossare
«c) 1985 bp/ks/re/we FOR
( adr - d >)
oder ( adr - n @<)
oder ( adr -- adr false )
Wandelt den Counted String mit der Adresse adr in die Zahl n um.
Die Umwandlung erfolgt entsprechend der Zahlenbasis in BASE oder
wird vom ersten Zeichen im String bestimmt. Enthaelt der String
zwischen den Ziffern auch Ascii-Zeichen fuer Komma oder Punkt, so
wird er als doppelt-genaue Zahl d interpretiert. Sonst wird der
String in eine einfach-genaue Zahl n umgewandelt. Wenn die Ziffern
des String nicht in eine Zahl verwandelt werden koennen, bleibt die
Adresse des String erhalten und der Wert fuer logisch-falsch wird
auf den Stack gelegt. Die Zeichen, die zur Bestimmung der
Zahlenbasis dem Ziffernstring vorangestellt werden koennen, sind:
% (Basis 2 "binaer")
%& (Basis 10 "decimal")
$ (Basis 16 "hexadecimal")
ı (Basis 16 "hexadecimal")
Der Wert in BASE wird dadurch nicht veraendert.
( adrl nl char -- adr? n2 )
Der String mit der Laenge nl, der im Speicher ab Adresse adrl
steht, wird nach dem Zeichen char durchsucht. adr2 ist die Adresse,
bei der das Zeichen char gefunden wurde. n2 ist die Laenge des
verbleibenden String. Wird char nicht gefunden, ist adr2 die
Adresse des ersten Zeichen hinter dem String und n2 ist Null.
(n-) 83
Wenn n negativ ist, wird ein Minuszeichen in den bildhaften
Ausgabestring eingefuegt. Wird ueblicherweise benutzt zwischen <#
und >.
( adrl nl char -- adr2 n2 )
Der String mit der Laenge nl, der im Speicher ab Adresse adrl
steht, wird nach. dem ersten Zeichen, das verschieden von char ist,
durchsucht. adr?2 ist die Adresse dieses Zeichens. n2 ist die Laenge
des verbleibenden String. Besteht der gesammte String aus den
Zeichen char, ist adr2 die Adresse des ersten Zeichen hinter dem
String und n2 ist Null.
| Seite 88 [ Glossare = FORTH-Gesellsc ultraFORTH83
Datentypen
( -- sys ) 83 "colon"
ein definierendes Wort, das in der Form:
<name> : 5
benutzt wird. Es erzeugt die Wortdefinition fuer
<name> im Kompilations- Vokabular und schaltet den
Kompiler an. Das erste Vokabular in der Suchreihen-
folge wird durch das Kompilations- Vokabular er-
setzt. Das Kompilations- Vokabular wird nicht ge-
aendert. Der Quelltext wird anschliessend kompi-
liert. <name> wird eine "colon-definition"” oder
eine ":-Definition" genannt. Die neue Wortdefini-
tion fuer <name> kann solange nicht im Dictionary
gefunden werden, bis das zugehoerige ; oder ;CODE
erfolgreich ausgefuehrt wurde.
Eine Fehlerbedingung liegt vor, wenn ein Wort
nicht gefunden und nicht in eine Zahl gewandelt
werden kann oder wenn, waehrend der Kompilation
vom Massenspeicher, der Quelltext erschoepft ist,
bevor ; oder ;CODE erreicht werden. sys wird vom
zugehoerigen ; abgebaut.
(--) 83 I C "semi-colon"
(sys -- ) compiling
beendet die Kompilation einer :-Definition; macht
den Namen <name> dieser :-Definition im Dictionary
auffindbar, schaltet den Interpreter ein und kompi-
liert ein EXIT. Die Stackparameter sys, die von
hinterlassen wurden, werden geprueft und abgebaut.
Siehe : und EXIT
Alias (cfa -- )
ein definierendes Wort, das typisch in der Form:
<namex> Alias <name> „,
benutzt wird. ALIAS erzeugt einen Kopf fuer <name>
im Dictionary. Wird <name> aufgerufen, so verhaelt
es sich wie <namex>. Insbesondere wird beim Kompi-
lieren nicht <namex>, sondern <name> ins Dictio-
nary eingetragen. Im Unterschied zu
<name> <namex> ;
ist es mit ALIAS auch moeglich, Worte, die den Re-
turnstack beeinflussen (vergleiche >R oder R> ),
mit anderem Namen zu definieren. Ausser dem neuen
Kopf fuer <name> wird kein zusaetzlicher Speicher-
platz verbraucht.
Constant ( 16b -- ) 83
ein definierendes Wort, das in der Form:
16b Constant <name>
benutzt wird. Wird <name> spaeter ausgefuehrt, so
wird 16b auf den Stack gelegt.
ultraFORTH83
Xch 1985 bo/ksfrerwe FOR blossare Seite 89
Defer ( --
ein definierendes Wort, das in der Form:
Defer <name>
benutzt wird. Erzeugt den Kopf fuer ein neues Wort
<name> im Dictionary, haelt 2 Bytes in dessen Para-
meterfeld frei und speichert dort die Kompilations-
adresse einer Fehlerroutine. Wird <name> nun ausge-
fuehrt, so wird die Ausfuehrung mit einer Fehler-
meldung abgebrochen. Man kann dem Wort <name> zu
jedem Zeitpunkt eine andere Funktion zuweisen, sie-
he IS . <name> laesst sich jedoch schon kompilie-
— ren, ohne dass es eine sinnvolle Aktion ausfuehrt.
Damit ist die Kompilation erst spaeter definierter
Worte indirekt moeglich. Andererseits ist die Ver-
aenderung des Verhaltens von <name> fuer spezielle
Zwecke moeglich.
Deferred Worte im System sind:
R/W ,„ COLD ,„ RESTART , ABORT , QUIT ,
NOTFOUND , .STATUS und DISKERR .
Ein spezielles Deferred Wort ist
>INTERPRET.
Input: =>) "input-colon"
ein definierendes Wort, benutzt in der Form:
Input: <name>
newKEY newKEY? newDECODE newEXPECT [
INPUT: erzeugt einen Kopf fuer <name> im Dictio-
nary und kompiliert einen Vektor von Zeigern auf
Worte, die fuer die Eingabe von Zeichen zustaendig
sind. Wird <name> ausgefuehrt, so wird ein Zeiger
auf das Parameterfeld von <name> in die Uservari-
able INPUT geschrieben. Alle Eingaben werden jetzt
ueber die neuen Eingabeworte abgewickelt. Die Rei-
henfolge der Worte nach INPUT: <name> bis zur [
muss eingehalten werden.
Im System ist das mit INPUT: definierte Wort
KEYBOARD enthalten, wenn der Editor geladen ist,
stehen ausserdem EDIBOARD und DIGITS zur Verfue-
gung. “
Is (efa--)
ein Wort, mit dem das Verhalten eines Deferred Wor-
tes veraendert werden kann. IS wird in der Form:
<namex> Is <name>
benutzt. Wenn <name> kein Deferred Wort ist, so
wird eine Fehlerbehandlung eingeleitet, sonst wird
<name> die Ausfuehrung von <namex> zugewiesen. Sie-
he DEFER.
Seite 98 blossare bE/kSt/re/we FORTH-Gesellsc ultraFORTH83
Output: (-) "“output-colon"
ein definierendes Wort, benutzt in der Form:
Output: <name>
newEMIT newCR newTYPE newDEL newPAGE newAT
newAT? [
OUTPUT: erzeugt einen Kopf fuer <name> im Dictio-
nary und kompiliert einen Vektor aus Zeigern auf
Worte, die fuer die Ausgabe von Zeichen verantwort-
lich sind. Wird <name> ausgefuehrt, so wird ein
Zeiger auf das Parameterfeld von <name> in die
Uservariable OUTPUT geschrieben. Alle Ausgaben wer-
den jetzt ueber die neuen Ausgabeworte abge-
wickelt. Die Reihenfolge der Worte nach OUTPUT:
<name> bis zur [ muss eingehalten werden.
Im System ist das mit OUTPUT: definierte Wort
DISPLAY enthalten.
User {[—-) 83
ein definierendes Wort, benutzt in der Form:
User <name>
USER erzeugt einen Kopf fuer <name> und haelt 2
Byte in der Userarea frei. Siehe UALLOT . Diese 2
Byte werden fuer den Inhalt der USERvariablen be-
nutzt und werden nicht initialisiert. Im Parameter-
feld der USERvariablen im Dictionary wird nur ein
Byte- Offset zum Beginn der Userarea abgelegt.
Wird <name> spaeter ausgefuehrt, so wird die Adres-
se des Wertes der USERvariablen in der Userarea
auf den Stack gegeben.
Variable Ve) 83
ein definierendes Wort, benutzt in der Form:
Variable <name>
VARIABLE erzeugt einen Kopf fuer <name> und haelt
2 Byte in seinem Parameterfeld frei. Siehe ALLOT.
Dies Parameterfeld wird fuer den Inhalt der
VARIABLEn benutzt und wird nicht initialisiert.
Wird <name> spaeter ausgefuehrt, so wird die Adres-
se des Parameterfeldes auf den Stack gegeben.
Vocabulary [3 83
ein definierendes Wort, das in der Form:
Vocabulary <name>
benutzt wird. VOCABULARY erzeugt einen Kopf fuer
<name>, das den Anfang einer neuen Liste von Wor-
ten bildet. Spaetere Ausfuehrung von <name> er-
setzt das erste Vokabular in der Suchreihenfolge
durch <name>. Wird <name> das Kompilations Vokabu-
lar, so werden neue Definitionen in die Liste von
<name> gelinkt. Vergleiche DEFINITIONS .
ultraFORTH83
ker TS08 Berkesrarue or Glossare Seite 1]
Dictionary - Worte
” ( -- 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.
(forget ( 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.
; (?16b ==) 83 "comma"
2 ALLOT fuer 16b und speichere 16b ab HERE 2-
.name ( addr -- ) "dot-name"
addr ist die Adresse des Countfeldes eines Namens.
Dieser Name wird ausgedruckt. Befindet er sich im
Heap, so wird das Zeichen | vorangestellt. Ist addr
null, so wird "???" ausgegeben.
allot (WW) 83
Allokiere w Bytes im Dictionary. Die Adresse des
naechsten freien Dictionaryplatzes wird entsprechend
verstellt.
& ( 16b -- ) "c-comma"
ALLOT ein Byte und speichere die unteren 8 Bit von 16b
in HERE 1-.
clear Aa
Loescht alle Namen und Worte im Heap.
dp ( -- addr ) "4-p"
Eine Uservariable, die die Adresse des naechsten
freien Dictionaryplatzes enthaelt.
empty e=-)
= Loescht alle Worte, die nach der letzten Ausfuehrung
von SAVE oder dem letzten Kaltstart definiert wurden.
DP wird auf seinen Kaltstartwert gesetzt und der Heap
geloescht.
forget (-) 83
Wird in der Form FORGET <name> benutzt
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 geschuetzten Bereich, so wird
ebenfalls eine Fehlerbehandlung eingeleitet. Es wurden
Vorkehrungen getroffen, die es ermoeglichen, aktive
Tasks und Vokabulare, die in der Suchreihenfolge
auftreten, zu vergessen.
| Seite 92 [_stossare = FORTH-Gesellsce ultraFORTH83
here ( -- addr ) 83
addr ist die Adresse des naechsten freien
Dictionaryplatzes.
hide ( =
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 )
last ( -- addr )
Variable, die auf das Countfeld des zuletzt
definierten Wortes zeigt.
name> ( addri -- addr2 ) "name-from"
addr2 ist die Kompilationsadresse die mit dem
Countfeld in addri korrespondiert.
origin ( -- addr )
addr ist die Adresse, ab der die Kaltstartwerte der
Uservariablen abgespeichert sind.
reveal (5)
Traegt das zuletzt definierte Wort in die Liste des
Vokabulars ein, in dem es definiert wurde.
save We)
Kopiert den Wert aller Uservariablen in den
Speicherbereich ab ORIGIN und sichert alle
Vokabularlisten. Wird spaeter COLD ausgefuehrt, so
befindet sich das System im gleichen Speicherzustand
wie bei Ausfuehrung von SAVE.
uallot (ni -- n2)
Allokiere bzw. deallokiere nl 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.
udp ( -- addr ) ued-p"
Eine Uservariable, in dem das Ende der bisher
allokierten Userarea vermerkt ist.
>body ( addri -- addr2 ) "to-body"
addr2 ist die Parameterfeldadresse, die mit der
Kompilationsadresse addri korrespondiert.
>name ( addri -- addr2 ) "to-name"
addr2 ist die Adresse eines Countfeldes, das mit der
Kompilationsadresse addri korrespondiert. Es ist
moeglich, dass es mehrere addr2 fuer ein addri gibt.
In diesem Fall ist nicht definiert, welche
ausgewaehlt wird.
rj ultrafORTHB3 DI 2: Sererneree zo] S1ossare Pserre5]
Vokabular - Worte
also (-)
Ein Wort, um die Suchreihenfolge zu spezifizieren. Das
Vokabular im auswechselbarem Teil der Suchreihenfolge
wird zum ersten Vokabular im festen Teil gemacht,
wobei die anderen Vokabulare des festen Teils nach
hinten ruecken. Ein Fehler liegt vor,. falls der feste
Teil sechs Vokabulare enthaelt.
Assembler .=)
Ein Vokabular, das Prozessor-spezifische Worte
enthaelt, die fuer Code-Definitionen benoetigt werden.
context ( -- addr )
addr ist die Adresse des auswechselbaren Teils der
Suchreihenfolge. Sie enthaelt einen Zeiger auf das
erste zu durchsuchende Vokabular.
current ( — addr )
addr ist die Adresse eines Zeigers, der auf das
Kompilationsvokabular zeigt, in das neue Worte
eingefuegt werden.
definitions (--) 83
Ersetzt das gegenwaertige Kompilationsvokabular durch
das Vokabular im auswechselbaren Teil der
Suchreihenfolge, d.h. neue Worte werden in dieses
Vokabular eingefuegt. :
Forth (—-) 83
Das urspruengliche Vokabular.
forth-83 (—-) 83
Lt. Forth83-Standard soll dieses Wort sicherstellen,
dass ein Standardsystem benutzt wird. Im ultraFORTH
funktionslos. u
Only (
Loescht die Suchreihenfolge vollstaendig und ersetzt
sie durch das Vokabular ONLY im festen und
auswechselbaren Teil der Suchreihenfolge. ONLY
enthaelt nur wenige Worte, die fuer die Erzeugung
einer Suchreihenfolge benoetigt werden.
Onlyforth ( =)
entspricht der haeufig benoetigten Sequenz
ONLY FORTH ALSO DEFINITIONS.
seal fe 3
Loescht das Vokabular ONLY , so dass es nicht mehr
durchsucht wird. Dadurch ist es moeglich, nur die
Vokabulare des Anwenderprogramms durchsuchen zu lassen.
FORTH-Gesellsc
| Seite 94 blossare =
toss
words
voc-link
vP
( .—_
ultraFORTH83
Entfernt das erste Vokabular des festen Teils der
Suchreihenfolge. Insofern ist es das Gegenstueck zu
ALSO .
me)
Gibt die Namen der Worte des Vokabulars,
das im
auswechselbaren Teil der Suchreihenfolge steht, aus,
beginnend mit dem zuletzt erzeugtem Namen.
( -- addr )
Eine Uservariable.
mit allen Vokabularen.
FORGET benoetisgt.
{ — addr )
V-P
Sie enthaelt den Anfang einer Liste
Diese Liste wird u.a.
?üsr
Eine Variable, die das Ende der Suchreihenfolge
markiert. Sie enthaelt ausserdem Informationen ueber
die Laenge der Suchreihenfolge.
ultraFORTH83
PET Beykbrmerme For Blossare EB eite 35]
Heap - Worte
?head ( -- addr ) "question-head"
Eine Variable, die angibt, ob und wieviele der
naechsten zu erzeugenden Namen im Heap angelegt werden
sollen (s.a. ! ).
hallot (a)
Allokiere bzw. deallokiere n Bytes auf dem Heap. Dabei
wird der Stack verschoben, ebenso wie der Beginn des
Heap.
heap ( -- addr )
addr ist der Anfang des Heap. Er wird u.A. durch
HALLOT geaendert.
heap? ( addr -- flag ) "heap-question"
Das Flag ist wahr, wenn addr ein Byte im Heap
adressiert, ansonsten falsch.
' (u) "headerless"
Setzt bei Ausfuehrung ?HEAD so, dass der naechste
erzeugte Name nicht im normalen Dictionaryspeicher
angelegt wird, sondern auf dem Heap.
| Seite 96 blossare on FORTH-Gesellsc ultraFORTH83
Kontrollstrukturen
+LOOP (Gäu) 83,1,C "plus-loop"
(sys ==) compiling
n wird zum Loopindex addiert. Falls durch die Addition
die Grenze zwischen limit-1i und limit ueberschritten
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.
?DO (w1w2 -- ) 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. Details ueber die Beendigung von
Schleifen: s. +LOOP. Ist w2=w1 , so wird der
Schleifenrumpf ueberhaupt nicht durchlaufen.
?exit ( flag -- ) "question-exit"
Fuehrt EXIT aus, falls das flag wahr ist. Ist das flag
falsch, so geschieht nichts.
BEGIN (--) 83,I,C
( sys -"”) compiling
Wird in der folgenden Art benutzt:
BEGIN ( ...flag 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
bei UNTIL wahr oder oder das flag bei WHILE falsch
ist. REPEAT setzt die Schleife immer fort.
bounds ( start count -- limit start )
Dient dazu, ein Intervall, das durch Anfangswert start
und Laenge count gegeben ist, in ein Intervall
umzurechnen, das durch Anfangswert start und Endwert+1
limit beschrieben wird.
Beispiel : 10 3 bounds DO ... LOOP fuehrt dazu, das I
die Werte 10 11 12 annimmt.
DO ( wl w2 -- ) 83,1,C
( sys -- ) " compiling
Entspricht ?DO , jedoch wird der Schleifenrumpf
mindestens einmal durchlaufen. Ist wl=w2 , so wird der
Schleiferumpf 65536-mal durchlaufen.
ELSE (-®=) 83,1,C
( sysl -- sys2 )compiling
Wird in der folgenden Art benutzt:
flag IF ... ELSE ... THEN
ELSE wird unmittelbar nach dem Wahr-Teil , der auf IF
folgt, ausgefuehrt. ELSE setzt die Ausfuehrung
unmittelbar hinter THEN fort.
1 ultraFORTH83 ich 1985 bp/kssrerwe FOR: Glossare | Seite 97]
execute ( addr -- ) 83
Das Wort, dessen Kompilationsadresse addr ist, wird
ausgefuehrt.
I fis= wo) 83,C
Wird zwischen DO und LOOP benutzt, um eine Kopie des
Schleifenindex auf den Stack zu holen.
IF ( flag -- ) 83,15€
( -- 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
Zu ELSE ausgefuehrt 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. "
I (--w) 83,C
Wird zwischen DO .. DO und LOOP .. LOOP benutzt, um
eine Kopie des Schleifenindex der aeusseren Schleife
auf den Stack zu holen.
LEAVE t =, 83,C
Setzt die Ausfuehrung des Programmes hinter dem
naechsten LOOP oder +LOOP fort, wobei die zugehoehrige
Schleife beendet wird. Mehr als ein LEAVE pro Schleife
ist moeglich, ferner kann LEAVE zwischen anderen
Kontrollstrukturen auftreten. Der Forth83-Standard
schreibt abweichend vom ultraFORTH vor, dass LEAVE ein
immediate Wort ist.
LOOP 0-) 83,1,C
( -- sys ) compiling
Entspricht +LOOP, jedoch mit n=1 fest gewaehlt.
perform ( addr -- )
addr ist eine Adresse, unter der sich ein Zeiger auf
die Kompilationsadresse eines Wortes befindet. Dieses
Wort wird ausgefuehrt. Entspricht der Sequenz @
EXECUTE
REPEAT =) 83,1,C
( -- sys ) compiling
Wird in der folgenden Form benutzt:
BEGIN (.. WHILE) .. REPEAT
REPEAT setzt die Ausfuehrung der Schleife unmittelbar
hinter BEGIN fort. Der ()-Ausdruck ist optional und
kann beliebig oft auftreten.
THEN (En 83,1,€C
(sys -- ) compiling
Wird in der folgenden Art benutzt:
IF (...ELSE) ... THEN
Hinter THEN ist die Programmverzweigung zuende.
[Seite 98 Glossare I FORTH-Gesellsc ultraFORTH83
UNTIL ( flag -- ) 83,1,6
(sys -- ) compiling
Wird in der folgenden Art benutzt:
BEGIN (... flag WHILE) ... flag UNTIL
Markiert das Ende einer Schleife, deren Abbruch durch
flag herbeigefuehrt wird. Ist das flag vor UNTIL wahr,
so wird die Schleife beendet, ist es falsch, so wird
die Schleife unmittelbar hinter BEGIN fortgesetzt.
WHILE ( flag -- ) 83,1,C
( sysi -- 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 Ausfuehrung
der Schleife bis UNTIL oder REPEAT fortgesetzt, ist es
falsch, so wird die Schleife beendet und das Programm
hinter UNTIL bzw. REPEAT fortgesetzt. Es koennen mehre
WHILE in einer Schleife verwendet werden.
ultraFORTHBS B, 1:5 Sopran a Glossare Seite 39
Compiler - Worte
Fu (de "comma-quote"
Speichert einen counted String im Dictionary ab HERE.
Dabei wird die Laenge des Strings in dessen erstem
Byte, das nicht zur Laenge hinzugezaehlt wird,
vermerkt.
Ascii ( -- char ) I
(-) compiling
Wird in der folgenden Art benutzt:
Ascii ccc
wobei ccc durch ein Leerzeichen beendet wird. char ist
_ der Wert des ersten Zeichens von ccc im benutzten
Zeichensatz (gewoehnlich ASCII). Falls sich das System
im kompilierenden Zustand befindet, so wird char als
Konstante compiliert. Wird die :-definition spaeter
ausgefuehrt, so liegt char auf dem Stack.
compile | 83,0
Typischerweise in der folgenden Art benutzt:
<name> ... compile <namex> ... ;
Wird <name> ausgefuehrt, so wird die
Kompilationsadresse von <namex> zum Dictionary
hinzugefuegt und nicht ausgefuehrt. Typisch ist <name>
immediate und <namex> nicht immediate.
Does> („z.addr:) 83,1,C "does"
( =) compiling
Definiert das Verhalten des Wortes, das durch ein
definierendes Wort erzeugt wurde. Wird in der
folgenden -Art benutzt:
<namex> ... <create> ... Does> ... ;
und spaeter:
<namex> <name>
wobei <create> CREATE oder ein anderes Wort ist, das
CREATE ausfuehrt.
Zeigt das Ende des Wort-erzeugenden Teils des
definierenden Wortes an. Beginnt die Kompilation des
_ Codes, der ausgefuehrt wird, wenn <name> aufgerufen
wird. In diesem Fall ist addr die Parameterfeldadresse
von <name>. addr wird auf den Stack gebracht und die
Sequenz zwischen DOES> und ; wird ausgefuehrt.
immediate ( ==) 83
Markiert das zuletzt definierte Wort als "immediate",
d.h. dieses Wort wird auch im kompilierenden Zustand
ausgefuehrt.
Literal ( -- 16b ) 83,1,C
( 12.5 — J compiling
Typisch in der folgenden Art benutzt:
[ 16b ] Literal
Kompiliert ein systemabhaengiges Wort, so dass bei
Ausuehrung 16b auf den Stack gebracht wird.
[Seite 198 | Slossare = mas UltraFORTHBT
recursive (--) 1,C
(--) compiling
Erlaubt die rekursive Kompilation des gerade
definierten Wortes in diesem Wort selbst. Ferner kann
Code fuer Fehlerkontrolle erzeugt werden.
restrict (9--
Markiert das zuletzt definierte Wort als "restrict",
d.h. dieses Wort kann nicht vom Textinterpreter
interpretiert sondern ausschliesslich in anderen
Worten kompiliert werden.
[ (--) 83,1 "left-bracket"
(==>) compiling
Schaltet den interpretierenden Zustand ein. Der
Quelltext wird sukzessive ausgefuehrt. Typische
Benutzung : s. LITERAL
Ü’] ( -- addr ) 83,1,C "bracket-tick"
(—-) compiling
Wird in der folgenden Art benutzt:
[] <name>
Kompiliert die Kompilationsadresse von <name> als eine
Konstante. Wenn die :-definition spaeter ausgefuehrt
wird, so wird addr auf den Stack gebracht. Ein Fehler
tritt auf, wenn <name> in der Suchreihenfolge nicht
gefunden wird.
[compile] (. ==) 83,1,C "bracket-compile"
(, ==) compiling
Wird in der folgenden Art benutzt:
[compile] <name>
Erzwingt die Kompilation des folgenden Wortes <name>.
Damit ist die Kompilation von immediate-Worten
moeglich.
| ultraFORTH83 “ch 1985 bp/ks/re/we FORTI Glossare Seite iBi
Interpreter - Worte
( (rasch 83:1 "paren"
“= compiling
Wird in der folgenden Art benutzt:
( ccec)
Die Zeichen ccc, abgeschlossen durch ) , werden als
Kommentar betrachtet. Kommentare werden ignoriert. Das
Leerzeichen zwischen ( und ccc ist nicht Teil des
Kommentars. ( kann im interpretierenden oder
kompilierenden Zustand benutzt werden. Fehlt )
werden alle Zeichen im Quelltext als Kommentar
betrachtet.
50
+load (H--) "plus-load"
LOAD den Block, dessen Nummer um n hoeher ist, als die
Nummer des gegenwaertig interpretierten Blockes.
+thru { ni n2 m.) "plus-thru"
LOAD die Bloecke hintereinander, die nl..n2 vom
gegenwaertigen Block entfernt sind.
Beispiel : 1 2 +thru laedt die naechsten beiden
Bloecke.
"2 (e 7.) I "next-block"
se) compiling
Setze die Interpretation auf dem naechsten Block fort.
>in ( -- addr ) 83 "to-in"
Eine Variable, die den Offset auf das gegenwaertige
Zeichen im Quelltext enthaelt. s. WORD
»interpret Del "to-interpret"”
Ein deferred Wort, das die gegenwaertige
Interpretationsroutine aufruft, ohne eine
Rueckkehradresse auf dem Returnstack zu hinterlassen
(was INTERPRET tut). Es kann als spezielles GOTO
angesehen werden.
blk ( -- addr ) 83 "b-1-k"
_ Eine Variable, die die Nummer des gerade als Quelltext
interpretierten Blockes enthaelt. Ist der Wert von BLK
Null, so wird der Quelltext vom Texteingabepuffer
genommen.
find ( addri -- addr2 n )83
addri ist die Adresse eines counted string. Der String
enthaelt einen Namen, der in der aktuellen
Suchreihenfolge gesucht wird. Wird das Wort nicht
gefunden, so ist addr2 = addri und n = Null. Wird das
Wort gefunden, so ist addr2 dessen Kompilationsadresse
und n erfuellt folgende Bedingungen:
n ist vom Betrag 2 , falls das Wort restrict ist,
sonst vom Betrag 1
n ist positiv, wenn das Wort immediate ist, sonst
negativ.
| Seite 182 [| stossare h bEeKkS/re/we FORTH-Gesellsc ultraFORTH83
interpret G == )
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 Null, so werden Zeichen
aus dem Texteingabepuffer interpretiert.
load ya) 83
Die Inhalte von >IN und BLK, die den gegenwaertigen
Quelltext angeben, 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
zurueckgebracht. s.a. BLK >IN BLOCK
name ( -- addr )
Holt den naechsten String, der durch Leerzeichen
eingeschlossen wird, aus dem Quelltext, wandelt ihn in
Grossbuchstaben um und hinterlaesst die Adresse addr,
ab der der String im Speicher steht. s. WORD
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 erkennen.
Ist mit NO.EXTENSIONS vorbesetzt. Dieses Wort bricht
die Interpretation des Quelltextes ab und druckt die
Fehlermeldung "haeh?" aus.
parse ( char -- addr +n )
Liefert die Adresse addr und Laenge tn des naechsten
Strings im Quelltext, der durch den Delimiter char
abgeschlossen wird. tn ist Null, falls der Quelltext
erschoepft oder das erste Zeichen char ist. >IN wird
veraendert.
quit =) 83
Entleert den Returnstack, schaltet den
interpreterierenden Zustand ein, akzeptiert Eingaben
von der aktuellen Eingabeeinheit und beginnt die
Interpretation des eingegebenen Textes.
source ( -- addr +tn )
Liefert Anfang addr und maximale Laenge +n des
Quelltextes. Ist BLK Null, beziehen sich Anfang und
Laenge auf den Texteingabepuffer, sonst auf den Block,
dessen Nummer in BLK steht und der in den
Rechnerspeicher kopiert wurde. s. BLOCK >IN
state ( "waddr.) 83
Eine Variable, die den gegenwaertigen Zustand
enthaelt. Der Wert Null zeigt den interpretierenden
Zustand an, ein von Null verschiedener Wert den
kompilierenden Zustand.
ultraFORTH83 «c» 1985 bp/ks/re/ue FORT 6lossare Seite 183
thru (Bin —-)
LOAD die Bloecke von ni bis inklusive n2.
word t char --- addr, )83
erzeugt einen counted String durch Lesen von Zeichen
vom Quelltext, bis dieser erschoepft ist oder der
Delimiter char auftritt. Der Quelltext wird nicht
zerstoert. Fuehrende Delimiter werden ignoriert. Der
gesamte String wird im Speicher beginnend ab Adresse
addr als eine Sequenz von Bytes abgelegt. Das erste
Byte enthaelt die Laenge des Strings (0..255). Der
String wird durch ein Leerzeichen beendet, das nicht
in der Laengenangabe enthalten ist. Ist der String
laenger als 255 Zeichen, so ist die Laenge
undefiniert. War der Quelltext schon erschoepft, als
WORD aufgerufen wurde, so wird ein String der Laenge
Null erzeugt.
Wird der Delimiter nicht im Quelltext gefunden, so ist
der Wert von >IN die Laenge des Quelltextes. Wird der
Delimiter gefunden, so wird >IN so veraendert, dass
>IN das Zeichen hinter dem Delimiter indiziert. #TIB
wird nicht veraendert.
Der String kann sich oberhalb von HERE befinden.
] {2 83,1 "right-bracket"
ee) compiling
Schaltet den kompilierenden Zustand ein. Der Text vom
Quelltext wird sukzessive kompiliert. Typische
Benutzung s. LITERAL
\ € =) I "skip-line"
(ee | compiling
Ignoriere den auf dieses Wort folgenden Text bis zum
Ende der Zeile. s. C/L
\\ (] I "skip-screen"
==.) compiling
Ignoriere den auf dieses Wort folgenden Text bis zum
Ende des Blockes. s. B/BLK
\needs ku] "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 gefunden, so wird die
Interpretation hinter <name> fortgesetzt.
Beispiel:\needs Editor 1+ load
Laedt den folgenden Block, falls EDITOR im Dictionary
nicht vorhanden ist.
| Seite 184 [ 6lossare m FORTH-Gesellse ultraFORTN83
(error
?pairs
?stack
abort
Abort"
diskerr
Fehlerbehandlung
( string -- ) "paren-error"
Dieses Wort steht normalerweise in der Variablen
ERRORHANDLER und wird daher bei ABORT" und ERROR".
ausgefuehrt. 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# abgelest.
(nin2 --) "question-pairs"
Ist nl <> n2 , so wird die Fehlermeldung
"unstructured” ausgegeben. Dieses Wort wird benutzt,
um die korrekte Schachtelung der Kontrollstrukturen zu
ueberpruefen.
-- ) "question-stack"
Prueft, ob der Stack ueber- oder leerlaeuft. Der
Stack laeuft leer, falls der Stackpointer auf eine
Adresse oberhalb von SO zeigt. In diesem Fall wird
die Fehlermeldung "stack empty" ausgegeben. Der
Stack laeuft ueber, falls der Stackpointer zwischen
HERE und HERE + $100 liegt. In diesem Fall wird die
Fehlermelurg "tight stack" ausgegeben, falls mehr
als 31 Werte auf dem Stack liegen. Ist das nicht der
Fall, so versucht das System, das zuletzt definierte
Wort zu vergessen und es wird die Fehlermeldung
"dictionary full" ausgegeben.
( == ) 83,1
Leert den Stack, fuehrt END-TRACE STANDARDI/O und
QUIT aus.
( flag ) 83,1,C "abort-quote"
==) compiling
Wird in der folgenden Form benutzt:
flag Abort" ccc"
Wird ABORT" spaeter ausgefuehrt, so geschieht nichts,
wenn flag falsch ist. Ist flag wahr, so wird der Stack
geleert und der Inhalt von ERRORHANDLER ausgefuehrt.
Beachten Sie bitte, dass im Gegensatz zu ABORT kein
END-TRACE ausgefuehrt wird. —
(=
Ein deferred Wort, das normalerweise mit (DISKERR
vorbesetzt ist. DISKERR wird aufgerufen, wenn ein
Fehler beim Massenspeicherzugriff auftrat. (DISKERR
gibt dann die Meldung "error ! r to retry" aus. Wird
anschliessend r gedrueckt, so wiederholt das System
den Massenspeicherzugriff, der zum Fehler fuehrte.
Wird eine andere Taste gedrueckt, so wird der Zugriff
abgebrochen und die Meldung "aborted" ausgegeben. In
diesem Fall wird die interne Verteilung der
Blockpuffer nicht geaendert.
ultraFORTH83
Error" ( flag ) LG "error-quote"
7 compiling
Dieses Wort entspricht ABORT" , jedoch mit dem
Unterschied, dass der Stack nicht geleert wird.
errorhandler ( -- adr )
adr ist die Adresse einer Uservariablen, deren Inhalt
die Kompilationsadresse eines Wortes ist. Dieses Wort
wird ausgefuehrt, wenn das flag, das ABORT" bzw.
ERROR" verbrauchen, wahr ist. Der Inhalt von
ERRORHANDLER ist normalerweise (ERROR.
warning ( -- adr )
adr ist die Adresse einer Variablen. Ist der Inhalt
der Variablen null, so wird die Warnung "exists"
ausgegeben, wenn ein Wort redefiniert wird. Ist der
Wert nicht null, so wird die Warnung unterdrueckt.
“c} 1985 bp/ks/re/we FORTE Glossare Seite 185
| Seite 186 [_stossare Do FORTH-Gesellsc ultraFORTH83
Sonstiges
abort (-) "tick-abort"
Dies ist ein deferred Wort, das mit NOOP vorbesetzt
ist. Es wird in ABORT ausgefuehrt, bevor QUIT
aufgerufen wird. Es kann benutzt werden, um
"automatisch" selbst definierte Stacks zu loeschen.
cold (ee! "tick-cold"
Dies ist ein deferred Wort, das mit NOOP vorbesetzt
ist. Es wird in COLD aufgerufen, bevor die
Einschaltmeldung ausgegeben wird. Es wird benutzt, um
Geraete zu initialisieren oder Anwenderprogramme
automatisch zu starten.
quit (=) "tick-quit"
Dies ist ein deferred Wort, das normalerweise mit
(QUIT besetzt ist. Es wird in QUIT aufgerufen,
nachdem der Returnstack enleert und der
interpretierende Zustand eingeschaltet wurde. Es wird
benutzt, um spezielle Kommandointerpreter (wie z.B. im
Tracer) aufzubauen.
restart (==) "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 Geraete
nach einem Warmstart zu reinitialisieren.
(quit (-- ) "paren-quit"
Dieses Wort ist normalerweise der Inhalt von QUIT.
Es wird von QUIT benutzt. Es akzeptiert eine Zeile
von der aktuellen Eingabeeinheit, fuerht sie aus und
druckt "ok" bzw. "compiling".
status (—-) "dot-status"
Dieses Wort ist ein deferred Wort, das vor dem
Einlesen einer Zeile bzw. dem Laden eines Blocks
ausgefuehrt wird. Es ist mit NOOP vorbesetzt und
kann dazu benutzt werden, Informationen ueber den
Systemzustand oder den Quelltext auszugeben.
bye (--) N
Dieses Wort fuehrt FLUSH und EMPTY aus.
Anschliessend wird der Monitor des Rechners
angesprungen oder eine andere
implementationsabhaengige Funktion ausgefuehrt.
cold ( --
Bewirkt den Kaltstart des Systems. Dabei werden alle
nach der letzten Ausfuehrung von SAVE definierten
Worte entfernt, die Uservariablen auf den Wert
gesetzt, den sie bei SAVE hatten, die Blockpuffer
neu initialisiert, der Bildschirm geloescht und die
Einschaltmeldung "ultraFORTH-83 rev..." ausgegeben.
Anschliessend wird RESTART ausgefuehrt.
7 ultraFORTH83 F-——- rn Glossare Seite 107
end-trace Ü —
Schaltet den Tracer ab, der durch "patchen" der
Next-Routine arbeitet. Die Ausfuehrung des aufrufenden
Wortes wird fortgesetzt.
noop (re)
Tut gar nichts.
R# ( -- adr ) "r-sharp"
adr ist die Adresse einer Variablen, die den Abstand
des gerade editierten Zeichens vom Anfang des gerade
editierten Screens enthaelt. Vergleiche (ERROR und
SCR.
restart ==)
Bewirkt den Warnmstart des Systems. Dieses Wort wird
beim C64 durch Druecken von RUN/STOP - RESTORE
aufgerufen. Es setzt QUIT ,„ ERRORHANDLER und ABORT
auf ihre normalen Werte und fuehrt ABORT aus.
ser ( -- adr ) 83 "Beo-r"
adr ist die Adresse einer Variablen, die die Nummer
des gerade editierten Screens enthaelt. Vergleiche R#
(ERROR und LIST
| Seite 186 blossare == FORTH-Gesellsc ultraFORTH83
Massenspeicher
>drive ( block #drv -- block ) "to-drive"
block ist die Nummer des Blocks block auf dem
Laufwerk #drv, bezogen auf das aktuelle Laufwerk (
Vergleiche OFFSET und DRIVE ) . Beispiel:
5 20 >drive block
holt den Block mit der Nummer 20 vom Laufwerk 5, egal
welches Laufwerk gerade das aktuelle ist.
all-buffers )
Belegt den gesamten Speicherbereich zwischen dem Ende
des Returnstacks und LIMIT mit Blockpuffern.
allotbuffer Fe)
Fuest der Liste der Blockpuffer noch einen weiteren
hinzu, falls oberhalb vom Ende des Retunstacks dafuer
noch Platz ist. FIRST wird entsprechend geaendert.
Vergleiche ALL-BUFFERS
b/blk { -- &1024 )} "bytes pro block"
&1024 ist die Anzahl der Bytes in einem Block.
b/buf (-- nA) "bytes pro buffer"
n ist die Laenge eines Blockpuffers incl. der
Verwaltungsinformationen des Systems.
blk/drv (--n) "blocks pro drive"
n ist die Anzahl der auf dem aktuellen Laufwerk
verfuegbaren Bloecke.
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
FILE . Falls der Block in diesem Puffer UPDATEd und
nicht der Block u ist, dann wird er auf den
Massenspeicher zurueckuebertragen, bevor der
Blockpuffer an den Block u vergeben wird. Befindet
sich der Block u nicht in einem Blockpuffer, so wird
er vom Massenspeicher in einen an ihn vergebenen
Blockpuffer ( s.o.) geladen. Eine Fehlerbedingung
liegt vor, falls u keine Nummer fuer einen vorhandenen
Block ist. Nur Daten im letzten Blockpuffer, der von
BLOCK oder BUFFER vergeben wurde, sind gueltig. Alle
anderen Blockpuffer duerfen nicht mehr als gueltig
angenommen werden. Der Inhalt eines Blockpuffers
sollte nur veraendert werden, wenn die Aenderungen
auch auf den Massenspeicher uebertragen werden sollen.
buffer (u--adr ) 83
Vergibt einen Blockpuffer an den Block u. addr ist die
Adresse des ersten Bytes des Blocks in seinem Puffer.
Dieses Wort entspricht BLOCK , jedoch mit der
Ausnahme, das, wenn der Block noch nicht im Speicher
ist, er nicht vom Massenspeicher geholt wird. Daher
ist der Inhalt dieses Blockpuffers nicht festgelegt.
B ultraFORTH83 F- —_ Glossare Seite 189
convey ( blkl1 bIk2 to.blk -- )
Die Bloecke im Ursprungsbereich von blkl bis b1k2
inclusive werden in den Zielbereich ab Block to.blk
verschoben. Die Bereiche duerfen sich ueberlappen. Ist
blk2 kleiner als blkl, so wird "nein" ausgegeben und
die Ausfuehrung abgebrochen.
copy (altuzı=>))
Der Block ul wird in den Block u2 kopiert. Der alte
Inhalt des Blocks u2 ist verloren.
core? { blik file -- addr/false )"core-question"
Sofern sich der Block blk aus dem File file im
Speicher befindet, ist addr die Adresse des ersten
Bytes des Blocks in seinem Blockpuffer. Befindet sich
der Block nicht im Speicher, so wird false als
Ergebnis geliefert. Vergleiche BUFFER und FILE
drive t 20V — )
Selektiert das Laufwerk #drv als aktuelles. Dann
liefert 0 BLOCK die Adresse des ersten Blocks auf
diesem Laufwerk. Vergleiche >DRIVE und OFFSET.
drv? k bloskn+ S#drv..) "drive-question"
#drv ist das Laufwerk, auf dem sich der Block block
befindet. Vergleiche OFFSET >DRIVE und DRIVE.
empty-buffers ( 7b)
Loescht den Inhalt aller Blockpuffer. UPDATEA
Blockpuffer werden nicht auf den Massenspeicher
zurueckgeschrieben.
file ( -- addr )
addr ist die Adresse einer Uservariablen, deren Wert
die Nummer des aktuellen Files, auf das sich alle
Massenspeicheroperationen beziehen, ist. Typisch
entspricht die Nummer eines Files der Adresse seines
File Control Blocks. Ist der Wert von FILE Null, so
wird direkt, ohne ein File, auf den Massenspeicher
(z.B. die Sektoren einer Diskette) zugegriffen.
m first ( -- addr )
addr ist die Adresse einer Variablen, in der sich ein
Zeiger auf den Blockpuffer mit der niedrigsten Adresse
befindet. Vergleiche ALLOTBUFFER
flush {- ) 83
Fuehrt SAVE-BUFFERS aus und loescht anschliessend
alle Blockpuffer. Vergleiche EMPTY-BUFFERS
freebuffer ==)
Der Blockpuffer, auf den FIRST zeigt, wird, falls
UPDATEd, auf den Massenspeicher gebracht und von der
Liste der Blockpuffer entfernt. FIRST wird
entsprechend veraendert. Der Speicherbereich, in dem
sich dieser Puffer befand, steht damit zur Verfuegung.
Gibt es nur noch einen Blockpuffer, so geschieht
nichts.
Seite 118 blossare ka FORTH-Gesellsc ultraFoRTH83
limit
offset
prev
r/w
( -- addr )
Unterhalb von addr befinden sich die Blockpuffer. Das
letzte Byte des obersten Blockpuffers befindet sich in
addr-1. Vergleiche ALL-BUFFERS ALLOTBUFFER
( -- addr )
addr ist die Adresse einer Uservariablen, die einen
Offset enthaelt. Dieser Offset wird zu der Blocknummer
addiert, die sich bei Aufruf von BLOCK BUFFER usw.
auf dem Stack befindet. Die Summe ergibt die Nummer
des Blocks, der vom Massenspeicher geholt wird.
I: u addr 7
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.
( addr block file n -- flag )"r-w"
Ein deferred Wort, bei dessen Aufruf das
systemabhaengige Wort ausgefuehrt wird, das einen
Block vom Massenspeicher holt. Dabei ist addr die
Anfangsadresse des Speicherbereichs fuer den Block
block, file die Filenummer des Files, in dem sich der
Block befindet und n=0, falls der Block vom
Speicherbereich in den Massenspeicher gebracht werden
soll. Ist n=1, so soll der Block vom Massenspeicher in
den Speicherbereich gelesen werden. Das flag ist
Falsch, falls kein Fehler auftrat, sonst Wahr.
save-buffers (==) 83
update
Der Inhalt aller Blockpuffer, die als UPDATEd
gekennzeichnet sind, wird in ihre korrespondierenden
Massenspeicherbloecke zurueckgeschrieben. Alle
Blockpuffer werden als unveraendert gekennzeichnet,
bleiben aber an ihre Bloecke vergeben.
Gr) 83
Der zuletzt mit BLOCK BUFFER usw. zugegriffene Block
wird als veraendert gekennzeichnet. Bloecke mit
solcher Kennzeichnung werden auf den Massenspeicher
zurueckgeschrieben, wenn ihr Blockpuffer fuer einen
anderen Block benoetigt oder wenn SAVE-BUFFERS
ausgefuehrt wird. Vergleiche PREV
u ultraFORTHBI3 F- — —---- if blossare sem li
(bload
(bsave
1541r/w
?device
C64-spezifische Worte
( -- flag )
laedt ein File von einem externen Geraet. Ein Feh-
ler beim Laden wird durch flag <> FALSE angezeigt.
Die File- Parameter muessen in der Zeropage abge-
legt sein. Siehe (BSAVE .
( -- flag )
speichert ein File auf ein externes Geraet. Ist
flag = FALSE , so war das Abspeichern erfolgreich,
sonst ist flag <> FALSE. (BLOAD setzt voraus, dass
die File- Parameter in der Zeropage abgelegt sind:
ADR Typ Bedeutung
OAE Wort Endadresse des Files +1
0B7 Byte Laenge des Filenamens
OBA Byte Device Nummer
OBB Wort Adresse des Filenamens
0C1 Wort Anfangsadresse des Files
Vergleiche (BLOAD .
( adr blk file r/wf -- flag ) "15-41-r-w"
liest oder schreibt einen Block Daten ($400
(&1024) Bytes) vom Diskettenblock blk nach adr
bzw. von adr auf den Diskettenblock blk. Ist
r/wf = FALSE , so wird auf die Diskette geschrie-
ben, ist r/wf <> FALSE , so wird von der Diskette
gelesen. 1541R/W ermittelt die zu lesenden bzw. zu
beschreibenden Sektoren, fuehrt das Lesen bzw.
Schreiben aus und prueft auf alle moeglichen Feh-
ler. Vergleiche RW .
file ist die Nummer des Files, dem der zu uebertra-
gende Block zugeordnet ist. Zur Zeit ist aus-
schliesslich der Direktzugriff auf die Diskette
realisiert. Deshalb wird eine Fehlerbehandlung ein-
geleitet, wenn file <> O0 ist.
( dev# -- ) "question-device"
prueft, ob das Geraet mit der Nummer dev# am seri-
ellen Bus anwesend ist. Meldet sich das Geraet
nicht, so wird eine Fehlerbehandlung eingeleitet.
Ein Fehler liegt vor, wenn dev# nicht die Bedin-
gung 4 =< dev# =< $0F (&15) erfuellt. Typische
dev# sind 8 fuer das Diskettenlaufwerk und 4 fuer
den Drucker.
Seite 112 1 Slossare = Formsesenze]t UltraFORTNES
bus!
bus@®
busclose
busin
businput
busoff
busopen
busout
(8b --) "bus-store"
gibt 8b ueber den seriellen Bus aus. Ein Fehler
liegt vor, wenn die Ausgabe nicht vorbereitet wur-
de. (2.B. durch BUSOUT oder BUSOPEN).
( -- 8b) "bus-fetch" -
holt 8b vom seriellen Bus. Ein Fehler liegt vor,
wenn die Eingabe nicht vorbereitet wurde. (Z.B.
durch BUSIN).
( dev# 2nd -- )
beendet die Ausgabe an oder die Eingabe vom Geraet
mit der Nummer dev# in bzw. aus einer mit BUSOPEN
eroeffnete Datei. BUSCLOSE braucht nicht mit
BUSOFF abgeschlossen werden. Weiteres Verhalten
siehe BUSOUT .
( dev# 2nd -- ) .
bereitet die Eingabe ueber den seriellen Bus vom
Geraet mit der Nummer dev# vor. Verhaelt sich
sonst wie BUSOUT , siehe dort.
(adrü--)
holt u Zeichen vom seriellen Bus und legt sie im
Speicher ab adr ab. Ein PAUSE wird ausgefuehrt.
Ein Fehler liegt vor, wenn die Eingabe nicht vorbe-
reitet wurde. (Z.B. durch BUSIN).
( )
gibt den seriellen Bus und den Semaphor I/O frei.
Vergleiche BUSIN , BUSOUT , BUSOPEN , BUSCLOSE und
I/O , LOCK , UNLOCK .
( dev# 2nd -- )
bereitet die Ausgabe ueber den seriellen Bus auf
das Geraet mit der Nummer dev# vor und teilt dem
Geraet mit, dass alle nachfolgenden Zeichen bis
zum naechsten BUSOFF als Dateiname aufzufassen
sind. Dient zur Vorbereitung von Ein- oder Ausga-
ben von bzw. in Dateien auf Diskette. Weiteres Ver-
halten siehe BUSOUT .
( dev 2nd -- )
bereitet die Ausgabe ueber den seriellen Bus auf
das Geraet mit der Nummer dev# vor. Meldet sich
das Geraet nicht, so wird eine Fehlerbehandlung
eingeleitet, sonst bekommt das Geraet den Wert 2nd
zugesandt. Zulaessige Werte sind 4 =< dev# =< $0F
(&15) und O0 =< 2nd =< $1F (&31) anderenfalls liegt
ein Fehler vor. Der Semaphor I/O wird gesperrt und
damit der serielle Bus vor dem Zugriff durch ande-
re Tasks geschuetzt (Vergleiche LOCK , 1/0). Ver-
gleiche BUSOFF , BUSIN , BUSOPEN , BUSCLOSE .
| ultraFORTH83 ic) 1985 bprksrre/ue FOR Glossare Seite 113
bustype ( adr-u=*@)
gibt u Zeichen, die ab adr im Speicher stehen,
ueber den seriellen Bus aus. Ein PAUSE wird ausge-
fuehrt. Ein Fehler liegt vor, wenn die Ausgabe
nicht vorbereitet wurde. (Z.B. durch BUSOUT oder
BUSOPEN).
c64at ( row col -- ) "e-64-at"
positioniert den Cursor in die Zeile row und die
Spalte col. Ein Fehler liegt vor, wenn row > $18
(&24) oder col > $27 (&39) ist. Vergleiche AT
c64at? {( = zowWcol) "e-64-at-question"
ermittelt die aktuelle Cursorposition und legt die
Nummer der Zeile row und die Nummer der Spalte col
nacheinander auf den Stack. Vergleiche AT?
c64cr (a "c=b4=-c-T"
ein Wagenruecklauf wird auf die Console gegeben.
Vergleiche CR . Es wird immer die Console angespro-
chen. Ein PAUSE wird ausgefuehrt.
c64decode ( adr lenO key -- adr leni ) "c-64-decode"
wertet key aus. Ist key weder #BS noch #CR , so
wird key in der Speicherstelle adr + lenO abge-
legt, das Zeichen als Echo zum Ausgabegeraet ge-
sandt und lenO inkrementiert. Im Falle von #BS
wird das letzte Echo geloescht und lenO dekremen-
tiert, bei #CR wird lenO nicht veraendert und in
die Variable SPAN kopiert. Vergleiche DECODE . Sol-
len andere Zeichen (z. B. Cursortasten) ausgewer-
tet werden, so ist ein USERdecode zu schreiben und
in die Input-Struktur einzuhaengen. Vergleiche
INPUT: und EDIDECODE
c64del (u "a-64-del"
ueberschreibt das Zeichen links vom Cursor mit ei-
nem SPACE und positioniert den Cursor darauf. Ver-
gleiche DEL . Siehe C64CR fuer weiteres Verhalten.
c64emit ( 8b -- ) "o-64-emit"
gibt 8b auf die Console aus. Alle nicht druckbaren
(Steuer-) Zeichen werden durch einen Punkt er-
setzt. Es wird immer die Console angesprochen. Ein
PAUSE wird ausgefuehrt. Vergleiche EMIT und
OUTPUT:
c64expect ( adr len -- ) "e-64-expect"
erwartet len Zeichen vom Eingabegeraet, die ab adr
im Speicher abgelegt werden. Ein Echo der Zeichen
wird ausgegeben. CR beendet die Eingabe vorzeitig.
Ein abschliessendes Leerzeichen wird immer ausgege-
ben. Die Laenge der empfangenen Zeichenkette wird
in der Variablen SPAN uebergeben. Vergleiche
EXPECT . Siehe auch EDIEXPECT
| Seite 114 Glossare = FORTH-Gesellsc ultraFoRTH83
c64init
c64key
c64key?
c64page
c64type
con!
curoff
curon
derror?
(==) "o-64-init"
initialisiert den C64. Neben der normalen Re-
set-Initialisierung wird das basic-ROM abgeschal-
tet, Rahmen-, Bildschirm- und Zeichenfarbe aus
INK-POT gesetzt, Repeat fuer alle Tasten einge-
schaltet und der Modus Gross/Kleinschrift ge-
waehlt. C64INIT wird typisch durch COLD oder
RESTART aufgerufen.
(vemı8B ) "c-64-key"
wartet auf einen Tastendruck. Waehrend der Warte-
zeit wird PAUSE ausgefuehrt. Der cbm-Code des Tas-
tendrucks wird auf den Stack gelegt. Steuerzeichen
werden nicht ausgewertet, sondern unveraendert ab-
geliefert. Vergleiche KEY .
cf) "c-64-key-question"
prueft, ob eine Taste gedrueckt wurde und hinter-
laesst dann f = TRUE , wurde keine Taste ge-
drueckt, so ist f = FALSE . Vergleiche KEY?
{-- ) "e-564-page"
loescht den Bildschirm und positioniert den Cursor
in die linke obere Ecke. Vergleiche PAGE . Siehe
C6ACR fuer weiteres Verhalten.
( adr len -- ) "e-64-type"
gibt den String, der im Speicher bei adr beginnt
und die Laenge len hat, auf die Console aus. Wirkt
immer auf die Console. Alle nicht druckbaren
(Steuer-) Zeichen werden durch einen Punkt er-
setzt. Ein PAUSE wird ausgefuehrt. Vergleiche
TYPE , OUTPUT: und C64EMIT .
( Bu — ) "con-store"
gibt 8b auf die CONsole aus. Es wird immer der
Bildschirm angesprochen. Alle Steuerzeichen werden
zur Console gesandt. Ein PAUSE wird ausgefuehrt.
schaltet den Cursor aus.
( )
schaltet den Cursor ein.
(==) “ "derror-question"”
prueft den Fehlerkanal des aktuellen Diskettenlauf-
werks. Ist die Fehlernummer kleiner als $0A (&10)
(das heisst, kein Fehler), so ist f = FALSE .
Liegt ein Fehler vor, so wird f = TRUE und die gan-
ze Fehlermeldung in der Form NN, Fehlertext, TT,SS
ausgegeben. Dabei ist NN die Fehler-Nummer, TT die
Track- uns SS die Sektor-Nummer, bei der der Feh-
ler auftrat (alle Zahlen in decimal).
u ultraFORTH83 FR - == Glossare sie is 115
diskclose Ku) "disk-close"
schliesst den mit DISKOPEN eroeffneten Disketten-
kanal wieder. DISKCLOSE ist zum Abschluss von
DISKOPEN vorgesehen. Vergleiche READSECTOR und
WRITESECTOR .
diskopen (ei -=r2) "disk-open"
oeffnet den Disketten-Kanal $0D (&13) fuer nachfol-
gende Lese- oder Schreib-Vorgaenge im direkten Zu-
griff auf die Diskette. DISKOPEN sollte die Aus-
und Eingabe mit READSECTOR und WRITESECTOR vorbe-
_ reiten. Ist das Oeffnen des Disketten-Kanals er-
folgreich, so ist f = FALSE , sonst ist f = TRUE
display (--)
ein mit OUTPUT: definiertes Wort, das den Bild-
schirm als Ausgabegeraet setzt, wenn es ausge-
fuehrt wird. Die Worte EMIT , CR , TYPE , DEL ,
PAGE , AT und AT? beziehen sich dann auf den Bild-
schirnm. -
findex (Eromı ton!)
liest, unter Umgehung des BLOCK-Mechanismus, die
ersten Zeilen der Blocks from bis to einschliess-
lich nach PAD und gibt sie aus. Der Bereich PAD
bis PAD $100 + wird von FINDEX benutzt. FINDEX
kann mit einer beliebigen Taste angehalten und mit
RUN/STOP abgebrochen werden. Vergleiche dazu
STOP? . Die Block-Buffer werden nicht veraendert.
Vergleiche auch READSECTOR .
getkey { = 8b)
holt den cbm-Code des jeweils naechsten Tasten-
drucks und legt ihn auf den Stack. War keine Taste
gedrueckt, so ist 8b = FALSE . (Vergleiche KEY?)
GETKEY liest direkt aus dem Tastaturpuffer.
i/o ( -- semaphoradr ) "i-o"
ein Semaphor (Ampel) (eine spezielle Variable).
I/O schuetzt den seriellen Bus vor dem Zugriff
durch andere Prozesse, wenn er von einem benutzt
wird. Ist der Inhalt von I/O FALSE , so ist der
Weg zum seriellen Bus fuer alle Prozesse freigege-
ben. Alle im System enthaltenen Routinen sind abge-
sichert. Der Benutzer muss bei eigenen Routinen
selbst fuer eine Absicherung sorgen. Vergleiche
LOCK , UNLOCK und die Beschreibung des Taskers.
index ( from to -- )
liest die BLOCKs from bis to einschliesslich und
gibt deren erste Zeilen aus. INDEX kann mit einer
beliebigen Taste angehalten und mit RUN/STOP abge-
brochen werden. Vergleiche dazu STOP? . Die ersten
Zeilen von Screens enthalten typisch Kommentare,
die den Inhalt charakterisieren.
Seite 116 Glossare bp/ksfrerwe FORTH-Gesellsc ultraFORTH83
ink-pot { ==. adr )
ein Byte-Feld von 3 mal 4 Byte Laenge, in denen
fuer 3 verschiedene Zwecke (Einschalt-, Editor-
und User-Farben) die Rahmen-, Bildschirm-, Zei-
chen-Farbe und ein Dummy-Byte abgelegt sind. Zur
Farbaenderung ist die gewuenschte Farb-Nummer
(0-&15) in das entsprechende Byte zu schreiben.
keyboard | Ba)
ein mit INPUT: definiertes Wort, das als Eingabege-
raet die Tastatur setzt. Die Worte KEY , KEY? ,
DECODE und EXPECT beziehen sich auf die Tastatur.
Steuerzeichen werden nicht ausgewertet. Siehe
C6AKEY , C64AKEY? „ C6ADECODE und C64AEXPECT. Ver-
gleiche INPUT: , STANDARDI/O und EDIBOARD .
printable? (8b bl!) "printable"
f ist TRUE , wenn 8b ein druckbares Zeichen ist,
sonst ist f = FALSE .
readsector ( adr tra# sec -- f )
liest alle $100 (&256) Bytes des Sektors sec# von
Spur tra# der Diskette im aktuellen Laufwerk ueber
den seriellen Bus und legt sie ab adr im Speicher
ab. War das Lesen erfolgreich, so ist f = FALSE ,
sonst ist f£f <> FALSE und die Fehlermeldung des
Laufwerks wird ausgegeben. Im Fehlerfall wird der
Speicherinhalt ab adr nicht veraendert. Der Disket-
ten-Kanal $0D (&13) muss fuer READSECTOR offen
sein (vergleiche DISKOPEN).
writesector ( adr tra# sec# -- f )
schreibt $100 (&256) Bytes, die ab adr im Speicher
stehen, ueber den seriellen Bus in den Sektor sec#
der Spur tra# auf der Diskette im aktuellen Lauf-
werk. War das Schreiben erfolgreich, so ist f =
FALSE , sonst ist f <> FALSE und die Fehlermeldung
des Laufwerks wird ausgegeben. Der Disketten-Kanal
$0D (&13) muss fuer WRITESECTOR offen sein (ver-
gleiche DISKOPEN).
| ultraFORTH83 I 1985 bp/ksf/re/ue u Glossare J Seite il?
Multitasking Worte
s ( Tadr -- usradr ) "tick-s"
wird benutzt in der Form:
<taskname> s <uname> i
liest den Namen einer Uservariablen <uname> und
hinterlaesst die Adresse usradr dieser Uservari-
able in der durch Tadr gekennzeichneten Task.
Typisch wird Tadr durch Nennung von <taskname> er-
— zeugt. Eine Fehlerbedingung liegt vor, wenn
<uname> nicht der Name einer Uservariablen ist.
Vergleiche USER und TASK . S ist fuer die Veraen-
derung des Inhalts von User-Variablen einer Task
durch eine andere Task vorgesehen.
activate ( Tadr -- )
aktiviert die Task, die durch Tadr gekennzeichnet
ist, und weckt sie auf. Tadr wird typisch durch
Nennung eines Task-Namens erzeugt. Vergleiche
SLEEP , STOP , PASS , PAUSE , UP@ , UP! und WAKE
lock ( semadr -- )
der Semaphor, dessen Adresse auf dem Stack liegt,
wird von der Task, die LOCK ausfuehrt, blockiert.
Dazu prueft LOCK den Inhalt von semadr. Zeigt der
Inhalt an, dass eine andere Task den Semaphor
blockiert hat, so wird PAUSE ausgefuehrt, bis der
Semaphor freigegeben ist. Ist der Semaphor freige-
geben, so schreibt LOCK ein Kennzeichen der Task,
die LOCK ausfuehrt, in den Semaphor und sperrt ihn
damit fuer alle anderen Tasks. Den Code zwischen
semadr LOCK ... und ... semadr UNLOCK kann also
immer nur eine Task ausfuehren. Vergleiche UNLOCK
und die Beschreibung des Taskers.
multitask GC)
schaltet das Multitasking ein. Das Wort PAUSE ist
— nach Ausfuehrung von MULTITASK keine NOOP-Funktion
mehr, sondern gibt die Kontrolle ueber den Prozes-
sor an eine andere Task weiter. .
pass nd ... ner Tadr Fr N
aktiviert die Task, die durch Tadr gekennzeichnet
ist, und weckt sie auf. Tadr wird typisch durch
Nennung eines Task-Namens erzeugt. r gibt die An-
zahl der Parameter nO bis nr-1 an, die vom Stack
der PASS ausfuehrenden Task auf den Stack der
durch Tadr gekennzeichneten Task uebergeben wer-
den. Die Parameter nO bis nr-1 stehen der durch
Tadr gekennzeichneten Task zur weiteren Verarbei-
tung zur Verfuegung. Vergleiche STOP , ACTIVATE ,
PAUSE , UP@ und UP!
| Seite 118 [ Glossare = FORTH-Gesellsce ultraFORTH33
pause (--)
eine NOOP-Funktion, wenn der Singletask-Betrieb
eingeschaltet ist; bewirkt iedoch, bei aktiviertem
Multitasking, dass die Task, die PAUSE ausfuehrt,
Jie Kontrolle ueber den Prozessor an eine andere
Task abgibt. Existiert nur eine Task, oder schla-
fen alle anderen Tasks, so wird die Kontrolle un-
verzueglich an die Task zurueckgegeben, die PAUSE
ausfuehrte. Ist mindestens eine andere Task aktiv,
so wird die Kontrolle des Prozessors von dieser
uebernommen und erst bei erneuter Ausfuehrung von
PAUSE oder STOF an eine andere Task weitergegeben.
Da die Tasks zyklisch miteinander verkettet sind,
erhaelt die Task, die zuerst PAUSE ausfuehrte,
irgendwann die Kontrolle zurueck. Eine Fehlerbs-
dingung liegt vor, wenn eine Task weder PAUSE noch
STOP ausfuehrt. Vergleiche STOP , MULTITASK und
SINGLETASK
rendezvous ( semadr -- )
gibt den Semaphor mit der Adresse semadr frei und
fuehrt PAUSE aus, um anderen Tasks den Zugriff auf
das durch diesen Semaphor geschuetzte Geraet zu er-
moeglichen. Anschliessend wird LOCK ausgefuehrt,
um das Geraet zurueck zu erhalten. Vergleiche LOCK
und UNLOCK
singletask (—-)
schaltet das Multitasking aus. Das Wort PAUSE ist
nach Ausfuehrung von SINGLETASK eine NOOP-Funk-
tion. Eine Fehlerbedingung liegt vor, wenn eine
Hintergrundtask SINGLETASK ohne anschliessendes
MULTITASK ausfuehrt, da die MAIN- oder TERMINAL-
TASK dann nicht mehr die Kontrolle ueber den Pro-
essor bekommt. Vergleiche UP®@ und UP!
sleep ( Tadr -- )
bringt die Task, die durch Tadr gekennzeichnet
ist, zum Schlafen. Tadr wird typisch durch Nennung
eines Task-Namens erzeugt. SLEEP hat den gleichen
Effekt, wie die Ausfuehrung von STOP durch die
Task selbst. Der Unterschied ist, dass STOP in der
Regel ein Endpunkt in der Bearbeitung ist, SLEEP
trifft die Task zu einem nicht vorhersehbaren Zeit-
punkt, so dass die laufende Arbeit der Task unter-
brochen wird. Vergleiche WAKE
stop (. ==.) ;
bewirkt, dass die Task, die STOP ausfuehrt, sich
schlafen legt. Der Inhalt des IP (Interpretive
Pointer), des RP (Returnstack Pointer) und des SP
(Stack Pointer) werden gesichert, dann wird die
Kontrolle ueber den Prozessor an die naechste Task
abgegeben. Diese Aktionen werden ebenfalls von
PAUSE ausgefuehrt (siehe dort), der Unterschied zu
A ultraFORTH83 En SSERIBEIErREGE =) Glossare i Seite 119
PAUSE ist, dass die Task bei STOP inaktiv hinter-
lassen wird, bei PAUSE dagegen aktiv. Vergleiche
auch ACTIVATE , PASS , WAKE , SLEEP , UP@ und
UP! .
Task ( rlen slen -- )
wird benutzt in der Form:
rlen slen Task <cccc>
Task ist ein definierendes Wort, das eine Task -
den Arbeitsbereich fuer ein weiteres Programm, das
gleichzeitig zu den schon laufenden Programmen ab-
laufen soll - einrichtet. Die Task erhaelt den
nr Namen cccc, hat einen Stack von der Groesse slen
und einen Returnstack von rlen Bytes. Im Stack-Be-
reich liegen das task-eigene Dictionary (ein-
schliesslich PAD), das in Richtung zu hoeheren
Adressen waechst und der Stack, der zu niedrigeren
Adressen hin waechst. Im Returnstack-Bereich befin-
den sich die task-eigene Userarea (waechst zu hoe-
heren Adressen), und der Returnstack (wird gegen
kleinere Adressen groesser). Eine Task ist damit
eine verkleinertes Abbild des gesamten ultra-
FORTH-Systems.
Die Ausfuehrung von cccc in einer beliebigen Task
hinterlaesst die gleiche Adresse, die die Task
cccc selbst mit UP@ erzeugt. Diese Adresse wird
von S , ACTIVATE , LOCK ,„ PASS , SLEEP , TASK und
WAKE benutzt.
tasks (=
listet die Namen aller eingerichteten Tasks und
zeigt, ob sie schlafen oder aktiv sind.
unlock ( semadr -- )
gibt den Semaphor, dessen Adresse auf dem Stack
liegt, fuer alle Tasks frei. Ist der Semaphor im
Besitz einer anderen Task, so muss die UNLOCK aus-
m fuehrende Task mit PAUSE auf die Freigabe warten.
Vergleiche LOCK und die Beschreibung des Taskers.
up® ( -- Tadr ) "u-p-fetch"
liefert die Adresse Tadr des ersten Bytes der User-
area der Task, die UP@ ausfuehrt. Tadr ist die
Adresse, die jede Task kennzeichnet. Vergleiche
dazu S , ACTIVATE , LOCK , PASS , SLEEP , TASK
und WAKE . In der Userarea sind Variablen und ande-
re Datenstrukturen hinterlegt, die jede Task fuer
sich haben muss. Vergleiche UP!
_Seite 178
up!
wake
blossare WB — —- ultraFORTH83
FORTH-Gesellsc
( ad2ı. == ) "u-p-store"
richtet den UP (User Pointer) auf adr. Vergleiche
UP®@ .
( Tadr -- )
weckt die Task, die durch Tadr gekennzeichnet ist,
auf. Tadr wird typisch durch Nennung eines Task-Na-
mens erzeugt. Die Task fuehrt ihren Code dort wei-
ter aus, wo sie durch SLEEP angehalten wurde oder
wo sie sich selbst durch STOP beendet hat (Vor-
sicht!) . Vergleiche SLEEP, STOP, ACTIVATE und
PASS
| ultraFORTHB3 ic} 1985 bpr/ksirerue FORTI Glossare Seite i?i
Input und Output Worte
#bs e em) "number-b-s"
n ist der Wert, den man durch KEY erhaelt, wenn
die Backspace- (Delete-) Taste gedrueckt wird.
#cr ( =) “"number-c-r"
eine Konstante, die den Wert liefert, den man
durch KEY erhaelt, wenn die Return-Taste gedrueckt
u wird.
#tib ( -- adr ) 83 "number-t-i-b"
eine Variable, die die Laenge des aktuellen Textes
im Text-Eingabe-Puffer haelt. Vergleiche TIB
-trailing ( adr +nO-- adr +nl ) 83 "dash-trailing"
adr ist die Anfangsadresse und +tnD die Laenge ei-
nes Strings. -TRAILING veraendert +nO so zu +tnl,
dass eventuell abschliessende Leerzeichen nicht
mehr in der neuen Stringlaenge +tnl enthalten sind.
Der String selbst bleibt unangetastet. Ist
+nO = 0, so ist auch tni1 = 0. Besteht der ganze
String aus Leerzeichen, so ist +nl = 0.
(n--) 83 "dot"
druckt n vorzeichenbehaftet aus.
so” (==) 83 I C "dot-quote"
[-) compiling
wird in :-Definitionen in der Form verwendet:
<mamert 24." Sece" Mi:
Der String cccc wird bis zum abschliessenden " so
compiliert, dass bei Ausfuehrung von <name> der
String cccc ausgedruckt wird. Das Leerzeichen nach
" und das abschliessende " sind Pflicht und gehoe-
ren nicht zum String.
vo; el =) 83 I "dot-paren"
=J5 compiling
wird in der Form:
. .( :CECE)
benutzt und druckt den String cccce bis zur ab-
schliessenden Klammer sofort aus. Das Leerzeichen
nach .( und die schliessende Klammer sind Pflicht
und gehoeren nicht zum String.
Er Gen -=9) "dot-r"”
druckt die Zahl n in einem +n langen Feld mit Vor-
zeichen rechtsbuendig aus. Reicht tn nicht zur Dar-
stellung der Zahl aus, so wird ueber den rechten
Rand hinaus ausgegeben. Die Zahl n wird in jedem
Fall vollstaendig dargestellt.
Seite 127 | Glossare = ra UltraFORTHB3
>tib
at
at?
base
bl
e/l
col
er
( -- adr ) 83 "tortib"
adr ist die Adresse eines Zeigers auf den Text-Ein-
gabe-Puffer. Siehe TIB .
(+) "question-c-r"
prueft, ob in der aktuellen Zeile mehr als C/L -
$0A (&10) Zeichen ausgegeben wurden und fuehrt
dann CR aus.
( row col -- )
positioniert die Schreibstelle eines Ausgabegerae-
tes in die Zeile row und die Spalte col. AT ist ei-
nes der ueber OUTPUT vektorisierten Worte.
( -- row col ) "at-question"
ermittelt die aktuelle Position der Schreibstelle
eines Ausgabe-Geraetes und legt Zeilen- und Spal-
tennummer auf den Stack. Eines der OUTPUT-Worte.
Gr adıer) 83.0
adr ist die Adresse einer Uservariablen, die die
Zahlenbasis enthaelt, die zur Wandlung von Zah-
len-Ein- und Ausgaben benutzt wird.
C -- 16b ) "b-Ll"
16b ist der ASCII-Wert fuer das Leerzeichen.
( -- 40) "characters-per-line"
+n ist die Anzahl der Zeichen pro Bildschirm-Zei-
le.
= a)
u ist die Spalte in der die Schreibstelle eines
Ausgabe-Geraetes sich gerade befindet. Vergleiche
ROW und AT?
(er) It"
bewirkt, dass die Schreibstelle eines Ausgabe-Ge-
raetes an den Anfang der naechsten Zeile verlegt
wird. Eines der OUTPUT-Worte.
(d--) "d-dot"
druckt d vorzeichenbehaftet aus.
(d+n--) "d-dot-r"
druckt d vorzeichenbehaftet in einem +n Zeichen
breiten Feld rechtsbuendig aus. Reicht +n nicht
zur Darstellung der Zahl aus, so wird ueber den
rechten Rand hinaus ausgegeben. Die Zahl d wird in
jedem Fall vollstaendig dargestellt.
| ultraFORTHöS ic} 1985 bprks/re/we zu blossare i Seite 1731|
decimal
decode
del
emit
expect
hex
input
key
( )
stellt BASE auf $0A (&10) ein. Alle Zahlenein- und
Ausgaben erfolgen im dezimalen Zahlensysten.
( adr +nO key -- adr +nil )
wertet key aus. Typisch werden normale druckbare
ASCII-Zeichen in die Speicherstelle adr + +nO
uebertragen, als Echo zum Ausgabegeraet gesandt
und +nO inkrementiert. Andere Zeichen (#BS, #CR,
Steuercodes) koennen andere Aktionen zur Folge ha-
ben. Eines der ueber INPUT vektorisierten Worte.
Vergleiche C64DECODE . Wird von EXPECT benutzt.
Fre)
loescht das letzte ausgesandte Zeichen. Eins der
OUTPUT-Worte. Bei Druckern ist die korrekte Funk-
tion nicht garantiert.
( 26b ==) 83
die unteren 7 Bit (commodore - Benutzer: Achtung:
die unteren 8 Bit) werden ausgegeben. Ist das Zei-
chen nicht druckbar, (insbesondere alle Steuerco-
des) so wird stattdessen ein "." ausgegeben. Eines
des OUTPUT-Worte.
( adr +tn -- ) 833
empfaengt Zeichen und speichert sie im Speicher.
Die Uebertragung beginnt bei adr und setzt sich zu
hoeheren Adressen fort, bis ein Return erkannt
oder +n Zeichen uebertragen sind. Ein Return wird
nicht mit abgespeichert. Wenn +n = 0 ist, so wer-
den keine Zeichen uebertragen. Alle empfangenen Z-
eichen werden als Echo, statt des Return wird ein
Leerzeichen ausgegeben. Vergleiche SPAN . Eines
der ueber INPUT vektorisierten Worte.
( )
stellt BASE auf $10 (&16) ein. Alle Zahlenein- und
Ausgaben erfolgen im hexadezimalen Zahlensystem.
( -- adr ) U
adr ist die Adresse einer Uservariablen, die einen
Zeiger auf ein Feld von (zur Zeit) 4 Kompila-
tions-Adressen enthaelt, die fuer ein Eingabe-Ge-
raet die Funktionen KEY KEY? DECODE und EXPECT
realisieren. Vergleiche die gesonderte Beschrei-
bung der INPUT- und OUTPUT-Struktur.
( -- 16b ) 83
empfaengt ein Zeichen von einem Eingabe-Geraet.
Die niederwertigen 7 Bit (commodore 8 Bit) enthal-
ten den ASCII- (commodore-) Code des zuletzt em-
pfangenen Zeichens. Alle gueltigen ASCII- (commo-
dore-) Codes koennen empfangen werden. Steuerzei-
chen werden nicht ausgewertet, sondern so, wie sie
| Seite 124 blossare = FORTH-Gesellsc
ultraFORTH83
sind, abgeliefert. Es wird kein Echo ausgesandt.
KEY wartet, bis tatsaechlich ein Zeichen empfangen
wurde. Eines der INPUT-Worte.
key? ( -- flag ) "key-question"
flag ist TRUE, wenn ein Zeichen zur Eingabe bereit-
steht, sonst ist flag FALSE . Eins der INPUT-Wor-
te.
list {u®=) 83
zeigt den Inhalt des Screens u. SCR wird auf u ge-
setzt. Siehe BLOCK.
1/s — tm) "lines-per-screen"
+n ist die Anzahl der Zeilen pro Bildschirmseite.
output ( = ade I U
adr ist die Adresse einer Uservariablen, die einen
Zeiger auf ein Feld von (zur Zeit) 7 Kompila-
tions-Adressen enthaelt, die fuer ein Ausgabe-Ge-
raet die Funktionen EMIT , CR , TYPE , DEL
P-
AGE ,„ AT und AT? realisieren. Vergleiche die geson-
derte Beschreibung der INPUT- und OUTPUT-Struktur.
page (--)
bewirkt, dass die Schreibstelle eines Ausgabege-
raetes auf eine leere neue Seite bewegt wird. Ver-
gleiche CG6APAGE. Eines der OUTPUT-Worte.
query ) 83
Zeichen werden von einem Eingabe-Geraet geholt und
in den Text-Eingabe-Puffer, der bei TIB beginnt,
uebertragen. Die Uebertragung endet beim Emfang
von Return oder wenn die Laenge des Text-Einga-
be-Puffers erreicht ist. Die Werte von >IN und BLK
werden auf 0 gesetzt und SPAN wird nach #TIB ko-
piert. Um Text aus dem Puffer zu lesen, kann WORD
benutzt werden. Siehe EXPECT und "Quelltext".
row (nn) N
n ist die Zeile, in der die Schreibstelle eines
Ausgabe-Geraetes sich gerade befindet. Vergleiche
COL und AT?
space CE) 83
sendet ein Leerzeichen an das Ausgabe-Geraet.
spaces (a7 83
sendet tn Leerzeichen an ein Ausgabe-Geraet. Ist
+n = 0, so wird nichts ausgesandt.
u ultraFORTH83 ic) 1985 bprks/re/ue FORT| Glossare Seite 125
span ( -- adr ) 83
der Inhalt der Variablen SPAN gibt an, wieviele
Zeichen vom letzten EXPECT uebertragen wurden. Sie-
he EXPECT
standardi/o ( -- ) "standard-i-o"
stellt sicher, dass die beim letzten SAVE bestimm-
ten Ein- und Ausgabegeraete wieder eingestellt
sind.
stop? ( -- flag ) "stop-question"
steht vom Eingabe-Geraet ein Zeichen zur Verfue-
gung, so wird es geholt. Ist es #CR (commodore
RUN/STOP bzw. Ctrl-C), so ist flag = TRUE, sonst
wird auf das naechste Zeichen gewartet. Ist dieses
jetzt = #CR (RUN/STOP) so wird STOP? mit TRUE ver-
lassen, sonst mit FALSE .
tib („Ss adr) 8 "tib"
liefert die Adresse des Text-Eingabe-Puffers. Er
wird benutzt, um die Zeichen vom Quelltext des ak-
tiven Eingabe-Geraetes zu halten. Er kann mindes-
tens $50 (&80) Zeichen aufnehmen. Siehe >TIB .
type ( adr +n -- ) 83
sendet +n Zeichen, die ab adr im Speicher abgelegt
sind, an das aktive Ausgabegeraet. Ist +n = 0, so
wird nichts ausgegeben.
u. (ü&-) "u-dot"
die Zahl u wird vorzeichenlos ausgedruckt.
ur (u+tn--) "u-dot-r"
druckt die Zahl u in einem +n langen Feld ohne Vor-
zeichen rechtsbuendig aus. Reicht +n nicht zur Dar-
stellung der Zahl aus, so wird ueber den rechten
Rand hinaus ausgegeben. Die Zahl u wird in jedem
Fall vollstaendig dargestellt.
Glossare
Seite 126 bp/ks/re/ue FORTH-Gesallseı ultraFORTHB3
Ergänzungen / Berichtigungen des Glossars
Im folgenden werden Änderungen und Ergänzungen des Glossars
zusammengefaßt. Hierbei wurden außer Worten des Forth-Kerns
auch einige andere - im Lieferumfang enthaltene - Worte
mitaufgenommen, um die Übersicht zu verbessern.
Vergleiche hierzu auch "Änderungen seit rev. 3.5"
Nachtrag
Create (—-) 83
Ein definierendes Wort, das in der Form
Create <name>
benutzt wird. Es erzeugt einen Kopf für <name>. Die
nächste freie Stelle im Dictionary (vergleiche HERE
und DP ) ist nach einem CREATE <name> das erste
Byte des Parameterfeldes von <name>. Wenn <name>
ausgeführt wird, legt es die Adresse seines Parame-
terfeldes auf den Stack. CREATE reserviert keinen
Speicherplatz im Parameterfeld von <name>.
Das Verhalten von <name> kann mit DOES> verändert
werden.
sate: (=
Ein definierendes Wort, das in der Form
Create: <name> .. ;
benutzt wird. Es wirkt wie : mit der Ausnahme, daß
bei Ausführung von <name> die Parameterfeldadresse
von <name> auf den Stack gebracht, das Wort jedoch
nicht ausgeführt wird.
exit (==) 83,C
Wird in einer :-Definition benutzt. Bei Ausführung
von EXIT wird in das diese :-Definition aufrufende
Wort zurückgekehrt. Eine Fehlerbedingung besteht,
wenn das oberste Element des Returnstacks keine
Rückkehradresse enthält. EXIT darf nicht innerhalb
von DO .. LOOP verwendet werden.
order (—-)
Bei Aufruf wird die aktuelle Suchreihenfolge (s.
"Definition der Begriffe") ausgegeben. Anschließend
wird das Vokabular ausgegeben, in das neue Worte
eingetragen werden.
ultraFoRTHE3
623 1908 bprma/rarue rorj Blossare OTnire 177]
c64- und C16-spezifische Worte
(drv ( --adr)
adr ist die Adresse einer Variablen, die das aktuelle
Laufwerk enthält. Der Inhalt ist i.a. gleich 0.
Wenn Diskettenzugriffe nicht über den Blockmechanis-
mus, sondern z.B. über READSECTOR bzw. WRITESECTOR
gehen, sollte (DRV gesetzt werden.
(64 (==) T.
(16 ==) I
Diese Worte ermöglichen es maschinenspezifische Teile
in einer gemeinsamen Quelle zu vereinigen. Typische
Benutzung:
...WorteFürAlleMaschinen...
(6A assns WorteNurFürC64
(en WorteNurFürCi6....... c)
...WorteFürAlleMaschinen...
Beim C64 bewirkt (64 nichts, (16 ignoriert alles
bis C) . Beim C16 bewirkt (16 nichts, (64 igno-
riert alles bis C).
€) ze I
Tut nichts und zwar sofort. Vgl. NOOP (16 (64.
c64fkeys (==)
Dieses Wort gibt es nur auf dem C16. Es stellt die
Funktionstastenbelegung des C64 her.
Seite 126
cpush
debug
endloop
nest
trace
unnest
unbug
Glossare ultraFORTH83
bpfksfre/ue FORTH-Gesellsc
Tools
(adru--)
Es werden analog PUSH u bytes ab inclusive adr
gesichert. Beim nächsten EXIT oder UNNEST werden
sie zurückgespeichert.
(==)
Benutzt in der Form:
debug <name>
Hierbei ist <name> ein ausführbares Wort. Aktiviert
den Tracer, so daß das Wort <name> schrittweise
ausgeführt wird.
==)
Deaktiviert den Tracer für das angezeigte Wort; er
bleibt jedoch für alle folgenden Worte aktiv. Ist das
angezeigte Wort (LOOP oder (+LOOP oder ein von
REPEAT oder UNTIL kompilierter Sprung, so kann damit
das (wiederholte) Tracen der Schleife unterdrückt
werden.
(--)
Weist den Tracer an, das angezeigte Wort ebenfalls zu
tracen.
( 8)
Benutzt in der Form:
Trace' <name>
Wirkt wie DEBUG <name> „ zusätzlich wird jedoch das
zu tracende Wort anschließend ausgeführt.
(=)
Weist den Tracer an, das getracete Wort zuende auszu-
führen und erst ab dem aufrufenden Wort wieder zu
tracen.
(-—-) N
Deaktiviert den Tracer. Die Ausführung wird fortge-
setzt.
Fu
H
"3
(rd
.rd
T>c
autoload
binary
bload
bsave
>37
ultraFoRTNE3
Glossare
«c) 1985 bp/ks/re/uwe
Kassettenversion
(==) T
Benutzt in der Form
\IF <name> <worte> ..
Wenn <name> in der aktuellen Suchreihenfolge gefunden
wird, werden die folgenden Worte bis zum Zeilenwech-
sel ausgeführt, sonst geschieht nichts. Gegenstück zu
\NEEDS
( --adr )
adr ist die Adresse einer Variablen, die die An-
£fangsadresse der aktuellen Ramdisk enthält bzw. 0
wenn explizit keine Ramdisk existiert. Zum Format der
Ramdisk vgl. die Shadows des Quelltextes. Vgl. auch
RD
e=> )
Druckt zentrale Informationen über die Ramdisk aus.
( 8b--7b) "seven-to-char
Zur Rück-Umwandlung von mit cC>7 erzeugten 7-bit-
Buchstaben in Buchstaben. Funktioniert nur für den
von ultraFORTH benutzten Zeichensatz sicher.
( --adr)
adr ist die Adresse einer Variablen. Ist sie ungleich
0, so wird beim nächsten TAPEINIT eine Ramdisk
geladen. Wird i.a. nur vor SAVESYSTEM benutzt.
( u--u )
u ist die BlockNummer eines Blockes, der nicht
komprimiert werden soll. Dies ist für binäre Ram-
disk-Blöcke erforderlich, da sie sonst verändert
würden. Der Block belegt ab Deklaration ca. 1024
Bytes.
( adri adr3 8b-- adr?2)
Ab adri wird ein File mit dem 8b langen Nanen, der
ab adr3 im Speicher ahgelegt ist, vom mit device
gesetzten Gerät gelesen. Diverse Fehlerbedingungen
werden behandelt. adr2 ist die Endadresse des gela-
denen Files plus 1 . Beim C16/C64 hat der Benutzer
bei allen Lade-Operationen Sorge zu tragen, daß genug
Platz vorhanden ist, sonst folgen undefinierte Resul-
tate. (System-Absturz)
( adri adr2 adr3 8b--)
Der Bereich von adri bis exklusive adr2 wird mit dem
8b langen Namen, der ab adr3 im Speicher abgelegt
ist, auf das mit device gesetzte Gerät geschrieben.
Diverse Fehlerbedingungen werden behandelt.
( 8b--7b) "char-to-seven"
Zur Umwandlung von Buchstaben in 7-bit-Buchstaben.
Die Zurückverwandlung mit 7>C funktioniert nur für
den von ultraFORTH benutzten Zeichensatz sicher.
Seite 130
cload
commodore
compress
csave
derr?
device
expand
floppy
ia"
Glossare
BPFkKSFreFue FORTH-Gesellse ultraFoRTH83
( adri adr3 8b ul--adr2 u2 )
Lädt ab adri das File mit dem 8b langen Namen, der
bei adr3 steht von dem Gerät der Nummer ul. ul
enthält beim cC16/C64 im unteren Byte die Geräte-
Nummer und im oberen Byte die Sekundäradress
(i.a.=0). adr2 ist die Endadresset1 des geladenen
Files. u2 ist eine Fehlerbeschreibung, die zum Aufruf
von DERR? benutzt werden sollte. Beim C16/C64 hat
der Benutzer bei allen Lade-Operationen Sorge zu
tragen, daß genug Platz vorhanden ist. Sonst folgen
undefinierte Resultate. (System-Absturz)
( ==)
Setzt den Kassettenrekorder im Commodore-Format als
aktuelles Ausgabegerät. Vgl.: DEVICE SUPERTAPE
FLOPPY
( adri adr2 ul--u2 )
Zum Komprimieren von Forth-Quelltexten. Beginnend bei
adr1 werden ul Bytes zur adr2 komprimiert. Die Länge
des komprimierten Bereichs ist u2 . Sie beträgt ca.
30-50% der ursprünglichen Länge. Vgl.: EXPAND
( adrl adr2 adr3 8b ul--u2 )
Sichert den Speicherbereich von adri bis exklusive
adr2 unter dem 8b langen Namen, der bei adr3 steht
auf das Gerät der Nummer ul. ul enthält beim C16/C64
im unteren Byte die Geräte-Nummer und im oberen Byte
die Sekundäradresse (i.a.=0). u2 ist eine Fehlerbe-
schreibung, die zum Aufruf von DERR? benutzt werden
sollte.
( u--flag )
Wird nach CLOAD und CSAVE benutzt. Falls ein
Fehler aufgetreten ist, gibt es eine u entsprechende
Fehlermeldung aus. flag ist true, wenn ein Fehler
aufgetreten ist, sonst false.
( --adr)
adr ist die Adresse einer Variablen, die im nieder-
wertigen Byte die Geräte-Nummer des aktuellen Gerätes
enthält und im höherwertigen Byte die Sekundäradresse
(i.a.=0). Vgl.: COMMODORE SUPERTAPE FLOPPY
( adrli adr2 ul--u2 )
Zum Expandieren von komprimierten Forth-Quelltexten.
Beginnend bei adri werden ul Bytes zur adr2
expandiert. Die Länge des expandierten Bereichs wird
in u2 zurückgegeben. Vgl.: COMPRESS
Gar)
Setzt das Diskettenlaufwerk als aktuelles Ausgabege-
rät. Vgl.: DEVICE COMMODORE SUPERTAPE
(==)
Benutzt in der Form
ja ice”
Setzt den Namen der aktuellen Ramdisk auf RD.ccc
ultraFORTH83
23 1005 pruazrenue rorj Glossare Gore 131]
loadramdisk N u)
Es wird eine neue Ramdisk eingerichtet und vom
aktuellen Gerät geladen. Beim C16/C64 hat der Benut-
zer bei allen Lade-Operationen Sorge zu tragen, daß
genug Platz vorhanden ist. Sonst folgen undefinierte
Resultate, (System-Absturz)
memtop ( -- adr )
adr ist die erste Adresse oberhalb des verfügbaren
RAM-Bereiches. Sie ist systemabhängig.
n" ( --adr 8b )
Ist identisch der Sequenz
Ascii " parse
Der Quelltext bis inklusive dem nächsten " wird nicht
ausgeführt, sondern als Zeichenkette verstanden. Sie
beginnt bei der Adresse adr und ist 8b Bytes lang.
ramdisk (--)
Ein Vokabular, in sich Worte der Ramdisk befinden.
ramR/W ( adri u adr2 flag--flag )
R/W wird bei Benutzung der Ramdisk auf RAMR/W
gesetzt. Dadurch wird bei Blockzugriffen auf Drive 0
weiterhin auf ein Diskettenlaufwerk zugegriffen,
Blockzugriffe auf Drive 1 und folgende werden jedoch
auf die aktuelle Ramdisk umgeleitet. Zur Benutzung
der Ramdisk vgl.: DRIVE >DRIVE DRV? COPY CONVEY
rd ( --adr )
adr ist die Anfangsadresse der aktuellen Ramdisk.
Wenn keine gültige Ramdisk eingerichtet ist, wird
eine Fehlerbehandlung eingeleitet. Zum Format der
Ramdisk vgl. die Shadows des Quelltext. Vgl. auch (RD
rdcheck (-)
Druckt Informationen über die Ramdisk aus und prüft
die zentralen Zeiger.
rddel (--)
Löscht alle Blöcke der aktuellen Ramdisk.
rdnew ( adri adr2-- )
Richtet eine neue Ramdisk von adri bis maximal
adr2-1 ein und setzt sie als die aktuelle. Eine
Fehlerbedingung liegt vor, wenn der Speicherbereich
von adri bis adr2 bereits anders belegt ist.
rduse ( adr-- )
Erklärt die Ramdisk ab adr zur aktuellen. Eine
Fehlerbedingung liegt vor, wenn adr nicht die
Anfangsadresse einer Ramdisk ist.
restore" (. =)
Wirkt wie ABORT" , mit der Ausnahme, daß vorher mit
STORE gesicherte Bereiche zurückgespeichert werden.
Seite 132
Glossare
bo/keirerus mas UltraFORTHBF
saveramdisk (--)
store
supertape
tapeinit
Die aktuelle Ramdisk wird auf das aktuelle Gerät
gesichert. Eine Fehlerbedingung liegt vor, wenn keine
Ramdisk eingerichtet war.
( adr -- )
Wirkt wie PUSH, mit der Ausnahme, daß bei einem
anschließenden RESTORE” der gesicherte Bereich zu-
zückgespeichert wird.
(en
Setzt den Kassettenrekorder im Supertape-Format als
aktuelles Ausgabegerät. Supertape ist eine Schnell-
Lade-Routine, die von der Zeitschrift "c't" für alle
gängigen Mikro-Rechner angeboten wird. wir danken
dem Heise-Verlag für die freundliche Genehmigung, es
in ultraFORTH83 integrieren und weiterverbreiten zu
dürfen. Vgl.: DEVICE COMMODORE : FLOPPY
(--)
Initialisiert die Kassettenversion. Wenn autoload un-
gleich 0 ist, wird eine Ramdisk geladen. Wird im
allgemeinen als "'RESTART installiert.
blossare
ultraFoRTH83
ic) 1985 bp/ks/re/ue FORT
Seite 133
Massenspeicher-Utilities
2disk1551 (=)
Sendet beim C16 einen Befehl über den Bus, der ein
anwesendes Diskettenlaufwerk 1551 auf Unit 9
umstellt. Alle nicht gemeinten Laufwerke sind vorher
auszuschalten.
bamallocate (=)
Kennzeichnet alle Sektoren einer Diskette als belegt.
copy2disk ==)
Kopiert eine Diskette von einem Laufwerk auf ein
anderes. Die Directory wird mitkopiert, daher auch
für Files zu verwenden.
copydisk (ul u u3 --)
Kopiert die Blöcke ul bis u2 einer Diskette ab Block
u3 auf die andere Diskette.
formatdisk ()
Formatiert eine Diskette für die Benutzung unter
ultraFORTH83. Beim C16/C64 benutzt in der Form:
formatdisk [<name>, [<id>]]
Neue Disketten müssen mit [<id>] formatiert werden.
Beispiel:
formatdisk hallo,xx
savesystem t ==)
Benutzt in der Form
savesystem <name>
Das ultraFORTH-System wird bis HERE auf einen
externen Massenspeicher gesichert. Vorher wird es in
den Zustand versetzt, in dem es beim nächsten Kalt-
start sein soll. Insbesondere werden die aktuellen
Parameter von Uservariablen in den User-Kaltstart-
Bereich kopiert. Nicht gesichert werden Blockpuffer.
S.a. "Erstellen eines eigenen Arbeitssystems".
FORTH-Gesellsc
| Seite 134 6lossare =
ultraFORTH83
ultraFORTH83
ic) 1985 beo/ks
Definition der Begriffe Seite 135]
H-Gezellschaft eU
FORTH-Gesellschaft eV
Definition der Begriffe
Definition Be Begriffe
| er
Rakiaition der Begriffe
| Definition der Begriffe
Definition der Begriffe
Dp/Kks/re.
Seite 136 Definition der Begriffe ultraFORTH83
FORTH-Gesellsı
Entscheidungskriterien
Bei Konflikten laesst sich das Standardteam von folgenden
Kriterien in Reihenfolge ihrer Wichtigkeit leiten:
1. Korrekte Funktion - bekannte Einschraenkungen Eindeutigkeit
2. Transportabilitaet - wiederholbare Ergebnisse, wenn
Programme zwischen Standardsystemen portiert werden
3. Einfachheit
4. Klare, eindeutige Namen - die Benutzung beschreibender
statt funktionaler Namen, zB [COMPILE] statt c, und ALLOT
statt dpt+!
5. Allgemeinheit
6. Ausfuehrungsgeschwindigkeit
7. Kompaktheit
8. Kompilationsgeschwindigkeit
9. Historische Kontinuitaet
10. Aussprechbarkeit
11. Verstaendlichkeit - es muss einfach gelehrt werden koennen
ultraFORTH83
ic} iI9835 bp/ks/
Seite 137
Adresse, Byte (address, byte)
Adresse, Kompilation (address, compilation)
Adresse, Natuerliche (address, native machine)
Adresse, Parameterfeld (address, parameter field) ""apf""
anzeigen (display)
Arithmetik, 2er-komplement (arithmetic, twos complement)
Block (block)
Blockpuffer (block buffer)
Byte (byte)
Kompilation (compilation)
Definition (Definition)
Dictionary (Woerterbuch)
Division, floored (division, floored)
Empfangen (receive)
Falsch (false)
Fehlerbedingung (error condition)
Flag (logischer Wert)
Floor, arithmetic
Glossar (glossary)
Interpreter, Adressen (interpreter, address)
Interpreter, Text (interpreter, text)
Kontrollstrukturen (structure, control)
laden (load)
Massenspeicher (mass storage)
Programm (program)
Quelltext (input stream)
Rekursion (recursion)
Screen (Bildschirm)
Suchreihenfolge (search order)
stack, data (Datenstapel)
stack, return (Ruecksprungstapel)
String, counted (abgezaehlte Zeichenkette)
String, Text (Zeichenkette)
Userarea (Benutzerbereich)
Uservariable (Benutzervariable)
Vokabular (vocabulary)
Vokabular, Kompilation (vocabulary, compilation)
Wahr (true)
Wort, Definierendes (defining word)
Wort, immediate (immediate word)
Wortdefinition (word definition)
Wortname (word name)
Zahl (number)
Zahlenausgabe, bildhaft (pictured numeric output)
Zahlenausgabe, freiformatiert (free field format)
Zahlentypen (number types)
Zahlenumwandlung (number conversion)
Zeichen (character)
Zustand (mode)
| Seite 138
Definition der Begriffe
FORTH-Gesellscl
ultraFORTH83 |
ultraFORTHB3 © A Pefinition der Begriffe Seite 139]
Definition der Begriffe
Es werden im allgemeinen die amerikanischen Begriffe
beibehalten, es sei denn, der Begriff ist bereits gelauefig.
Wird ein deutscher Begriff verwendet, so wird in Klammern der
engl. Originalbegriff beigefuegt; wird der Originalbegriff
beibehalten, so wird in Klammern eine moeglichst treffende
Uebersetzung 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 manipuliert.
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 gehoerigen Maschinencode
aufzufinden.
Adresse, Natuerliche (address, native machine)
Die vorgegebene Adressdarstellung der Computerhardware.
Adresse, Parameterfeld (address, parameter field) ""apf""
Die Adresse des ersten Bytes jedes Wortes, das fuer das
Ablegen von Kompilationsadressen ( bei :-definitionen )
oder numerischen Daten bzw. Textstrings usw. benutzt wird.
anzeigen (display)
Der Prozess, .ein oder mehrere Zeichen zum aktuellen
Ausgabegeraet zu senden. Diese Zeichen werden
normalerweise auf einem Monitor angezeigt bzw. auf einem
Drucker gedruckt.
Arithmetik, 2er-komplement (arithmetic, twos complement)
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 Ueberlaufsituationen.
m Dadurch ist es moeglich, dass die gleichen Operatoren
benutzt werden koennen, gleichgueltig, ob man die Zahl mit
Vorzeichen (<-32,768...32,767> bei 16bit) oder ohne
Vorzeichen (<0...65,535> bei 16bit) benutzt.
Block (block) °
Die 1024byte Daten des Massenspeichers, auf die ueber
Blocknummern im Bereich <O...Anzahl_existenter_Bloecke-1>
zugegriffen wird. Die exakte Anzahl der Bytes, die je
Zugriff auf den Massenspeicher uebertragen werden, und die
Uebersetzung von Blocknummern in die zugehoerige Adresse
des Laufwerks und des physikalischen Satzes, sind
rechnerabhaengig.
Siehe: "Blockpuffer" und "Massenspeicher"
Seite 140 Definition der Begriffe _ ultraFORTHB3
FORTH-Gesellsc
Blockpuffer (block buffer)
Ein 1024byte langer Hauptspeicherbereich, in dem ein Block
voruebergehend benutzbar ist. Ein Block ist in hoechstens
einem Blockpuffer enthalten.,
Byte (byte)
Eine Einheit von 8bit. Bei Speichern ist es die
Speicherkapazitaet von 8bits.
Kompilation (compilation)
Der Prozess, den Quelltext in eine interne Form
umzuwandeln, die spaeter ausgefuehrt werden kann. Wenn
sich das System im Kompilationszustand befindet, werden
die Kompilationsadressen von Worten im Dictionary
abgelegt, so dass sie spaeter vom Adresseninterpreter
ausgefuehrt werden koennen. Zahlen werden so kompiliert,
dass sie bei Ausfuehrung auf den Stack gelegt werden.
Zahlen werden aus dem Quelltext ohne oder mit negativem
Vorzeichen akzeptiert und gemaess dem Wert von BASE
umgewandelt.
Siehe: "Zahl", "Zahlenumwandlung", "Interpreter, Text" und
"Zustand"
Definition (Definition)
Siehe: "Wortdefinition"
Dictionary (Woerterbuch)
Eine Struktur von Wortdefinitionen, die im Hauptspeicher
des Rechners angelegt ist. Sie ist erweiterbar und waechst
in Richtung hoeherer Speicheradressen. Eintraege sind in
Vokabularen organisiert, so dass die Benutzung von
Synonymen moeglich ist, d.h. gleiche Namen koennen, in
verschiedenen Vokabularen enthalten, vollkommen
verschiedene Funktionen ausloesen.
Siehe: "Suchreihenfolge"
Division, 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 naechstkleinere ganze Zahl
gerundet.
Bemerkung: Ausgenommen von Fehlern durch Ueberlauf gilt:
N1 N2 SWAP OVER /MOD ROT * + ist identisch mit Nl.
Siehe: "floor, arithmetisch"
Beispiele: Dividend Divisor Rest Quotient
10 7 3 1
-10 7 4 -2
10 =T -4 =2
-10 1 -3 1
Empfangen (receive)
Der Prozess, der darin besteht, ein Zeichen von der
aktuellen Eingabeeinheit zu empfangen. Die Anwahl einer
Einheit ist rechnerabhaengie.
ultraFORTH83
ich 1985 bp/ksf initi Seite 141
Falsch (false)
Die Zahl Null repraesentiert den "Falschzustand" eines
Flags.
Fehlerbedingung (error condition)
Eine Ausnahmesituation, in der ein Systemverhalten
erfolgt, das nicht mit der erwarteten Funktion
uebereinstimmt. Im der Beschreibung der einzelnen Worte
sind die moeglichen Fehlerbedingungen und das
dazugehoerige Systemverhalten beschrieben.
Flag (logischer Wert)
Eine Zahl, die eine von zwei moeglichen Werten hat, falsch
oder wahr.
Pe Siehe: "Falsch" "Wahr"
Floor, arithmetic
Z sei eine reelle Zahl. Dann ist der Floor von Z die
groesste ganze Zahl, die kleiner oder gleich Z ist.
Der Floor von +0,6 ist 0
Der Floor von -0,4 ist -1
Glossar (glossary)
Eine umgangssprachliche Beschreibung, die die zu einer
Wortdefinition gehoerende Aktion des Computers beschreibt
- die Beschreibung der Semantik des Wortes.
Interpreter, Adressen (interpreter, address)
Die Maschinencodeinstruktionen, die die kompilierten
Wortdefinitionen ausfuehren, die aus Kompilationsadressen
bestehen.
Interpreter, Text (interpreter, text)
Eine Wortdefinition, die immer wieder einen Wortnamen aus
dem Quelltext holt, die zugehoerige Kompilationsadresse
bestimmt und diese durch den Adressinterpreter ausfuehren
laesst. Quelltext, der als Zahl interpretiert wird,
hinterlaesst den entsprechenden Wert auf dem Stack.
Siehe: "Zahlenumwandlung”
Kontrollstrukturen (structure, control)
Eine Gruppe von Worten, die, wenn sie ausgefuehrt werden,
den Programmfluss veraendern.
Beispiele von Kontrollstrukturen sind:
DO ... LOOP
BEGIN ... WHILE ... REPEAT
IF ... ELSE ... THEN
laden (load) s
Das Umschalten des Quelltextes zum Massenspeicher. Dies
ist die uebliche Methode, dem Dictionary neue Definitionen
hinzuzufuegen.
Massenspeicher (mass storage)
Speicher, der ausserhalb des durch FORTH adressierbaren
Bereiches liegen kann. Auf den Massenspeicher wird in Form
von 1024byte grossen Bloecken zugegriffen. Auf einen Block
kann innerhalb des Forth-Adressbereichs in einem
Blockpuffer zugegriffen werden. Wenn ein Block als
veraendert (UPDATE) gekennzeichnet ist, wird er
Seite 147 Definition der Begriffe sun UltraFORTHES
letztendlich wieder auf den Massenspeicher
zurueckgeschrieben.
Programm (program)
Eine vollstaendige Ablaufbeschreibung in FORTH-Quelltext,
um eine bestimmte Funktion zu realisieren.
Quelltext (input stream)
Eine Folge von Zeichen, die dem System zur Bearbeitung
durch den Textinterpreter zugefuehrt wird. Der Quelltext
»ommt ueblicherweise von der aktuellen Eingabeeinheit
(ueber den Texteingabepuffer) oder dem Massenspeicher
(ueber einen Blockpuffer). BLK, >IN, TIB und #TIB
charakterisieren den Quelltext. Worte, die BLK, >IN, TIB
oder #TIB benutzen und/oder veraendern, sind dafuer
verantwortlich, die Kontrolle des Quelltextes
aufrechtzuerhalten oder wiederherzustellen.
Der Quelltext reicht von der Stelle, die durch den
Relativzeiger >IN angegeben 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 lange.
Wenn BLK ungleich Null ist, so ist der Quelltext der
Inhalt des Blockpuffers, der durch BLK angegeben ist, und
er ist 1024byte lang.
Rekursion (recursion)
Der Prozess der direkten oder indirekten Selbstreferenz.
Screen (Bildschirm)
Ein Screen sind Textdaten, die zum Editieren aufbereitet
sind. Nach Konvention besteht ein Screen aus 16 Zeilen zu
je 64 Zeichen. Die Zeilen werden von O0 bis 15
durchnumeriert. Screens enthalten normalerweise Quelltext,
koennen jedoch auch dazu benutzt werden, um
Massenspeicherdaten zu betrachten. Das erste Byte eines
Screens ist gleichzeitig das erste Byte eines
Massenspeicherblocks; dies ist auch der Anfangspunkt fuer
Quelltextinterpretation waehrend des Ladens eines Blocks.
Suchreihenfolge (search order)
Eine Spezifikation der Reihenfolge, in der ausgewaehlte
Vokabulare im Dictionary durchsucht werden. Die
Suchreihenfolge besteht aus einem auswechselbaren und
einem festen Teil, wobei der auswechselbare Teil immer als
erstes durchsucht wird. Die Ausfuehrung eines =
Vokabularnamens macht es zum ersten Vokabular in der
Suchreihenfolge, wobei das Vokabular, das vorher als
erstes durchsucht worden war, verdraengt wird. Auf dieses
erste Vokabular folgt, soweit spezifiziert, der feste Teil
der Suchreihenfolge, der danach durchsucht wird. Die
Ausfuehrung von ALSO uebernimmt das Vokabular im
auswechselbaren Teil in den festen Teil der
Suchreihenfolge. Das Dictionary wird immer dann
durchsucht, wenn ein Wort durch seinen Namen aufgefunden
werden soll.
ultraFORTH83 BA Definition der Begriffe Seite 143
stack, data (Datenstapel)
Eine "Zuletzt-rein, Zuerst-raus"” (last-in, first-out)
Struktur, die aus einzelnen 16bit Daten besteht. Dieser
Stack wird hauptsaechlich zum Ablegen von
Zwischenergebnissen waehrend des Ausfuehrens von
Wortdefinitionen benutzt. Daten auf dem Stack koennen
Zahlen, Zeichen, Adressen, Boolesche Werte usw. sein.
Wenn der Begriff "Stapel" oder "Stack" ohne Zusatz benutzt
wird, so ist immer der Datenstack gemeint.
stack, return (Ruecksprungstapel)
Eine "Zuletzt-rein, Zuerst-raus” Struktur, die
hauptsaechlich Adressen von Wortdefinitionen enthaelt,
deren Ausfuehrung durch den Adressinterpreter noch nicht
beendet ist. Wenn eine Wortdefinition eine andere
. Wortdefinition aufruft, so wird die Ruecksprungadresse auf
dem Returnstack abgelegt.
Der Returnstack kann zeitweise auch fuer die Ablage
anderer Daten benutzt werden.
String, counted (abgezaehlte Zeichenkette)
Eine Hintereinanderfolge von 8bit Daten, die im Speicher
durch ihre niedrigste Adresse charakterisiert wird. Das
Byte an dieser Adresse enthaelt einen Zahlenwert im
Bereich <0...255>, der die Anzahl der zu diesem String
gehoerigen 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 Hintereinanderfolge von 8bit Daten, die im Speicher
durch ihre niedrigste Adresse und ihre Laenge in Bytes
charakterisiert ist. Strings enthalten normalerweise
ASCII-Zeichen. Wenn der Begriff "String" alleine oder in
Verbindung mit anderen Begriffen benutzt wird, so sind
Textstrings gemeint.
Userarea (Benutzerbereich)
Ein Gebiet im Speicher, das zum Ablegen der Uservariablen
benutzt wird und fuer jeden einzelnen Prozess/Benutzer
getrennt vorhanden ist.
— Uservariable (Benutzervariable)
Eine Variable, deren Datenbereich sich in der Userarea
befindet. Einige Systemvariablen werden in der Userarea
gehalten, so dass die Worte, die diese benutzen, fuer
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 koennen mehrere Definitionen mit dem
gleichen Namen existieren; diesen Vorgang nennt man
redefinieren. Wird das Vokabular nach einem Namen
durchsucht, so wird. die juengste Redefinition gefunden.
ultraFORTH83
Seite 144 Definition der Begriffe
FORTH-Gesellsc
Vokabular, Kompilation (vocabulary, compilation)
Das Vokabular, in das neue Wortdefinitionen eingetragen
werden.
Wahr (true) i
Ein Wert, der nicht Null ist, wird als "wahr"
interpretiert. Wahrwerte, die von Standard-FORTH-Worten
errechnet werden, sind 16bit Zahlen, bei denen alle 16
Stellen auf "1" gesetzt sind, so dass diese zum Maskieren
benutzt werden koennen.
Wort, Definierendes (defining word)
Ein Wort, das bei Ausfuehrung einen neuen
Dictionary-Eintrag im Kompilationsvokabular erzeugt. Der
Name des neuen Wortes wird dem Quelltext entnommen. Wenn
der Quelltext erschoepft ist, bevor der neue Name erzeugt
wurde, so wird die Fehlermeldung "ungueltiger Name"
ausgegeben.
Beispiele von definierenden Worten sind:
CONSTANT CREATE
Wort, immediate (immediate word)
Ein Wort, das ausgefuehrt wird, wenn es waehrend der
Kompilation oder Interpretation aufgefunden wird.
Immediate Worte behandeln Sondersituationen waehrend der
Kompilation.
Siehe z.B. IF LITERAL ." usw.
Wortdefinition (word definition)
Eine mit einem Namen versehene, ausfuehrbare
FORTH-Prozedur, 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.
Wortname (word name)
Der Name einer Wortdefinition. Wortnamen sind maximal 31
Zeichen lang und enthalten kein Leerzeichen. Haben zwei
Definitionen verschiedene Namen innerhalb desselben
Vokabulars, so sind sie eindeutig auffindbar, wenn das
Vokabular durchsucht wird.
Siehe: "Vokabular"
Zahl (number)
Wenn Werte innerhalb eines groesseren Feldes existieren,
so sind die hoeherwertigen Bits auf Null gesetzt. 16bit
Zahlen sind im Speicher so abgelegt, dass sie in zwei
benachbarten Byteadressen enthalten sind. Die
Bytereihenfolge ist rechnerabhaengig. Doppeltgenaue Zahlen
(32bit) werden auf dem Stack so abgelegt, dass die
hoeherwertigen 16bit (mit dem Vorzeichenbit) oben liegen.
Die Adresse der niederwertigen 16bit ist um zwei groesser
als die Adresse der hoeherwertigen 16bit, wenn die Zahl im
Speicher abgelegt ist.
Siehe: "Arithmetik, 2er-komplement" und "Zahlentypen"
ultraFORTH83
ic} 1985 bp/ks
Zahlenausgabe, bildhaft (pictured numeric output)
Durch die Benutzung elementarer Worte fuer die
Zahlenausgabe ( z.B. <# # #s #> ) werden Zahlenwerte in
Textstrings umgewandelt. Diese Definitionen werden in
einer Folge benutzt, die ein symbolisches Bild des
gewuenschten Ausgabeformates darstellen. Die Umwandlung
schreitet von der niedrigstwertigen zur hoechstwertigen
Ziffer fort und die umgewandelten Zeichen werden von
hoeheren gegen niedrigere Speicheradressen abgelegt.
Zahlenausgabe, freiformatiert (free field format)
Zahlen werden in Abhaengigkeit von BASE umgewandelt und
ohne fuehrende Nullen, aber mit einem folgenden
Leerzeichen, angezeigt. Die Anzahl von Stellen, die
Zi angezeigt werden, ist die Minimalanzahl von Stellen -
mindestens eine - die notwendig sind, um die Zahl
eindeutig darzustellen.
Siehe: "Zahlenumwandlung"
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 fuer jedes Bit um eine Zweierpotenz erhoeht.
Fuer eine Zahl ohne Vorzeichen ist das am weitesten links
stehende Bit in diese Bewertung eingeschlossen, so dass
fuer eine solche 16bit Zahl das ganz linke Bit den Wert
32.768 hat. Fuer Zahlen mit Vorzeichen wird die Bewertung
des ganz linken Bits negiert, so dass es bei einer 16bit
Zahl den Wert -32.768 hat. Diese Art der Wertung fuer
Zahlen mit Vorzeichen wird 2er-komplementdarstellung
genannt.
Nicht spezifizierte, bewertete Zahlen sind mit oder ohne
Vorzeichen; der Programmkontext bestimmt, wie die Zahl zu
interpretieren ist.
Zahlenumwandlung (number conversion)
Zahlen werden intern als Binaerzahlen gefuehrt und extern
durch graphische Zeichen des ASCII Zeichensatzes
dargestellt. Die Umwandlung zwischen der internen und
externen Form wird unter Beachtung des Wertes von BASE
durchgefuehrt, 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 "0"
(Position 3/0, dezimalwert 48) dargestellt. Diese
Zifferndarstellung geht den ASCII-code weiter aufwaerts
bis zum Zeichen "9", das dem dezimalen Wert neun
entspricht. Werte, die jenseits 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 fuer die
gerade umzuwandelnde Zahl dadurch umgangen werden, dass
den Ziffern ein "Zahlenbasisprefix" vorangestellt wird.
Dabei wird durch das Zeichen "%" die Basis voruebergehend
Seite 146 Definition der Begriffe u ultraFORTH83 |
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.
Enthaelt die Zahl ein Komma oder einen Punkt, so wird sie
als 32bit Zahl umgewandelt.
Zeichen (character)
Eine 7bit Zahl, deren Bedeutung durch den ASCII-Standard
festgelegt ist. Wenn es in einem groesseren Feld
gespeichert ist, so sind die hoeherwertigen Bits auf Null
gesetzt.
Zustand (mode)
Der Textinterpreter kann sich in zwei moeglichen
Zustaenden befinden: dem interpretierenden oder dem
kompilierenden Zustand. Die Variable STATUS wird vom
System entsprechend gesetzt, und zwar enthaelt sie bei der
Interpretation eine False-flag, bei der Kompilation eine
True-flag.
Siehe: "Interpreter, Text" und "Kompilation"
ultraFORTHB3 ic} 1985 bp/ks/rer/ue FORTH- Editor Seite id?
[Seite 148 Editor E bRikSFre/ue
FORTH-Gesellsc
ultraFORTH83
ultraFORTH83 ic} 1955 bpr/ks/reine cc Editor 3
C64 Full Screen Editor
Allgemeines
Der Bildschirm des C64 bedingt eine Abweichung vom FORTH-
Standard- Format der Screens mit 16 Zeilen zu 64 Zeichen,
wenn man Rollen zur Seite oder das haessliche 1 2/5 -Zeilen-
Format vermeiden will. Ein Screen wird in unserem Editor mit
24 Zeilen zu 41 Zeichen und 1 Zeile mit 40 Zeichen (zusammen
1024 Zeichen) dargestellt. Dabei sind 25 Zeilen mit 40 Zei-
chen sichtbar und auch voll beschreibbar, eine Spalte von
Fi Leerzeichen befindet sich rechts vom Bildschirm:
“ Sichtbarer Screen Eine Spalte
02 | mit 25 x 48 Zeichen. unsichtbarer
Jede Zeile bis Leerzeichen,
ı einschließlich des nicht direkt
: letzten Zeichens beschreibbar.
ı beschreibbar.
23
24
Der Bildschirm scrollt weder aufwaerts noch seitlich. Es
existiert kein "Quote- Modus".
Im Editor haben verschiedene Tasten besondere Bedeutung, ins-
— besonders sind die Funktionstasten belegt, diverse Tasten
wirken, wenn sie zusammen mit CTRL betaetigt werden.
Die Auswirkung der Funktionstasten wird von oben (F1/F2)
nach unten (F7/F8) geringer. Siehe die Beschreibung der Funk-
tionstasten. Loeschfunktionen sind aus Gruenden der Sicher-
heit beidhaendig einzugeben (F2, FA, F6). Die CURSORtasten,
INSerT, DELete und HOME verhalten sich wie gewohnt.
Der Editor bearbeitet zunaechst nur einen besonderen Buffer
und veraendert den Disk- Buffer nicht. Erst auf Kommando
wird der Disk- Buffer updated. Damit koennen grobe Editier-
Fehler keinen grossen Schaden anrichten.
Der Editor verhindert, dass versehentlich Text verloren
geht, indem er Funktionen nicht ausfuehrt, wenn dadurch Zei-
chen nach unten oder zur Seite aus dem Bildschirm geschoben
wuerden.
Editor ultraFoRTH83
SB bp/ks/re/ue FORTH-Gesellsc
Seite 158
Der Editor unterstützt das "Shadow-Konzept". Zu jedem Quell-
text-Screen existiert ein Kommentar-Screen, so daß viel Platz
für Kommentare zur Verfügung steht. Bei Benutzung dieser
Screens wird die Lesbarkeit von Forthprogrammen wesentlich
erhöht (obwohl ein guter FORTH-Stil selbstdokumentierend ist).
Auf Tastendruck stellt der Editor den Kommentar-Screen zur
Verfügung, der somit "deckungsleich" angefertigt werden kann.
Das Druckerinterface druckt Quelltext und Kommentar, falls
gewünscht, nebeneinander aus.
Zum "Umgraben” umfangreicher Quelltexte ist der Wechsel zwi-
schen zwei beliebig wählbaren Screens oft nützlich. Durch einen
Tastendruck werden Kopien und beliebige Umgruppierungen von
Zeichen besonders einfach.
Eine Suche- und Ersetze-Funktion ist die Voraussetzung für eine
effektive Fehlersuche und für eine verbesserte Lesbarkeit der
Programme, denn damit kann die Namensgebung von Worten nach-
träglich verbessert werden.
Ist der Editor geladen, so stehen zur Eingabe auch außerhalb
des Editors die Cursortasten und alle zeichenbezogenen Ctrl-
Codes zur Verfügung. Mit <Return> wird die Cursorzeile nach den
Änderungen übernommen.
ci6 Full Screen Editor
Im Gegensatz zu den Erläuterungen zum C64-Editor können beim
c16 Zeilen nach unten aus dem Bildschirm herausgeschoben
werden. Das geschieht unter folgenden Umständen:
-) Es wird in die 40. Bildschirmspalte einer beliebigen Zeile
ein Zeichen geschrieben. Wenn hier eine logische Zeile
Bildschirmzeile aufhört, schiebt die I/O-Routine des
Betriebssystems eine neue Zeile ein.
-) Es wird <ESC> <I> oder eine andere <ESC>-Kombination
eingegeben, die eine Zeile aus dem Bildschirm schiebt.
Die C16-ESCAPE-Tasten-Funktionen, wie sie z.B. aus dem BASIC
bekannt sind, können benutzt werden, führen aber zusammen mit
unseren Editor-Funktionen zu sonderbaren Reaktionen auf dem
Bildschirm.
ultraFORTH83 ic) 13855 berks/re/wue FORTH-G Editor | Seite 151 |
von FORTH in den Editor
edit ( m==7)
Einstieg in den Editor Screen # n. Der Screen
wird, wenn noetig, von der Diskette geholt. War
das System frisch geladen, so wird vor dem Ein-
stieg die Signatur des Benutzers erfragt. Diese
Signatur kann in die rechte obere Ecke des Screens
kopiert werden. Siehe GETSTAMP, "print stamp$"
und "updated exit". Typisch enthaelt die Signatur
_ das Tagesdatum und ein Programmierer- Kuerzel:
0Anov85re) oder We 18. April 85)
Man befindet sich nun im Editor- Modus, den man
nur mit "cancel", "updated exit", "flushed exit"
oder "load exit" wieder verlassen kann.
1 Gas=>) "list"
Einstieg in den Editor. Siehe EDIT. Unterschied zu
EDIT: Der Cursor wird bei L HOME positioniert, bei
EDIT nicht.
r (==) "re-list"
Einstieg in den Editor. Der zuletzt editierte
Screen wird aufgerufen, mit dem Cursor dort, wo er
bei Verlassen des Editors war. Bei Fehlern waeh-
rend LOAD von der Diskette, die der Interpre-
ter/Compiler erkennt, werden die Variablen SCR und
R# mit der Fehlerstelle versorgt. Ein R zeigt dann
den Screen, in dem der Fehler auftrat, der Cursor
steht 2 Zeichen hinter dem bemaengelten Wort.
+l („ ns: .) "plus-list"
Einstieg in den Editor. Zur aktuellen Screen-Nr.
wird n addiert und der entsprechende Screen zum
Editieren geholt. Das Gegenstueck des Editors zu
+LOAD und +THRU .
view (==)
wird benutzt in der Form:
view <name>
Sucht das Wort <name> im Dictionary und ruft den
zugehoerigen Quelltext- Screen zum Editieren auf.
Setzt allerdings voraus, dass die richtige Dis-
kette im Laufwerk ist. Vergleiche L und EDIT
[Seite 152 Editor E be/ks/re/we FORTH-Gesellsc ultraFORTH83
CTRL c
STOP
CTRL x
CTRL £
CTRL 1
Verlassen des Editors
"“cancel"
Der Editor wird verlassen. Dabei wird der Arbeits-
Buffer- Inhalt weggeworfen und der Disk- Buffer
nicht angetastet.
Der Editor wird verlassen wie mit "cancel".
"updated-exit"
Der Editor wird verlassen. Arbeits- und Disk- Buf-
fer werden miteinander verglichen, bei Abweichun-
gen wird
1. die Signatur, sofern eingegeben, in die rech-
te obere Ecke kopiert, und
2. der Arbeits- in den Disk- Buffer kopiert,
einschliesslich der nicht sichtbaren Spalte von
Leerzeichen rechts der Zeilen 0-23.
Wird keine Veraenderung festgestellt, so wird der
Editor wie bei "cancel" verlassen.
"flushed-exit"
Der Editor wird verlassen wie bei "updated exit",
anschliessend wird SAVE-BUFFERS ausgefuehrt, alle
UPDATEd Screens werden auf die Diskette zurueckge-
schrieben, sie bleiben jedoch in den Disk- Buf-
fern. Siehe SAVE-BUFFERS und FLUSH .
"load-exit"
Der Editor wird verlassen wie bei "flushed exit",
dann wird der editierte Screen ab der aktuellen
Cursorposition (!) geladen. Das Laden laesst sich
optisch verfolgen. Siehe SHOWLOAD
ultrarORTHBI Br: Torermerae Form Editor Seite 153]
Die gewohnten Editiertasten
CuRSoR right
CuRSoR left
CuRSoR down
CuRSoR up
au DELete "backspace"
INSerT
HOME
Verhalten sich wie gewohnt.
SHIFT HOME "to-end"
Der Cursor wird hinter das letzte Zeichen auf dem
Bildschirm bewegt.
RETURN
Der Cursor wird an den Anfang der naechsten Zeile
bewegt, der Insert- Modus wird geloescht, die logi-
sche Verbindung von Zeilen wird aufgehoben.
SHIFT RETURN
Siehe "RETURN".
LSeite 154 Editor 5 bErkSFTerue FÜRTH-Gesellsc ultraFORTH83
Fl
F2
F3
F4
F5
F6
F7
F8
Die Funktionstasten
"insert-line"
Der Screen wird ab und einschliesslich der Cursor-
zeile um eine Zeile nach unten geschoben, die Cur-
sorzeile wird mit Leerzeichen gefuellt.
"delete-line"
Die Cursorzeile wird weggeworfen, der Rest des
Screens um eine Zeile hochgezogen, die letzte Zei-
le wird mit Leerzeichen gefuellt. Um ganze Screens
zu loeschen, muss man F2 benutzen. Erscheint dies
zu muehsam, so definiere man sich:
wipe ( --) scr @ block b/blk bl fill;
WIPE loescht den zuletzt editierten Screen.
"pull-line"
Nach "insert line" wird die oberste Zeile vom Zei-
len- Stack in die Cursorzeile geholt.
"push-line"
Die Cursorzeile wird auf den Zeilen- Stack trans-
portiert, der Rest des Screens um eine Zeile hoch-
gezogen und die letzte Zeile gelovescht. Verglei-
che "delete line", Der Zeilen- Stack kann viele
Zeilen aufnehmen, abhaengig vom Dictionary- Space
oberhalb PAD bis unterhalb SP@ . Die Zeilen sind
dort sicher, bis das naechste Mal compiliert wird.
Auch FLUSH mit anschliessendem Diskettenwechsel be-
rushrt den Zeilen- Stack nicht, so dass kleine bis
mittlere Kopierarbeiten ueber diesen Stack vorge-
nommen werden koennen. Vergleiche "copy line"
und "copy char".
"pull-char"
Nach einem "INSerT" wird das oberste Zeichen vom
Zeichen- Stack unter die Cursorposition geholt.
"push-char"
Das Zeichen unter dem Cursor wird auf den Zeichen-
Stack transportiert, dann wird ein "delete char"
ausgefuehrt. Der Zeichen- Stack kann 80 Zeichen
aufnehmen. Die Zeichen sind dort bis zum naechsten
Compilieren sicher. Vergleiche "copy char".
"+tab"
Der Cursor wird um 10 Zeichen nach rechts bewegt.
"tab"
Der Cursor wird um 5 Zeichen nach links bewegt.
ultraFORTH83 1c) 1985 bo/ks/re/we FORTH-d Editor Seite 155
CTRL
CTRL
CTRL
CTRL
CTRL
CTRL
CTRL
CTRL
Andere Editor Funktionen
(für C64) "copy-char"
(für C16)
Das Zeichen unter dem Cursor wird auf den Zeichen-
stack kopiert, der Cursor nach rechts bewegt. Ver-
gleiche "push char" und "pull char" .
"copy-line"
Die Cursorzeile wird auf den Zeilenstack kopiert,
der Cursor abwaerts bewegt. Vergleiche "push line"
und "pull line".
"erase-line"
Die Cursorzeile wird geloescht. Es wird nichts ver-
schoben.
"delete-char"
Das Zeichen unter dem Cursor wird geloescht, der
Cursor bleibt, wo er ist, die Zeichen rechts vom
Cursor werden nach links gezogen. Die gleiche Funk-
tion liesse sich mit "CuRSoR right" und "backspace"
erreichen. Vergleiche "push char".
"insert-on"
Der Insert- Modus wird eingeschaltet, jedes in die-
sem Modus eingegebene Zeichen bewirkt ein vorange-
hendes "insert". Der neue Text wird also in den
vorhandenen eingefuegt. Vergleiche "insert".
"overwrite-on"
Der Insert- Modus wird wieder abgeschaltet.
"clear-to-right"
Die Cursorzeile wird ab und einschliesslich der
Cursorposition näch rechts geloescht.
| Seite 156 Editor E be/ks/re/ue FORTH-Gesellsc ultraFORTH8S
Ein bisschen Komfort(h)
CTRL $ "print-stamp-string"
Die Benutzersignatur wird in die rechte obere Ecke
des Screens kopiert. Vergleiche "getstamp".
CTRL # "show-screen-number"
Die Screen- Nummer wird in der obersten Zeile ein-
geblendet. Jeder folgende Tastendruck loescht die
Anzeige wieder.
delete Lıne
inst Line
-Tab
+Tab
ultraFORTH83 ich 19385 bprks/re/we FORTH-d Editor Seite 157
Blaettern durch den Text
CTRL n "next-screen"
Der naechste Screen wird zum Editieren bereitge-
stellt. Der gerade bearbeitete Screen wird wie
bei "updated exit" updated.
CTRL b "back-screen"
Der vorhergehende Screen wird zum Editieren ge-
holt. Siehe "next screen".
CTRL w "shadow-screen"
Es wird vom Original-Screen in den Shadow-Screen,
oder von dort zurueck, gewechselt. Siehe "next
screen".
CTRL a "alter-screen"
Wechselt vom aktuellen in einen alternativen
Screen und wieder zurueck. Nach dem Kaltstart auf
Screen # 1 eingestellt. Siehe "next screen".
Seite 158 |
CTRL
Editor
ultraFORTH83
E oO bpbs/treiwe FORTH-Gesellsc
Suchen und Ersetzen
"search"
Es wird nach. einem String gesucht. Zunaechst wer-
den der letzte zu durchsuchende Screen, der Such-
und der Ersatz2- String abgefragt. <RETURN> laesst
die Felder unveraendert, alle anderen Eingaben wer-
den uebernommen. Die Suche beginnt im aktuellen
Screen ab Cursorposition. Ist der Zielscreen vor
dem Startscreen, so werden die Screens in abstei-
gender Reihenfolge, sonst in aufsteigender Reihen-
folge, durchsucht. Innerhalb der Screens wird
immer von oben nach unten gesucht. Das Suchen kann
jederzeit mit "STOP" abgebrochen werden.
Wird der Such- String gefunden, so haelt der Cur-
sor dahinter. "STOP" bricht auch jetzt die weite-
re Suche ab, die Taste <r> ersetzt den Such- durch
den Ersatz- String, alle anderen Tasten bewirken
das Weitersuchen.
ultraFORTH83 ic) 1985 beikss/rerwe FORTH- Editor i Seite 159 ]
Andere Worte des Editors
Editor (==)
Ein Vocabulary, in das Worte compiliert sind, die
mit dem Editor zu tun haben. Siehe VOCABULARY .
digits (ei)
ein mit INPUT: definiertes Wort, das die Tastatur
als Eingabegeraet setzt. Zeichen, die keine Zif-
fern darstellen (siehe BASE ), werden nicht ange-
nommen. DIGITS benutzt DIGDECODE . Siehe INPUT: ,
KEYBOARD und EDIBOARD .
digdecode ( adr lenO key -- adr leni ) "digit-decode"
wertet key aus. Ist key weder #BS noch #CR , dann
wird geprueft, ob key eine gueltige Ziffer reprae-
sentiert. Siehe BASE . Wenn nicht, bleibt lenO un-
veraendert und key geht verloren, sonst wird key
in der Speicherstelle adr + lenO abgelegt, das Zei-
chen als Echo zum Ausgabegeraet gesandt und lenO
inkrementiert. Im Falle von #BS wird das letzte
Echo geloescht und lenO dekrementiert, bei #CR
wird lenO nicht veraendert und in die Variable
SPAN kopiert. DIGDECODE wird von DIGITS benutzt.
Vergleiche INPUT: , DECODE , C64DECODE und EDIDE-
CODE .
ediboard € =.)
ein mit INPUT: definiertes Wort, das als Eingabege-
raet die Tastatur setzt. Cursortasten und alle im
Editor definierten, auf Zeichen bezogene, CTRL-
Codes werden nach EDIBOARD ausgefuehrt. EDIBOARD
ist, wenn der Editor geladen ist, der Standard-
Input. Siehe STANDARDI/O . EDIBOARD benutzt EDI-
EXPECT und EDIDECODE . Vergleiche INPUT: ,
KEYBOARD und DIGITS .
ediexpect ( adr len -- )
richtet alle EDITOR- Puffer ein und erwartet dann
len Zeichen vom Eingabegeraet, die ab adr im Spei-
cher abgelegt werden. Ein Echo der Zeichen wird
ausgegeben. CR beendet die Eingabe vorzeitig. Ein
abschliessendes Leerzeichen wird immer ausgegeben.
Die Laenge der empfangenen Zeichenkette wird in
der Variablen SPAN uebergeben. Vergleiche EXPECT .
Siehe auch EDIEXPECT .
edidecode ( adr lenO key -- adr leni )
wertet key aus. Ist key = #CR , so wird die Zeile,
in der der Cursor steht, komplett im Speicher ab
adr aufwaerts abgelegt, leni auf die aktuelle
Laenge eingestellt und diese Laenge ausserdem in
SPAN uebergeben. Ist key ein zeichenbezogener
Seite 168 Editor E be/ksfre/ue FORTH-Gesellsce ultraFORTH83
(pad
(search
getstamp
stamp$
shadow
CTRL-Code, so wird die zugehoerige Aktion ausge-
fuehrt. Ist key ein normales druckbares Zeichen,
so wird es auf das Ausgabegeraet ausgegeben. len
wird in diesen Faellen nicht veraendert. Verglei-
che DECODE und INPUT:
H-m3dr )
adr ist die Adresse einer Variablen, die die Adres-
se von PAD haelt. Weichen PAD und der Inhalt von
(PAD ab, so werden die Editor- Buffer fuer Zeilen-
und Zeichen- Stack neu initialisiert.
( text tlen buf blen -- adr tf // ff )
text ist die Adresse eines Textes der Laenge tlen.
(SEARCH sucht diesen Text in einem Puffer, der bei
buf beginnt und blen Zeichen lang ist. Wird der
Text im Puffer gefunden, so wird die Adresse adr
des Textes im Puffer und ein TRUE tf uebergeben,
sonst nur ein FALSE ff.
er 9)
fragt die Benutzer- Signatur ab. Vergleiche STAMP$
und "print-stamp-string".
G4=-" ad")
adr ist die Adresse einer Datenstruktur, die die
Benutzer- Signatur enthaelt. Vergleiche GETSTAMP
und "print-stamp-string".
( -- adr )
adr ist die Adresse einer Variablen, die den Ab-
stand zwischen Original- und Shadow- Screen ent-
haelt.
(+=- FI
wird in der folgenden Form benutzt:
v <name>
V sucht <name> im Dictionary und hinterlaesst die
Nummer +n des Screens, von dem <name> compiliert
wurde. Ist +n = 0 so wurde <name> vom Terminal com-
piliert. Vergleiche VIEW .
ultraFORTH83 ich 1985 berksfrerue Gen etitor nr ser]
Besondere LOAD Worte
(load ( blk #n -- ) "paren-load"
laedt den Block blk nicht von Anfang an, sondern
ab dem +n sten Zeichen. Ist tn =0, so macht (LOAD
dasselbe wie LOAD . Vergleiche LOAD .
showload { DIE 42 og)
laedt den Block blk nicht von Anfang an, sondern
ab dem +n sten Zeichen. Beim Laden werden die
Screens gelistet und eine Marke hinter den gela-
denen Namen gesetzt. Das Laden kann so optisch ver-
folgt werden. Ein "load exit" benutzt SHOWLOAD .
Vergleiche (LOAD und LOAD . ü
bpiks/rteiue FORTH-Geszellsı
Seite 165 ( Editor 5: ultraFORTH83
Spezielle (64 Worte
**kultraFORTH83KK* ( -- )
.blk
cbm>scr
ein Wort ohne Funktion. Siehe NOOP .
(_ =) "print-block"
druckt die Block-Nummer aus, die gerade geladen
wird. Ist der Inhalt von BLK = 0, so wird nichts
gedruckt. .BLK wird typisch in der Form:
.blk Is .status
verwendet. .BLK wird nun von .STATUS ausgefuehrt.
Nach dem Laden des Editors ist dies voreinge-
stellt. Eigene Worte koennen .STATUS jederzeit zu- kn
gewiesen werden.
( 8b0 -- 8bl ) "commodore-to-screen"
ein Zeichen wird von commodore- Code 8b0O in den
commodore- screen- Code 8b1 gwandelt.
FORTH-Gesellschaft ( -- )
rvsoff
rvson
unlink
ein Wort ohne Funktion. Siehe NOOP .
( --) "reverse-off"
schaltet die inverse Darstellung von Zeichen auf
dem Bildschirm ab.
(eo) "reverse-on"
schaltet die inverse Darstellung von Zeichen auf
dem Bildschirm an.
( 860 -- 8b1 ) "screen-to-commodore"
ein Zeichen wird von commodore- screen- Code 8b0
in den commodore- Code 8b1l gwandelt. Siehe ASCII
( )
hebt die logische Verbindung aller physikalischen
Bildschirmzeilen auf. Ein, fuer normale Menschen
(nicht-commodore-Benutzer), voellig unverstaend-
liches und unnuetzes Wort; leider notwendig.
ultraFORTHBS B, 73:5 Sorkerrerue Form Editor te 163
32-Bit Worte
2! ( 32b adr -- ) "two-store"
32b werden im Speicher bei adr abgelegt. Siehe
2VARIABLE und "Definition der Begriffe, Zahl
(number)".
2@ ( adr -- 32b ) "two-fetch"
Von der Adresse adr werden 32b auf den Stack ge-
holt. Siehe 2VARIABLE und "Definition der Begrif-
fe, Zahl (number)".
2Constant ( 326 == ) "two-constant"
( -- 32b ) compiling
wird so benutzt:
32b 2Constant <name>
2CONSTANT erzeugt eine 32-Bit Konstante mit dem
Namen <name>. 32b wird compiliert. Bei Ausfuehrung
von <name> wird 32b auf dem Stack hinterlassen.
Siehe "Definition der Begriffe, Zahl (number)".
2Variable (- "two-variable"
( -- adr ) compiling
wird in der Form:
2Variable <name>
benutzt. 2VARIABLE erzeugt eine 32-Bit Variable
mit dem Namen <name>. Der Inhalt der Variablen
wird nicht initialisiert. Bei der spaeteren Aus-
fuehrung von <name> wird die Adresse adr der Vari-
ablen hinterlassen. Mit 2! koennen 32b-Werte in
der Variablen abgelegt und mit 2@ wieder entnommen
werden. Vergleiche 2CONSTANT , 2! ,„ 20 ,
VARIABLE , ! und @ . Siehe auch "Definition der Be-
griffe, Zahl (number)".
| Seite 164 Editor E berksfreiue
FORTH-Gesellsc
ultraFORTH83
; j REISE
ultraFORTHES ic) 1985 boikssrerme 0 FORTH- Anhang Seite i65
FORTH-Gesellsc
Seite 166 Anhang : berks/rer/we
ultraFoRTH33
ultraFORTH83
1x
>» 1
{N}
a
in
be/ks/re/ue Seite 167
Graphic Glossary
Al m
Das Graphic-Paket für ultraFORTH ermöglicht die einfache Nutzung
der Graphicmöglichkeiten des C64 von FORTH aus. Alle Routinen
wurden auf maximale Geschwindigkeit ausgelegt, daher sind die
grundlegenden Worte wie plot, line etc. in Maschinencode
geschrieben. Das Paket gliedert sich in drei Teile:
1. Hires-Graphic
2. Sprites
3. Turtle Graphic
Die Turtle-Graphic enthält alle vom LOGO her bekannten Befehle,
ebenso sind die in LOGO gebräuchlichen Abkürzungen implementiert.
Dies soll es vor allem dem Anfänger ermöglichen, sich spielerisch
in FORTH einzuarbeiten. Ein geteilter Bildschirm (Window)
ermöglicht auch das interaktive Arbeiten mit den Graphic-Befehlen,
d.h. man kann die Wirkung jedes Befehls unmittelbar am Bildschirm
beobachten.
Die Graphic verbiegt den IR@-Vector des Betriebssystems. Sie ist
deshalb mit Routinen unverträglich, die ihrerseits den IR@-Vector
für eigene Zwecke verstellen. Dies dürfte jedoch nur in den
seltensten Fällen vorkommen und zu Problemen führen.
Ss i erbe
Der Hires-Bildschirm ist in 299 Reihen zu je 328 Punkten
aufgeteilt. Der Punkt (98/9) liegt - wie in Koordinatensystemen
üblich - unten {!) links, der Punkt (319/199) oben rechts. Eine
Prüfung auf die Gültigkeit der eingegebenen Koordinaten findet aus
Geschwindigkeitsgründen nicht statt. Allerdings werden Punkte
außerhalb der Bitmap nicht gezeichnet, um ein versehentliches
überschreiben des Arbeitsspeichers zu verhindern.
Eine Hires-Bitmap belegt 8k RAM. Dazu müssen Bildschirm-, Farbram,
Zeichensatz und Sprites im gleichen 14k-Bereich liegen, da sie der
VIC-Chip anders nicht darstellen kann. Aus diesem Grund wird für
die Graphic der obere iö6k-Bereich ($C999-$FFFF) eingeschaltet.
Dieser Bereich ist folgendermaßen aufgeteilt:
cC288 Videoram für Text
c488 Farbram für Hires-Screen
C898 Bereich für Spritedaten
D808 frei
D888 Charactersatz im RAM t!)
ES9S Hires Bitmap
ACHTUNG : Auf dem cC16 wurde bisher keine Graphik fertig-
gestellt. Wer sich daran versuchen möchte, fordere bitte die
ersten Quelltexte von Claus Vogt an.
ultraFORTH83
SE bp/ks/re/we FORTH-Geseillsc
Seite 168
je rn rn
Die Graphic benutzt ein eigenes Vocabulary, das für den Benutzer
jedoch nicht aufrufbar ist, um ein versehentliches Aufrufen der
Graphic-Worte zu verhindern, wenn der Graphic-Modus nicht
eingeschaltet ist.
graphic -)I
Der Graphic-Bildschirm wird eingeschaltet, die Worte des
Graphic-Vocabularys werden verfügbar, die Taste Fi erhält
eine Umschaltfunktion (s.u.)
Sollen neue Worte ins Graphic-Vocabulary compiliert werden,
lautet die Befehlsfolge
graphic also definitions.
nographic =)
Der Graphic-Modus wird abgeschaltet, der Bildschirm liegt
wieder im normalen Bildschirmbereich etc.
Innerhalb der Graphic gibt es drei Modi:
text t-»
Der gesamte Bildschirm ist im Textmodus. Insbesondere sind
auch alle Editorfunktionen ausführbar. Dieses Wort wird beim
Aufruf von graphic ausgeführt.
hires =?
Der Bildschirm ist im Hires-Modus. Befehle können eingegeben
und ausgführt werden, die Worte sind allerdings nicht
sichtbar.
window in-)
Der Bildschirm wird in zwei Teile geteilt. Die oberen n
Zeilen werden im Hires-Modus dargestellt, der untere Teil im
Text-Modus. In diesem Modus ist interaktives Arbeiten mit
den Graphic-Worten besonders einfach, weil gleichzeitig die
Worte und ihre Wirkung sichtbar sind.
Conmodore-Taste
schaltet zwischen text, graphic und window um. der Aufruf
von graphic stellt 29 Zeilen für den Hires-Bereich und 5
Zeilen für den Text-Bereich ein.
ultraFORTH83
ich 1985 bp/ks/re/we FORTH-d Seite 169
Farbeinstellungen
Die Commodore üblichen Farbcodes können durch sinnvolle
Abkürzungen ersetzt werden:
bilk schwarz (9) wht weiß (2)
red rot i2) eyn cyan 15)
pur purpur (4) grn grün 15)
blu blau (6) yel gelb 7)
ora orange (8) brn braun (9)
ire hellrot (19) gri graui (11)
gr2 grau (12) igr hellgrün (15)
1b1 hellblau (i9) gr3 graus (15)
Irscreen (re) Abkürzung cs
löscht Hires-Bildschirm
border t ceolor - I)
setzt die Rahmenfarbe für den Textmodus. Die Einstellung
bleibt auch beim Rücksprung in den Normalmodus erhalten.
Beispiel: yel border
screen t color - I)
setzt die Hintergrundfarbe für den Textmodus. Die
Einstellung bleibt auch beim Rücksprung in den Normalmodus
erhalten.
Beispiel: blu screen
background t{ color -) Abkürzung b3
setzt die Hintergrundfarbe für den Hiresmodus.
pencolor t color -) Abkürzung pc
setzt die Zeichenfarbe für den Hiresmodus.
colors t background foreground - )
un
ist eine Zusammenfassung der Worte background und pencolor,
setzt gleichzeitig Zeichen- und Hintergrundfarbe für den
Hiresmodus.
Beispiel: yel blu colors
ultraFORTH83
beiksftre/iwe FORTH-Gesellsc
Seite 178
plot IxXy-)
setzt einen Punkt an den Koordinaten (x/y).
unplot iIxy-)
löscht einen Punkt mit den Koordinaten (x/y).
flip Ixy-)
setzt einen Punkt an den Koordinaten (x/y), wenn er gelösch
war, und löscht ihn, wenn er gesetzt war. =
line ( x1i yl x9 y9 -)
zeichnet eine Gerade von (x8/y8) nach (x1/yi). Dieses Wort
besteht aus einer eigenen Maschinenroutine und ist damit
erheblich schneller als eine Schleife mit plot.
dranto {xi yi -)
zeichnet eine Gerade vom zuletzt gezeichneten Punkt zu den
Koordinaten (x1/yil). Der letzte Punkt kann sowohl mit line
als auch mit plot, unplot etc. gezeichnet worden sein. Seine
Koordinaten liegen in den Variablen xpoint und ypoint
(s.u.).
Beispiel: 18 19 159 19 line
159 1528 drawto
19 159 drauwto
18 13 dranwto
zeichnet ein Quadrat.
flipline ( xi1 yi1 x9 y8 -)
ähnlich wie line, doch werden Punkte wie bei flip
umgeschaltet. Insbesondere kann ein zweites Ausführen von
flipline mit denselben Koordinaten den alten Zustand auf der
Bildschirm exakt wiederherstellen.
pointx t- adr )
Eine Variable, die die zuletzt gezeichnete X-Koordinate
anzeigt. Jedes der oben aufgeführten Worte aktualisiert
xpoint
pointy t{ - adr )
Eine Variable, die die zuletzt gezeichnete Y-Koordinate
enthält. Wird wie pointx aktualisiert.
ultraFORTH83
ic} 1986 be/ke/re/ue Seite 171
Worte für Sprites
Der VIC-Chip kann gleichzeitig bis zu 8 Sprites mit den Nummern
(spr#) 93 - 7 darstellen. Im dafür vorgesehenen Buffer können die
Daten von 32 Sprites abgelegt werden. Jedes Sprite benötigt 63
Bytes; der Buffer ist daher in Bereiche zu je 64 Bytes unterteilt,
die über eine Nummer {imem#) zwischen 8 und 51 angesprochen werden
können. Durch geschickte Zuordnung der Buffernummern zu den
Spritenummern eröffnen sich vielfältige Möglichkeiten, da diese
Zuordnung frei wählbar und natürlich auch innerhalb eines
Programms änderbar ist. Sprites werden imner sowohl im Textmodus
als auch im Hiresmodus dargestellt.
getform t( adr mem# - )
holt sich die Daten eines Sprite von Adresse adr in den
Spritebuffer mem#.
Beispiel: 38 block 8 getform
holt die Daten vom Diskettenblock 38 in den Spritebuffer 9.
formsprite { memt spr# - )
ordnet die Spritedaten aus Buffer mem# dem Sprite spr# zu.
Beispiel: 3 4 formsprite
Sprite 4 wird mit den Daten aus Buffer 5 dargestellt.
setsprite * memn# y x color spr# - )
setzt ein Sprite, dessen Daten im Spritebuffer unter der
Nummer mem# liegen, als Sprite spr#. Es erscheint an den
Koordinaten {x/y) in der Farbe color. Für x und y gelten die
bei Commodore üblichen Werte, d.h. (8/8) liegt links oben im
nichtsichtbaren Bereich des Bildschirms.
Beispiel: 8 198 19398 bik 1 setsprite
Dieses Wort faßt mehrere andere (getform, colored etc.)
zusammen, um die Programmierung zu vereinfachen. Als
Nachteil muß die übergabe von 5 Parametern in Kauf nehmen.
setbit (3b adr fl -)
setzt oder löscht in Abhängigkeit von fl das Bit Nummer Sb
im Byte adr. Dieses Wort wird in einigen Spriteworten
Ben benutzt, um gezielt die Werte in den Spriteregistern
beeinflussen zu können.
set ( 3b adr - )
setzt Bit Nummer 3b im Byte adr.
reset (Sb adr .- )
löscht Bit Nummer 3b im Byte adr.
xmove tx spr# - )
bewegt Sprite spr#® an die horizontale Position x.
ynove (y sprt# - )
bewegt Sprite spr#® an die vertikale Position y.
ultraFORTHB3
E Oo bpiksfreine FORTH-Gesellsc
Seite 172
move (yx spr# - )
Zusammenfassung der Worte xmove und ymove.
Die folgenden Befehle beeinflussen die Eigenschaften eines Sprites
high (spr# - )
vergrößert Sprite spr# in y-Richtung.
low t spr& -)
verkleinert Sprite spr#® in y-Richtung.
wide (spr# - )
vergrößert Sprite spr# in x-Richtung.
slim {spr# - )
verkleinert Sprite spr#® in x-Richtung.
big t( spr#t - )
vergrößert Sprite spr# in x- und y-Richtung.
small { spr# - )
verkleinert Sprite spr# in x- und y-Richtung.
behind (spr# - )
Sprite spr# erscheint hinter dem Text.
infront { spr# - )
Sprite spr# erscheint vor dem Text.
eolored ( spr# color - )
setzt Farbe color für Sprite spr#.
Sceolored ( - adr )
übergibt die Adresse des Multicolorregisters auf dem Stack.
Mit der Sequenz
5 Scolored set
wird der Multicolormodus für Sprite 5 eingeschaltet.
sprceolors t color color -)
setzt die Farben für den Multicolormodus.
sprite { - adr )
übergibt die Adresse des Sprite-Anzeigeregisters auf dem
Stack. Mit der Sequenz
4 sprite reset
wird Sprite 4 gelöscht.
ultraFORTH8Z
ic} 193286 bpiks/re/we FORTH-4 Anhang
Seite 173
Zurtle Graphic
Alle von LOGO her bekannten Worte sind mit gleicher Syntax -
allerdings in der Forth-typischen präfix-Notation implementiert.
Allerdings wurde auf die Darstellung der Turtle und damit auf die
Befehle shonwturtle und hideturtie verzichtet. Einige Worte sind
bereits bei der Hires-Graphic besprochen worden:
pencolor (pc)
background (bg)
cirscreen (cs)
Andere Worte haben lediglich zusätzliche Namen erhalten.
Allerdings sind beide Namen in allen Bereichen der Graphic
aufrufbar:
fullscreen ist gleichbedeutend mit hires.
splitscreen ist gleichbedeutend mit window.
heading t- deg)
übergibt die derzeitige Richtung der Turtle auf dem Stack.
8° bedeutet dabei nach rechts, 98°
bedeutet nach oben usw.
setheading . { deg - ) Abkürzung seth
setzt die Richtung der Turtle auf deg Grad. Richtungen s.o.
right t(deg -) Abkürzung rt
dreht die Turtle um deg Grad nach rechts. Bei Üüberschreitung
von 35698° wird ”um die Uhr gerechnet.
left t(deg - ) Abkürzung It
dreht die Turtle um deg Grad nach links. Bei Unterschreitung
von 8° wird ”um die Uhr gerechnet.
forward (n-) Abkürzung fd
bewegt die Turtle um n Schritte in der eingestellten
un Richtung nach vorn. Bei überschreitungen des
Bildschirmrandes werden die Punkte zwar nicht mehr
gezeichnet, aber die Position der Turtle (xcor,ycor)
trotzdem beeinflußt. Der Benutzer muß selbst auf die
Einhaltung der Grenzen achten !
back (n-) Abkürzung bk
bewegt die Turtle um n Schritte in der angegebenen Richtung
zurück. Bei Bereichsüberschreitungen gilt das oben Gesagte.
ultraFORTH83
bprks/rerwe FORTH-Gesellsc
xcor vs)
übergibt die augenblickliche X-Koordinate der Turtle auf dem
Stack.
ycor (-y)
übergibt die augenblickliche Y-Koordinate der Turtle auf dem
Stack.
setx u |
setzt die Turtle auf die *%-Koordinate x.
sety (y-)
setzt die Turtle auf die Y-Koordinate y.
setxy xy)
Zusammenfassung der Befehle setx und sety.
pendown (-) Abkürzung pd
Die Turtle zeichnet bei ihren Bewegungen.
penup -I Abkürzung pu
Die Turtle zeichnet nicht bei ihren Bewegungen.
home ee =)
Die Turtle wird in die Mitte des Bildschirms (179,192)
positioniert mit Richtung nach oben (79°). Der
Schreibstift wird eingeschaltet (pendown).
draw ne)
Der Bildschirm wird gelöscht und in ein Text- und ein
Grapkicftenster unterteilt, die Turtie auf Homeposition
gesetzt.
nodraw (-)I
schaltet in den Textmodus und löscht den Bildschirm.
turtlestate { - pen bg pc ) Abkürzung ts
liefert auf dem Stack den augenblicklichen Zustand der
Turtle in der Reihenfolge Schreibstift an (True) oder aus
(False), Hintergrundfarbe, Schreibfarbe.
ultraFORTH83 | Anhang
ic} 19556 berksz/re/we FORTH-
Seite 175
Der 6502-Assembler
Im folgenden werden die Konzepte des 6502-Assemblers für das
ultraFORTH83 dargestellt. Es wird kein vollständiges Glossar
angegeben, da die Mnemonics des Assemblers allen
Programmierern vertraut sein dürften. Eine genaue Darstellung
der Funktionsweise findet Sie in den FÖRTH DIMENSIÖNS, Vol
III,5 p. 143ff . Im folgenden wird eine kurze Zusammenfassung
angegeben sowie Änderungen gegenüber dem Original dargestellt.
Die Funktionsweise des Adressinterpreters sowie der Routine
NEXT wird in Kapitel 2 dargestellt.
u Der 6502-Assembler gestattet strukturierte Programmierung. Die
Strukturelemente sind analog zu den Kontrollstrukturen des
Forth aufgebaut, tragen jedoch andere Namen, um die
Verwechselungsgefahr zu verringern und die Übersichtlichkeit
zu erhöhen. ;
Ein Beispiel:
cc ?[ <ausdrucki> ][ <ausdruck2 ]?
cc steht für "condition code" . <sausdruckl> wird ausgeführt,
wenn cc zutrifft, andernfalls <ausdruck2> . Der Teil
]E <sausdruck2>
kann auch weggelassen werden. Das Analogen in Forth ist IF
ELSE ... THEN
Beachten Sie bitte, daß vor ?[ immer (!) ein condition code
stehen muß. Außerdem findet keine Prüfung auf korrekte
Verschachtelung der Kontrollstrukturen statt.
Weitere Kontrollstrukturen sind:
[[ <ausdruck1> cc ?[[ <ausdruck2» ]]?
[[ <ausdruckl1> cc ?]
[[ <ausdruck1> ]]
Die analogen Ausdrücke in Forth wären
BEGIN <ausdruck1> WHILE <ausdruck2> REPEAT
BEGIN <ausdrucki> UNTIL
BEGIN <ausdruck1> REPEAT
Auch hier darf bei den Assemblerworten cc nicht weggelassen
werden. Außerdem ist nur genau ein ?[[ zwischen |[ und
]1? zulässig. Beachten Sie bitte auch den Unterschied zwischen
1] und 1]? !
Als condition code sind zulässig
0= 0<> 0< 0>= CS CC V5 VC
Seite 176 Anhang SE boi/ks/re/we FORTH-Gesellsc ultraFORTH8S
Sie können den Prozessor-Flags 2 N C und V zugeordnet werden.
Im ersten Beispiel wird also <ausdruckl> ausgeführt, wenn oc
durch 0= ersetzt wird und das Z-Flag gesetzt ist. Jeden der
condition codes kann man durch ein folgendes NOT erweitern,
also z2.B.:
0= NOT ?[ 0 # Ida ]?
Neben allen anderen Opcodes mit ihren Adressierungsarten gibt
es auch die Sprünge BCC BCS usw. Sie sind nur in der
Adressierungsart Absolut zulässig, d.h. auf dem Stack
befindet sich die Adresse des Sprungzieles. Liegt diese
Adresse außerhalb des möglichen Bereiches, so wird die
Fehlermeldung "out of range" ausgegeben.
Für die anderen Opcodes sind, je nach Befehl, die folgenden
Adressierungsarten zulässig:
A # X ;sY X) )Y )
Die Adressierungsart Absolut wird verwendet, wenn keine andere
angegeben wurde. Wird mit einem Mnemonic eine nicht erlaubte
Adressierungsart verwendet, so wird die Fehlermeldung
"invalid" ausgegeben.
Beispiele für die Verwendung des 6502-Assemblers (zur
Erläuterung wird die herkömmliche Notation hinzugefüst)
.a rol rola
1 # ldy ldy #1
data X sta sta data,x
$6 x) adc adc ($6,x)
vector )y lda lda (vector),y
vector ) jmp jmp (vector)
Zusätzlich enthält das System noch mehrere Macros, die alle
nur Absolut adressieren können:
winc - Inkrementiert einen 16-Bit-Zeiger um 1. wdec
dekrementiert analog.
2inc - Inkrementiert einen 16-Bit-Zeiger um 2. 2dec
dekrementiert analog.
;c: - Schaltet den Assembler ab und den Forth-Compiler
an. Damit ist es möglich, von Maschinencode in Forth
überzuwechseln. Ein Gegenstück ist nicht vorhanden.
Ein Beispiel für die Verwendung von ;C: ist:
0< ?f ;c: ." Fehler" ; Assembler |]?
ultraFORTH83 Anhang
ic} 1958 be/ks/re/we FORTH-Q
Seite 177
Ist irgendwas kleiner als Null, so wird "Fehler" ausgedruckt
und die Ausführung des Wortes abgebrochen, sonst geht es
weiter im Code.
Schließlich gibt es noch die Worte >LABEL und LABEL .
>LABEL erzeugt ein Label im Heap, wobei es den Wert des Labels
vom Stack nimmt. LABEL erzeugt ein Label mit dem Wert von
HERE. Beispiel:
Label schleife dex
schleife bne
Ein Codewort muß letztendlich immer auf NEXT JMP führen,
u damit der Adressinterpreter weiter arbeitet. Im folgenden
Glossar werden Konstanten angegeben, auf die gesprungen werden
kann und die Werte auf den Stack bringen bzw. von ihm
entfernen. Wichtig ist insbesondere die Routine SETUP. Sie
kopiert die Anzahl von Werten, die im Akkumulator angegeben
wird, in den Speicherbereich ab N.
Für den Zugriff auf den Stack wird, soweit das möglich ist,
die Benutzung der Worte SETUP und PUSH ... empfohlen. Das
reicht allerdings häufig nicht aus. In diesem Fall kann man
die Werte auf dem Stack folgendermaßen zugreifen:
SP x) Ida \ Das untere Byte des ersten Wertes
SP )y lda \ Das obere Byte des ersten Wertes
sowie durch Setzen des Y-Registers auch die zweiten, dritten
etc. Werte. Beachten Sie bitte, das in NEXT verlangt wird,
daß das X-Register den Inhalt $00 und das Y-Register den
Inhalt $01 hat. Das wurde im obigen Beispiel ausgenutzt.
Beispiele für Assemblercode in Forth, den wir als gut
empfinden, sind unter Anderem die Worte FILL und -TRAILING
Wollen Sie Assembler programmieren, so sollten Sie sich
diese Worte und noch einige andere ansehen.
Beim Assemblerprogrammieren muß beachtet werden, daß ultraFORTH
das ROM abschaltet. Daher müssen Lesezugriffe ins ROM etwas
_ anders organisiert werden.
Beispiel für den C16:
ffd2 jsr springt eine RAM-Routine an.
ff3e sta ffd2 jsr ff3f sta springt eine ROM-Routine an.
Sie funktioniert nur, wenn sie im unteren RAM-Bereich (<$8000)
steht. Sonst folgen undefinierte Reaktionen.
Beim cC64 ist eine Bankumschaltung nur für Lesezugriffe in das
BASIC-ROM erforderlich. Hierbei ist zusätzlich zu beachten, daß
eine Bankumschaltung mit SEI vorbereitet werden muß, da
andernfalls der periodische Tastaturinterrupt zu einem Absturz
führen würde.
Auf dem C16 ist kein SEI erforderlich, da im RAM der Vektor
$FFFE auf eine eigene Interruptroutine zeigt (sie benötigt ca.
1 Promille der Rechenzeit). Aus dem gleichen Grund führt eine
BRK - Instruktion zwar weiterhin in den Monitor, allerdings mit
falschem Registerdump, da der Monitor auf dem Stack die Daten
der Interruptroutine statt der Register vorfindet.
ultraFORTH83
Seite 176
be/ks/re/we FORTH-Gesellsc
Assembler
PushA -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die den Inhalt des Akku vorzeichenbehaftet auf den
Datenstack legt und dann zu NEXT springt. Wird als
letzter Sprungbefehl in Code-Worten benutzt.
Push8A -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die den Inhalt des Akku auf das Low-Byte des
Datenstacks ablegt. Das High-Byte wird grundsätzlich auf 8
gesetzt. Anschliessend wird zu NEXT gesprungen. Wird als
letzter Sprungbefehl in Code-Worten benutzt.
Push -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die den Inhalt des Akku als High-Byte auf den
Datenstack legt. Das Low-Byte wird vom prozessorstack
geholt und muß vorher dort abgelegt worden sein.
Anschliessend wird zu NEXT gesprungen. Wird als letzter
Sprungbefehl in Code-Worten benutzt.
Next -- addr
Eine Konstante, die die Adresse von NEXT auf den
Datenstack legt. Wird als letzter Befehl in Code-Worten
benutzt.
xyNext Sesaddr
Wie NEXT jedoch werden vorher das X-Register mit 8 und
das Y-Register mit 1 geladen. Das System erwartet
grundsätzlich bei Aufruf von NEXT diese Werte in den
Registern. Ansonsten reagiert es mit \bsturz.
Puta -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die den Akku als Low-Byte auf den Datenstack
ablegt. Das High-Byte wird nicht verändert, ebenso wird im
Gegensatz zu PUSH kein Platz auf dem Datenstack
geschaffen. Anschliessend wird NEXT durchlaufen. Wird als
letzter Befehl in Code-Worten benutzt.
Pop -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die das oberste Element vom Datenstack entfernt.
Anschliessend wird zu NEXT gesprungen. Wird als letzter
Sprungbefehl in Code-Worten benutzt.
Poptwo . -- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die die obersten beiden Elemente vom Datenstack
entfernt. Anschliessend wird zu NEXT gesprungen. Wird als
letzter Sprungbefehl in Code-Worten benutzt.
ultraFORTH83
RP
UP
sP
ER
setup
wemp
ram
rom
Sys
ic} 1925 berks/re/iwe FORTH-J
Seite 179
-- addr
Eine Konstante, die die Adresse des Returnstackpointers
enthält.
-- addr
Eine Konstante, die die Adresse des Userpointers, also des
Offsets zu ORIGIN enthält.
-- addr
Eine Konstante, die die Adresse des Datenstackpointers
enthält.
-- addr
Eine Konstante, die die Adresse des Instruktionspointers
der Forth-Maschine enthält. Dieser zeigt auf das jeweils
nächste abzuarbeitende Wort.
-- addr
Eine Konstante, die die Adresse des Wort-Pointers der Forth-
Maschine enthält. Dieser zeigt auf das jeweils gerade
bearbeitete Wort.
-- addr
Eine Konstante, die die Adresse eines Speicherbereichs in
der Zeropage enthält, der dem Anwender zur Verfügung steht.
-- addr
Eine Konstante, die die Adresse einer Maschinencode-Sequenz
enthält, die n Elemente vom Datenstack abbaut und bei N
ablegt. Die Anzahl n muß im Akku stehen, wenn SETUP als
Subroutine angesprungen wird. Das oberste Element des
Datenstacks liegt Bei N , das zweite bei N+2 etc. Zum
Schluß werden X- und Y-Register auf 9 bzw. 1 gesetzt.
( addri1 addr2 -- )
Dieses Assemblermakro assembliert eine Sequenz, die
bei Ausführung den Inhalt des Wortes an addri mit dem
Inhalt des Wortes an addr2 vergleicht. Anschließend
ist das Carry-Flag high, wenn der Inhalt von addri
größer oder gleich dem Inhalt von addr2 ist.
Es werden der Akku sowie die Statusregisterflags CZ
O N verändert.
=)
Makro. Schaltet bei Ausführung auf eine andere Spei-
cherbank. Die genaue Wirkungsweise ist maschinenab-
hängig.
(=)
Makro. Schaltet bei Ausführung auf eine andere Spei-
cherbank. Die genaue Wirkungsweise ist maschinenab-
hängig.
( addr-- )
Makro. Schaltet bei Ausführung auf eine Speicherbank
mit Systemroutinen und führt jsr aus. Die genaue
Wirkungsweise ist maschinenabhängig.
Seite 188
Anhang
E. bRiks/re/we
FORTH-Gesellsc
ultraFORTH83
ultraFORTH83 ic) 1385 be/kssrerue FORTH- Anhang Seite i8i
Abweichungen des ultraFORTH83 von
Programmieren in Forth
Die Gründe für die zahlreichen Abweichungen des Buches
"Starting Forth" bzw. "Programmieren in Forth" (Hanser, 1984)
von Leo Brodie wurden bereits im Prolog aufgeführt. Sie sollen
nicht wiederholt werden. Das Referenzbuch ist, trotz
offenkundiger Mängel in Übersetzung und Satz, die deutsche
Version, da sie erheblich weiter verbreitet sein dürfte. Im
folgenden werden nicht nur Abweichungen aufgelistet, sondern
auch einige Fehler mit angegeben. Die Liste erhebt keinen
Anspruch auf Vollständigkeit. Wir bitten alle Leser, uns
weitere Tips und Hinweise mitzuteilen. Selbstverständlich gilt
das auch für alle anderen Teile dieses Handbuchs. Vielleicht
wird es in der Zukunft ein Programm geben, das es ermöglicht,
Programme aus "Starting Forth" direkt, ohne daß man diese
Liste im Kopf haben muß, einzugeben.
Kapitel 1 - Grundlagen
3 -) Das ultraFORTH System befindet sich nach dem
Einschalten im Hexadezimal-Modus. Daher muß man, um
die folgenden Beispiele des Buches eingeben zu
können, erst DECIMAL eintippen. Danach werden
alle folgenden Zahlen als Dezimalzahlen
interpretiert. Außerdem dürfen alle Worte auch klein
geschrieben werden. Das Beispiel lautet dann:
decimal 15 spaces
7 -) im ultraFORTH System wurde statt "Lexikon"
konsequent der Begriff "Dictionary" verwendet.
9 -) Statt "?" durckt das ultraFORTH "haeh?" , wenn
XLERB eingegeben wird.
-) Selbstverständlich akzeptiert das ultraFORTH Namen
mit bis zu 31 Zeichen Länge.
ı Seite 187 Anhang H berks/re/we FORTH-Gesellsc ultraFORTH83
11 -) Im ultraFORTH kann auch der Hochpfeil "*" als
Zeichen eines Namens verwendet werden.
-) Fußnote 6 : Der 83-Standard legt fest, daß ." nur
innerhalb von Definitionen verwendet werden darf.
Außerhalb muß man .( verwenden.
17 -) Das ultraFORTH gibt bei Stackleerlauf irgendeine
Zahl aus, nicht unbedingt eine Null ! Nebenbei
bemerkt: Das ultraFORTH ist das erste System auf dem
664, für den der Satz mit dem großen Stack wirklich
zutrifft, denn dort können sich nun typisch mehr als
tausend Werte befinden.
18 -) Druckfehler : Bei dem Beispiel (n -- ) muß zwischen
"(" und "n" ein Leerzeichen stehen. Das gilt auch
für viele der folgenden Kommentare.
19 -) Bei dem Wort EMIT muß man natürlich angeben, in
welchem Code das Zeichen kodiert ist. Beim
ultraFORTH auf dem C64 ist das nicht der
ASCII-Zeichensatz, sondern der
Commodore-spezifische. Am Besten ist es, statt 42
EMIT lieber ASCII * EMIT einzugeben.
Kapitel 2 - Wie man in Forth rechnet
23 -) Druckfehler : Selbstverständlich ist 10 1000 *
kleiner als 32767, kann also berechnet werden.
Kurios wird es nämlich erst bei 100 1000 x
31 -) Die Operatoren /MOD und MOD arbeiten laut
83-Standard mit vorzeichenbehafteten Zahlen. Die
Definition von Rest und Quotient bei negativen
Zahlen findet man unter "Division, floored" in
"Definition der Begriffe" oder unter /MOD im
Glossar.
Seien Sie bitte bei allen Multiplikations- und
Divisionsoperatoren äußerst mißtrauisch und schauen
Sie ins Handbuch. Es gibt keinen Bereich von Forth,
wo die Abweichungen der Systeme untereinander größer
sind als hier.
ultraFORTH83 ic3 1985 bp/ksfre/uie FORTH- Anhang Seite 183
38 -) .S ist im System als Wort vorhanden. Unser .S
druckt nichts aus, wenn der Stack leer ist. Auch die
Reihenfolge der Werte ist andersherum, der oberste
Wert steht ganz links. Alle Zahlen werden
vorzeichenlos gedruckt, d.h. -1 erscheint als 65535
-) S heißt im ultraFORTH SPe@
-) Das Wort DO funktioniert nach dem 83-Standard
anders als im Buch. .S druckt nämlich, falls kein
Wert auf dem Stack liegt, 32768 Werte aus. Ersetzt
man DO durch ?DO , so funktioniert das Wort .S
aber nur dann, wenn man 2- wegläßt. Nebenbei
bemerkt ist es sehr schlechter Stil, den Stack
direkt zu addressieren !
39 -) <ROT ist im ultraFORTH unter dem Namen -ROT
vorhanden.
-) Im ultraFORTH gibt es das Wort 20OVER nicht.
Benutze:
Zover 3 pick 3 pick ;
Kapitel 3 - Der Editor und externe Textspeicherung
Beim ultraFORTH auf dem C64 wird ein leistungsfähiger
Bildschirmeditor mitgeliefert, dessen Bedienung sich von dem
im Buch benutzten Zeileneditor stark unterscheidet. Wir haben
jedoch den im Buch verwendeten Editor zum System dazugepackt.
Er wurde geringfügig modifiziert.
46 -) Das ultraFORTH für den C64 stellt auf einem
Diskettenlaufwerk 170 Blöcke zur Verfügung. Um den
Bildschirm besser ausnutzen zu können, wurden sie in
— 24 Zeilen mit je 41 Zeichen und eine Zeile mit 40
Zeichen aufgeteilt. Bei den Zeilen mit 41 Zeichen
ist das 41. Zeichen nicht sichtbar.
48 -) Bevor man Editor-Worte benutzen kann, muß man erst
EDITOR eingeben.
55 -) Das Wort F gibt nicht NONE aus, sondern
positioniert nur auf das erste Zeichen in der ersten
Zeile, wenn der Text nicht gefunden wurde.
[Seite 184 Anhang H bEErhSFeTerWe FÜRTH-Gesellsc ultraFORTH83
56
60
61
66
75
84
84
Mit .I kann man sich den I-Puffer und mit .F den
Suchpuffer ansehen.
Das ultraFORTH besitzt sowohl die Worte FLUSH als
auch SAVE-BUFFERS . Beim Diskettenwechsel sollten
sie FLUSH verwenden.
Das FLUSH nach COPY ist unnötig.
S gibt nur die Zeilennummer aus, und zwar vor dem
Inhalt der Zeile, in der der Text gefunden wurde.
M ist zu gefährlich. Der Editor sollte keine
fremden Screens ruinieren. Benutzen Sie das Wort G
oder BRING
DEPTH ist vorhanden, S heißt SP@ . Wegen der
Abweichungen beim Wort DO und der Stackadressen
muß 4 - weggelassen werden.
Kapitel 4 - Entscheidungen
Die Vergleichsoperatoren müssen nach dem 83-Standard
-1 auf den Stack legen, wenn die Bedingung wahr ist.
Dieser Unterschied zieht sich durch das ganze Buch
und wird im folgenden nicht mehr extra erwähnt. Also
: -1 ist "wahr" ,„ 0 ist "falsch" . Daher entspricht
O= nicht mehr NOT. NOT invertiert nämlich jedes
der 16 Bit einer Zahl, während 0= falsch liefert,
wenn mindestens eins der 16 Bit gesetzt ist.
Überall, wo NOT steht, sollten Sie 0= verwenden.
Das Wort ?STACK im ultraFORTH liefert keinen Wert,
sondern bricht die Ausführung ab, wenn der Stack
über- oder leerläuft. Daher ist das Wort ABORT"
überflüssig.
Statt -< muß es in der Aufgabenstellung 6
natürlich =< heißen. Für positive Zahlen tut
UWITHIN im ultraFORTH dasselbe.
ultraFORTH83 Xc} 1988 bowkszrerwe FORTH- Anhang Seite 155
Kapitel 5 - Die Philosophie der Festkomma-Arithmetik
89 -) Eine Kopie des obersten Wertes auf dem Returnstack
bekommt man beim ultraFORTH mit R@ . Die Worte I
und J liefern die Indices von DO-Schleifen. Bei
einigen Forth-Systemen stimmt der Index mit dem
ersten bzw. dritten Element auf dem Returnstack
überein. Der dann mögliche und hier dokumentierte
Mißbrauch dieser Worte stellt ein Beispiel für
schlechten Programmierstil dar. Also: Benutzen sie
I und J nur in DO-Schleifen.
91 -) Die angedeutete Umschaltung zwischen Vokabularen
geschieht anders als beim ultraFORTH.
93 -) Fußnote: Es trifft nicht immer zu, daß die Umsetzung
von Fließkommazahlen länger dauert als die von
Integerzahlen. Insbesondere dauert die Umsetzung von
Zahlen beim ultraFORTH länger als z.B. bei
verschiedenen BASIC-Interpretern. Der Grund ist
darin zu suchen, daß die BASICs nur Zahlen zur Basis
10 ausgeben und daher für dieses Basis optimierte
Routinen verwenden können während das ultraFORTH
Zahlen zu beliebigen Basen verarbeiten kann. Es ist
aber durchaus möglich, bei Beschränkung auf die
Basis 10 eine erheblich schnellere Zahlenausgabe zu
programmieren.
98 -) x/MOD im ultraFORTH arbeitet mit
vorzeichenbehafteten Zahlen. Der Quotient ist nur 16
Bit lang.
Kapitel 6 - Schleifenstrukturen
104 -) Die Graphik auf dieser Seite stellt
Implementationsdetails dar, die für das polyFORTH
gelten, nicht aber für das ultraFORTH. Reißen Sie
bitte diese Seite aus dem Buch heraus.
108 -) J liefert zwar den Index der äußeren Schleife, aber
nicht den 3. Wert auf dem Returnstack.
ultraFORTH83
"Seite Ib | Anhang E-
brrkstrerue FORTH-Gesellsıc
110 -) Das Beispiel TEST funktioniert nicht. Beim
83-Standard sind DO und LOOP geändert worden, so
daß sie jezt den gesamten Zahlenbereich von
0...65535 durchlaufen können. Eine Schleife nn DO
LOOP exekutiert also jetzt 65536 - mal und nicht
nur einmal, wie es früher war.
111 -) Beim ultraFORTH wird beim Eingeben von
nichtexistenten Worten nicht der Stack geleert, denn
der Textinterpreter führt nicht ABORT" aus,
sondern ERROR" . Den Stack leert man durch Eingabe
der Worte CLEARSTACK oder ABORT
114 -) LEAVE wurde im 83-Standard so geändert, daß sofort
bei Ausführen von LEAVE die Schleife verlassen
wird und nicht erst beim nächsten LOOP. Daher ändert
LEAVE auch nicht die obere Grenze.
Kapitel 7 - Zahlen, Zahlen, Zahlen
125 -) Erinnern Sie sich bitte daran, daß EMIT beim
ultraFORTH auf dem C64 keinen ASCII Code
verarbeitet. Außerdem ist es Systemabhängig, ob
EMIT Steuerzeichen ausgeben kann.
130 -) Seien Sie .mißtrauisch ! Das Wort U/MOD heißt im
83-Standard UM/MOD .
-) Das Wort /LOOP ist nun überflüssig geworden, da
das normale Wort LOOP bereits alle Zahlen
durchlaufen kann.
132 -) Beim ultraFORTH werden nur Zahlen, die "," oder “."
enthalten, als 32-Bit Zahlen interpretiert. "/" und
“ sind nicht erlaubt.
137 -) Der 83-Standard legt fest, daß SIGN ein negatives
Vorzeichen schreibt, wenn der oberste (und nicht der
dritte) Wert negativ ist. Ersetzen Sie bitte jedes
SIGN durch ROT SIGN , wenn Sie Beispiele aus dem
Buch abtippen.
-) Für HOLD gilt dasselbe wie das für EMIT
(Abweichung Seite 19) gesagte. Benutzen Sie statt
46 HOLD besser ASCII - HOLD
ultraFORTH83 F-—-—
140
141
Fr 143
149
158
=)
>)
bo/ks/re/ue FORTH-J Anhang
D- DMAX DMIN und DU< sind nicht vorhanden.
32-Bit Zahlen können in eine Definition geschrieben
werden, indem sie durch einen Punkt gekennzeichnet
werden. Die Warnung für experimentierfreudige Leser
trifft beim ultraFORTH also nicht zu.
M+ M/ und Mx/ sind nicht vorhanden.
können Sie M/MOD NIP
EXTEND D+
Für M/
einsetzen und für M+ etwa
UX heißt im 83-Standard UMk und U/MOD UM/MOD
Aufgabe 7 ist großer Quark !
viele Forth-Systeme als doppelt genaue Null
interpretieren, bedeutet nicht, daß es sich um
keinen Fehler der Zahlenkonversion handelt. Das
ultraFORTH toleriert solche Fehleingaben nicht.
Die Tatsache, daß
Kapitel 8 - Variablen, Konstanten und Felder
2VARIABLE 2@ und 2! sind nicht im System
enthalten
2@ dup 2+ @ swap @ ;
a rot over 2+ |! ı 5
2Variable Variable 2 allot ;
2Constant Create , , Does> 2@ ;
Kapitel 9 - Forth intern
Zu den Fußnoten 1,2 Der 83-Standard schreibt für
das Wort FIND ein anderes Verhalten vor, als hier
angegeben wird. Insbesondere sucht FIND nicht nach
dem nächsten Wort im Eingabestrom, sondern nimmt als
Parameter die Adresse einer Zeichenkette (counted
String), nach der gesucht werden soll. Auch die auf
dem Stack abgelegten Werte sind anders
vorgeschrieben.
Das Beispiel 38 GRENZE |! ist schlechter Forth
Stil; es ist verpönt, Konstanten zu ändern. Da das
Wort ’° nach dem 83-Standard die Kompilationsadresse
des folgenden Wortes liefert (und nicht die
Parameterfeldadresse), der Wert einer Konstanten
aber häufig in ihrem Parameterfeld aufbewahrt wird,
funktioniert das Beispiel auf vielen Forth Systemen,
Seite 187
Anhang E Oo bpiks/re/we FORTH-Sezellsc ultraFORTHB3
Seite 188
die dem 83-Standard entsprechen, folgendermaßen:
38 ” GRENZE >BODY !
179 -) Fußnote 3 : Die Fußnote trifft für den 83-Standard
nicht zu. verhält sich wie im Text beschrieben.
180 -) Das ultraFORTH erkennt 32-Bit Zahlen bereits
serienmäßig, daher gibt es kein Wort NUMBER
Wollen Sie eigene Zahlenformate erkennen (etwa
Floating Point Zahlen) , so können Sie dafür das
deferred Wort NOTFOUND benutzen.
181 -) Die vorgestellte Struktur eines Lexikoneintrags ist
nur häufig anzutreffen, aber weder vorgeschrieben
noch zwingend. Zum Beispiel gibt es Systeme, die
keinen Code Pointer aufweisen. Das ultraFORTH sieht
jedoch ähnlich wie das hier vorgestellte polyFORTH
aus.
188 -) Druckfehler : Statt ABORT muß es ABORT" heißen.
189 -) Der 83-Standard schreibt nicht vor, daß EXIT die
Interpretation eines Disk-Blockes beendet. Es
funktioniert zwar auch beim ultraFORTH, aber Sie
benutzen besser das Wort \N\
190 -) Die Forth Geographie gilt für das ultraFORTH nicht;
einige der Abweichungen sind :
-) Die Variable H heißt im ultraFORTH DP
(=Dictionary Pointer)
-) Der Eingabepuffer befindet sich nicht bei S0 ,
sondern TIB liefert dessen Adresse.
-) Der Bereich der Benutzervariablen liegt woanders.
191 -) Zusätzliche Definitionen : Beim ultraFORTH ist die
Bibliothek anders organisiert. Ein
Inhaltsverzeichnis der Disketten finden sie häufig
auf Block 1
197 -) Der Multitasker beim ultraFORTH ist gegenüber dem
des polyFORTH vereinfacht. So besitzen alle
Terminal-Einheiten (wir nennen sie Tasks) gemeinsam
nur ein Lexikon und einen Eingabepuffer. Es darf
daher nur der OPERATOR (wir nennen in Main- oder
Konsolen-Task) kompilieren.
ultraFORTH83 Anhang
“c) 1985 bo/ks/re/we FORTH-
Seite 189
198 -) Im ultaFORTH sind SCR R# CONTEXT CURRENT >IN
und BLK keine Benutzervariablen.
200 -) Das über Vokabulare gesagte trifft auch für das
ultraFORTH zu, genaueres finden Sie unter
Vokabularstruktur im Handbuch.
202 -) LOCATE heißt im ultraFORTH VIEW
ne 203 -) EXECUTE benötigt nach dem 83-Standard die
Kompilationsadresse und nicht mehr die
Parameterfeldadresse eines Wortes. Im Zusammenhang
mit ’” stört das nicht, da auch geändert wurde.
Kapitel 10 - Ein- und Ausgabeoperationen
211 -) Die angesprochene Funktion von FLUSH führt nach
dem 83-Standard das Wort SAVE-BUFFERS aus. Es
schreibt alle geänderten Puffer auf die Diskette
zurück. Das Wort FLUSH existiert ebenfalls. Es
unterscheidet sich von SAVE-BUFFERS dadurch, daß
es nach dem zurückschreiben alle Puffer löscht. Die
Definition ist einfach :
flush save-buffers empty-buffers ;
FLUSH wird benutzt, wenn man die Diskette wechseln
will, damit von BLOCK auch wirklich der Inhalt
dieser Diskette geliefert wird.
-) Fußnote 4 trifft für das ultraFORTH nicht zu.
212 -) Der 83-Standard schreibt vor, daß BUFFER sehr wohl
darauf achtet, ob ein Puffer für diesen Block
bereits existiert. PBUFFER verhält sich genauso wie
BLOCK , mit dem einzigen Unterschied, daß das evtl.
erforderliche Lesen des Blocks von der Diskette
entfällt.
213 -) Wie schon erwähnt, muß bei den Beispielen auf dieser
Seite SO @ durch TIB ersetzt werden. Ebenso muß
TEST durch °’ TEST >BODY ersetzt werden. Das
gilt auch für das folgende Beispiel BEZEICHNUNG
| Seite 198 Anhang E be/ksfrerwe FORTH-Gesellsc ultraFORTH83
218 -) Beim C64 sind Zeilen nur 41 Zeichen lang. Verwenden
Sie bitte statt 64 die Konstante C/L . Sie gibt
die Länge der Zeilen in einem System an.
217 -) Druckfehler : WORT ist durch QUATSCH zu ersetzen.
219 -) <CMOVE heißt nach dem 83-Standard CMOVE> . Der
Pfeil soll dabei andeuten, daß man das Wort benutzt,
um im Speicher vorwärts zu kopieren. Vorher war
gemeint, daß das Wort am hinteren Ende anfängt.
-) Für MOVE wird im 83-Standard ein anderes Verhalten
vorgeschlagen. MOVE wählt zwischen CMOVE und
CMOVE> ,„ je nachdem , in welche Richtung verschoben
wird.
220 -) Auch für KEY gilt das für EMIT gesagte: Der
Zeichensatz beim C64 ist nicht ASCII.
-) Statt der Systemabhängigen Zahl 32 sollte besser die
Konstante BL verwendet werden !
223 -) TEXT ist nicht vorhandern.
-) Fußnote 10 : QUERY ist auch im 83-Standard
vorgeschrieben.
-) WORD kann, muß aber nicht seine Zeichenkette bei
HERE ablegen.
224 -) Nach dem 83-Standard darf EXPECT dem Text keine
Null mehr anfügen.
229 -) Fußnote 14 : PTR heißt beim ultraFORTH DPL (=
decimal point location)
230 -) Ersetzen sie WITHIN durch UWITHIN oder
?INNERHALB. NOT muß durch 0= ersetzt werden, da
die beiden Worte nicht mehr identisch sind.
232 -) Druckfehler in Fußnote 15 : Der Name des Wortes ist
natürlich -TEXT und nicht TEXT . Außerdem müssen
die ersten beiden "/" durch "@" ersetat werden.
Das dritte "/" ist richtig.
ultraFORTHBS Ds on Ford Anhang gite 191]
Kapitel 11 - Wie man Compiler erweitert...
247 -) BEGIN DO usw. sehen im ultraFORTH anders aus,
damit mehr Fehler erkannt werden können.
248 -) Fußnote 2 : Die Erläuterungen beziehen sich auf
polyFORTH, im ultraFORTH siehts wieder mal anders
aus. Die Frage ist wohl nicht unberechtigt, warum in
einem Lehrbuch solche implementationsabhängigen
Details vorgeführt werden.
-) Fußnote 3 : Eine Konstante im ultraFORTH kommt,
falls sie namenlos (siehe Kapitel "Der Heap" im
Handbuch) definiert wurde, mit 2 Zellen aus.
249 -) Die zweite Definition von A4DAZU funktioniert beim
ultraFORTH nicht, da das Wort : dem ; während
der Kompilation Werte auf dem Stack übergibt. Das
ist durch den 83-Standard erlaubt.
250 -) Druckfehler : Statt L[SAG-HALLO] muß es [
SAG-HALLO ] heißen.
251 -) Die Beispiele für LITERAL auf dieser Seite
funktionieren, da LITERAL standartgemäß benutzt
wird.
-) Druckfehler : Statt ICH SELBST muß es ICH-SELBST
heißen.
252 -) Bei Definitionen, die länger als eine Zeile sind,
druckt das ultraFORTH am Ende jeder Zeile
"compiling"” statt "ok" aus.
255 -) Die Beispiele für INTERPRET und ] entstammen dem
polyFORTH. Eine andere Lösung wurde im ultraFORTH
verwirklicht. Hier gibt es zwei Routinen, je eine
für den interpretierenden und kompilierenden
Zustand. INTERPRET führt diese Routinen vektoriell
aus.
-) Fußnote 4 trifft für das ultraFORTH nicht zu.
| Seite 192 Anhang E EpR/ksfre/iwe FORTH-GSesellse ultraFORTH83
Kapitel 12 - Drei Beispiele
270 -) Druckfehler : In WÖRTER ist ein 2DROP zuviel;
ferner sollte >- >IN sein.
-) In BUZZ muß es statt WORT .WORT heißen.
(Reingefallen : Es muß WÖRTER sein!)
239 -) Die Variable SEED muß wohl SAAT heißen. Ob der
Übersetzer jemals dieses Programm kompiliert hat?
-) Nebenbei: Im amerikanischen Original hatten die
Worte NÄCHSTES WÖRTER FÜLLWÖRTER und EINLEITUNG
noch einen Stackkommentar, ohne die das Programm
unverständlich wird, besonders bei diesem
fürchterlichen Satz. Also, wenn Sie an Ihren
Fähigkeiten zweifeln, sollten Sie sich das
amerikanische Original besorgen.
| ultraFORTH83 = bE/ks/re/ue FORTH-9 Anhang Seite 133
Abweichungen des ultraFORTH83 von
FORTH TOOLS
von A. Anderson & M. Tracy
p.15 GLEAR macht im ultraFORTH3833 etwas anderes als in FORTH
TOOLS. Benutze statt CLEAR das Wort CLEARSTACK oder
definiere
clearstack Alias clear
Bun p.27 .S druckt die Werte auf dem Stack anders herum aus,
ausserdem fehlt der Text "Stack: "
p.34 20VER 2ROT fehlen. Benutze
2over 3 pick 3 pick ;
2rot BE zoll 5 woll ;
p.41 Es gibt noch keine Files.
p.42 Es gibt noch kein Wort DICTIONARY
p.45 THRU druckt keine Punkte aus.
p.46 Der Editor funktioniert anders. Ausserdem enthaelt
eine Zeile beim C-64 nur 40 Zeichen und nicht 64.
p.64 ultraFORTH83 enthaelt kein Wort ?. Benutze
9
@.;
p.73 Die Worte 2! 2@ 2VARIABLE und Z2CONSTANT fehlen.
Benutze
2Variable Variable 2 allot ;
2Constant Create , , Does> 2@ ,;
2! rot over 2+ ! !
2@ dup 2+ @ swap @ ;
p.99 AGAIN gibt es nicht. Benutze stattdessen REPEAT oder
definiere
tn, REPEAT Alias AGAIN immediate restrict
p.103 Benutze extend Alias s>d
p.107 DU< fehlt.
p.116 SPAN enthaelt 6 Zeichen, da "SPAN ?" genau 6 Zeichen
lang ist. Das System benutzt naemlich ebenfalls
EXPECT. Daher geht das Beispiel auf Seite 117 auch
nicht. Damit es geht, muss man alle Worte in einer
Definition zusammenfassen.
p.118 CPACK entspricht dem Wort PLACE.
Seite 194 Anhang £ berksfrerue FORTH-üesellsc ultraFORTHB3
p.125 Benutze
String Create dup , 0 c, allot Does» 1+ count ;
p.126 " kann nicht interpretiert werden. Zwei
Gaensefuesschen hintereinander sind ebenfalls nicht
erlaubt.
p.141 Das Wort IS aus dem ultraFORTH383 kann innerhalb von
Definitionen benutzt werden.
p.146 Es gibt keine Variable WIDTH , da bei Namen alle
Zeichen gueltig sind.
».149 Benutze
»link >»name 2- ;
link> 2+ name> ;
n>1link za
l>name +;
p.166 STOP entspricht \\
p.167 Bei FIND kann das Flag auch die Werte -2 oder +2
annehmen.
p.184 ORDER ist nicht in ONLY , sondern in FORTH
enthalten. Ausserdem druckt es auch nicht "Context: "
oder "Current:" aus. Current wird stattdessen einfach
zwei Leerzeichen hinter Context ausgegeben.
N ultraFORTH8Z
(c} 1985 bp/ks/re/ne FORTH-C Anhang Seite 195
Targetcompiler-Worte
Das ultraFORTH83-System wurde mit einem sog. Targetcopiler
erzeugt. Dieser Targetcompiler compiliert ähnlichen Quelltext
wie das ultraFORTH83-System. Es gibt jedoch Unterschiede.
Insbesondere sind im Quelltext des ultraFORTH83 Worte enthal-
ten, die der Steuerung des Targetcompilers dienen, also nicht
im Quelltext definiert werden. Wenn Sie sich also über eine
Stelle des Quelltextes sehr wundern, sollten Sie in .der
folgenden Liste die fragwürdigen Worte suchen.
Eine andere Besonderheit betrifft Uservariablen. Wenn im Quell-
text der Ausdruck [ <name> ] LITERAL auftaucht und <name>
eine Uservariable ist, so wird bei der späteren Ausführung des
Ausdrucks NICHT die Adresse der Uservariablen in der Userarea
sondern die Adresse in dem Speicherbereich, in dem sich die
Kaltstartwerte der Uservariablen befinden, auf den Stack
gelegt.
Wenn die Kaltstartwerte von Uservariablen benötigt werden, wird
dieser Ausdruck benutzt.
Folgende Worte im Quelltext werden vom Targetcompiler benutzt:
origin! Target >here nonrelocate Host Transient Tudp
Tvoc-link move-threads .unresolved
sowie eine Anzahl weiterer Worte.
Die mitgelieferte Quelle des Systems gilt für drei Versionen:
Die C64-Version, die C16-Version für 64 KByte (mit Interrupt-
Handling) und eine leicht abgemagerte C16-Version, die nur 32
KByte nutzen kann und dafür keine INTERRUPT-Umleitung braucht.
Zur Kennzeichnung dieser Vielfalt dienen Worte, die von manchen
Rechnern als Kommentare interpretiert werden, auf anderen aber
Code erzeugen (Achtung : Die im Quelltext des ultraFoORTH83-
Kerns verwendete Syntax unterscheidet sich von der in den
anderen Quelltexten verwendeten !).
Im Einzelnen sind das folgende Worte: (die Definitionen gelten,
wenn Code für den C16+ erzeugt werden soll.)
für alle Commodores
te ; immediate
für C64 : (c64 [compile] ( ; immediate
für C16/C116 & Plus4 : (c16 ; immediate
für C16/C116 & Plus4-64k : (c16+ ; immediate
für C16/C116 & Plus4-32k : (c16- [compile] ( ; immediate
die Schließende Klammer : ) ; immediate
Alles, was bis zur nächsten schließenden Klammer auf das Wort
(Cc64 folgt, wird also auf einem C16 als Kommentar verstanden.
Auf einem C64 werden die obigen Definitionen natürlich so
geändert, daß alles, was auf die Worter (C16 (C16+ und (c16-
folgt, als Kommentar aufgefaßt wird.
Seite 196 Dp/kssre/we FORTH-Gesellsc ultraFoRTH63
Vor der Targetcompilierung müssen sie ggf. umdefiniert werden
(s. Quelldiskette). Bei der Arbeit mit diesen Worten muß
man
allerdings höllisch aufpassen. Beispiele für Fehler sind:
1;) (ce : xx ( Kommentar ) ....;)
2.) CODE xx (c16 ..... ) -(c64 ::0% ) next jmp end-code
3.) (ce CODE yy .... SP )Y1da ....)
Am häßlichsten ist 2.), weil es beim Ausführen ohne jede
Meldung zu einem todsicheren System-Zusammenbruch führt. Daher
wird im Quelltext in einem solchen Fall eher:
(ei6 ««. U)
geschrieben. Wer die Beispiele nicht versteht, bedenke, daß
die Worte (C usw. nach der nächsten (!) schließenden Klammer
suchen und daß }Y sowie ) Worte des Assemblers sind.
Die Worte, die im laufenden System eine ähnliche Funktion
ausführen, sind (16 (64 und C) (siehe Glossar). Sie sind
so abgesichert, daß die genannten Fehlerquellen wegfallen.
1 ultraFoRThe3
«“e3 1985 bprks/rer/ne FORTH-:
Seite 197 |
Meldungen des ultraFORTH83
Das ultraFORTH83 gibt verschiedene Fehlermeldungen und Warnun-
gen aus. Zum Teil wird dabei das zuletzt eingegebene Wort
wiederholt. Diese Meldungen sind im folgenden nach Gruppen
getrennt, aufgelistet:
Kernel
Der eingegebene String konnte nicht mit NUMBER in eine
Zahl umgewandelt werden. Beachten Sie den Inhalt von BASE.
beyond capacity
Der angesprochene Block ist physikalisch nicht vorhanden.
Beachten Sie den Inhalt von OFFSET.
C) missing
Das Ende der Eingabezeile oder des Screens wurde erreicht,
bevor das zu (64 oder (16 gehörende C) gefunden wurde.
compiling
Das System befindet sich im compilierenden Zustand und
erwartet die Eingabe einer Zeile.
compile only
Das eingegebene Wort darf nur innerhalb von :-Definitionen
verwendet werden.
crash
Es wurde ein deferred Wort aufgerufen, dem noch kein
auszuführendes Wort mit IS zugewiesen wurde.
Dictionary £full
Der Speicher für das Dictionary ist erschöpft. Sie müssen
die Speicherverteilung ändern oder Worte mit FORGET ver-
gessen.
division overflow
Die Division zweier Zahlen wurde abgebrochen, da das Ergeb-
nis nicht im Zahlenbereich darstellbar ist.
exists
Das zuletzt definierte Wort ist im Definitons-Vokabular
schon vorhanden. Dies ist kein Fehler, sondern nur ein
Hinweis!
haeh?
Das eingegebene Wort konnte weder im Dictionary gefunden
noch als Zahl interpretiert werden.
invalid name
Der Name des definierten Wortes ist zu lang (mehr als 31
Zeichen) oder zu kurz (Der Name sollte dem definierenden
Wort unmittelbar folgen).
Seite 198 res mn UltrarORTHBI
is symbol
Das Wort, das mit FORGET vergessen werden sollte, befindet
sich auf dem Heap. Benutzen Sie dafür CLEAR.
ok
Das System befindet sich im interpretierenden Zustand und
erwartet die Eingabe einer Zeile.
nein
Der Bereich von Blöcken, der mit CONVEY kopiert werden
sollte, ist leer oder viel zu groß.
no file
Auf Ihrem System sind keine Files benutzbar. Die Variable
FILE muß daher den Wert Null haben.
not deferred
Es wurde versucht, mit IS einem Wort, das nicht deferred
ist, eine auszuführende Prozedur zuzuweisen.
no device
Das angewählte Gerät konnte über den seriellen Bus nicht
angesprochen werden.
protected
Es wurde versucht, ein Wort zu vergessen, das mit SAVE
geschützt wurde. Benutzen Sie die Phrase:
<name> >name 4 - (forget save
wobei <name> der Name des zu vergessenden Wortes ist.
read error ! r to retry
Bei einem Lesezugriff auf die Diskette trat ein Fehler auf.
Durch Drücken der Taste <R> wird ein erneuter Leseversuch
gestartet. Bei Drücken einer anderen Taste wird die Meldung
"aborted" ausgegeben und ABORT ausgeführt.
stack empty
Es wurden mehr Werte vom Stack genommen als vorhanden waren.
still £ull
Nach der Meldung DICTIONARY FULL wurde noch kein Platz im
Dictionary geschaffen. Holen Sie das unverzüglich nach,
indem Sie einige Worte mit FORGET vergessen !
tight stack
Es befanden sich zuviele Werte auf dem Stack, so daß der
Speicher erschöpft war. Legen Sie weniger Werte auf den
Stack, oder sparen Sie Speicherplatz im Dictionary.
ultraFORTH83 rev 3.8
Dies ist die Einschaltmeldung des ultraFORTH83.
unstructured
Kontrollstrukturen wurden falsch verschachtelt oder weg-
gelassen. Diese Fehlermeldung wird auch ausgegeben, wenn
sich die Zahl der Werte während der Kompilation einer :-
Definition zwischen : und ; geändert hat.
7 ultraFoRTH83
(c) 1985 bp/ks/re/we Seite 199
Userarea full
Es wurden mehr als 124 Uservariablen definiert. Das ist
nicht zulässig.
Vocabulary stack full
Es wurden zuviele Vokabulare mit ALSO in den festen Teil
der Suchreihenfolge übernommen. Benutzen Sie ONLY oder
TOSS, um Vokabulare zu entfernen.
write error ! r to retry
Siehe " read error ..."
|<name>
Der Name des ausgegebenen Wortes befindet sich auf dem Heap
und ist nach einem CLEAR nicht mehr sichtbar.
RELOCATION
returnstack ?
Der Speicherplatz, der nach Ausführung von RELOCATE für den
Returnstack übrig bliebe, ist zu klein.
stack ?
Der Speicherplatz, der nach Ausführung von BUFFERS oder
RELOCATE für das Dictionary übrig bliebe, ist zu klein.
buffers ?
Bei Ausführung würde RELOCATE keinen Blockbuffer im System
lassen. Prüfen Sie die Argumente von RELOCATE. Die Anweisung
0 BUFFERS ist natürlich ebenfalls nicht zulässig.
ASSEMBLER
invalid
Die Kombination von Opcode und Adressierungsart ist nicht
zulässig.
not here
Es wird in einem Speicherbereich assembliert, in dem das
Makro ROM nicht angewendet werden darf.
out of range
Es wurde versucht, mit einem Branch außerhalb des Bereiches
von -128..+127 Bytes zu springen.
Seite 208 bp/ksfre/we FORTH-Gesellst ultraFoRTH83
EDITOR
£from keyboard
Das Wort, das VIEW auffinden soll, wurde von der Tastatur
aus eingegeben. Es kann daher nicht auf dem Massenspeicher
gefunden werden.
your stamp :
Sie werden aufgefordet, ihr Namenskürzel einzugeben. Denken
Sie sich eines aus; es kann z.B. aus Ihren Initialien und
dem Datum bestehen.
KASSETTENVERSION
ChSumErr
Beim Screentausch über den Userport trat ein Prüfsummen-
fehler auf.
error ### : <meldung> load/save
Eine LI/O-Operation konnte nicht durchgeführt werden, weil
der Fehler <meldung> auftrat.
no ramdäisk
Es existiert keine Ramdisk. Wenn Sie eine Ramdisk benutzen
wollen, müssen Sie sie zuerst einrichten (s. "ultraFORTH83
für Kassettenrecorder" ).
ramdisk full
Die Ramdisk ist voll. Löschen Sie Screens oder Sichern Sie
die Ramdisk und legen Sie eine neue an (s. RDDEL EMPTY-
BUFFERS ).
range!
Die bei Ausführung von RDNEW auf dem Stack befindlichen
Werte sind nicht plausibel.
STXxXxX
Das ist die Einschaltmeldung des Supertape.
SyncErr
Analog ChSumErr
terminated
Analog ChSumErr
ultraFORTH83
“c) 1985 bp/ks/re/ue Seite 201
VERSCHIEDENES
can't be DEBUGged
Der Tracer kann das zu tracende Wort nicht verarbeiten
Evtl. ist es in Maschinencode geschrieben.
save-error
SAVESYSTEM gibt diese Meldung aus.
Task error
Eine Task hat ABORT" oder ERROR" ausgeführt,
was norma-
lerweise einen Systemabsturz versursacht.
trace dump is
Siehe Kap. 7.3 des Handbuches
[Seite 202 Anhang H BPFKSSre/ue
FORTH-Gesellsc
ultraFORTH83
ultraForTNö3 1 =
»
#tbs
#cr
#s
—t#tib
abort
"cold
'quit
'restart
's
(
(
(16
(16
(64
(64
(drv
(error
(forget
(load
(pad
(quit
(rd
(search
%*
*%**ultraFoORTH8
*/
*/mod
+
+!
+
+load
rLOOP
+LOOP
+thru
r
r
--)
--)
-1
-roll
-rot
-trailing
Seite 283
INDEX der im Handbuch erklärten Forthworte
Gruppe
Speicher
Strings
Strings
Strings
Strings
In/Output
In/Output
Strings
In/Output
Dictionary
Sonstiges
Sonstiges
Sonstiges
Sonstiges
Multitasking
Interpreter
Interpreter
C64-special
C64-special
C64-special
C64-special
C64-special
Fehler
Dictionary
Editor
Editor
Sonstiges
Kassetten
Stack vorher
( 16b addr
( string
( addr
( blk +n
(
(
(
Editor( text tlen buf blen
Arithmetik
C64-Special
Arithmetik
Arithmetik
Arithmetik
Speicher
Editor
Interpreter
Kontroll
Kontroll
Interpreter
Dictionary
Compiler
Arithmetik
Interpreter
Interpreter
Arithmetik
(ww
(
{nin2n3
(niln2n3
(ww
( wi adr
(n
(n
On
( sys
(nin2
( 16b
(
(ww
(
(
(
Stack( 16bn..16b1l 16b0 +n
Stack
In/Output
In/Output
In/Output
In/Output
In/Output
In/Output
( 16b1 16b2 16b3
( addr +nO
(n
(
= mm
Stack nachher
)
) compiling
addr )
addr )
addr +n )
n)
n)
00)
addr )
addr )
)
)
)
)
usraddr )
) compiling
compiling
)
)
) compiling
addr )
)
)
)
adr )
)
addr )
adr tf // ff)
w)
)
nd )
nA n5)
w )
compiling
3)
a a
) compiling
-1)
16b0 16bn..16b1 )
16b3 16b1 16b2 )
addr +ni )
)
)
) compiling
)
) compiling
[seite 204 Anhang H bP/ks/re/ue
.blk
„name
„status
/
/mod
/string
0
%
0%
0=
0
1
1+
1-
1541r/w
2
2!
2%
2+
2-
2/
2e
2Constant
2Constant
2disk1551
2drop
2dup
2swap
2Variable
2Variable
3
3+
4
NDc
Inarann
>
»body
»drive
»in
>interpret
>name
»r
»tib
2er
?device
?DO
?DO
?dup
?dup
?exit
?head
162
91
121
129
82
106
713
c64-Special
Dictionary
In/Output
Kassetten
Stack
Sonstiges
Arithnmetik
Arithmetik
Strings
Arithmetik
Logik/Vergl.
Logik/Vergl.
Logik/Vergl.
Logik/Vergl.
Arithmetik
Arithmetik
Arithmetik
C64-special
Arithmetik
32-Bit-Worte
Arithnetik
Arithmetik
Arithnmetik
Arithmetik
32-Bit-Worte
32-Bit-Worte
32-Bit-Worte
MaSputil
Stack
Stack
Stack
32-Bit-Worte
32-Bit-Worte
Arithmetik
Arithmetik
Arithmetik
Kassetten
Datentypen
Datentypen
Datentypen
Logik/Vergl.
Strings
Logik/Vergl.
Logik/Vergl.
Dictionary
Massensp.
Interpreter
Interpreter
Dictionary
Returnstack
In/Output
In/Output
Cc64-special
Kontroll
Kontroll
Stack
Stack
Kontroll
Heap
(
( addr
(n+n
(
(?
(
(nin2
(niln2
( addri ni n2
u
( addr block file n
(
{ 32b addr
("1
(wm
(w
(nl
( addr
( 32b
(
(
( 32b
( 32b
{ 32b1 32b2
(
(
(
(w
(
{ 8b
(
(
( sys
(nin2
(
(ww
(nn
( addri
( block drv#
{
{
( addri
( 16b
{
{
( dev#
(1
(
(0
( 16b
( £lag
(
FORTH-Gesellsc
ultraFORTH8S
)
n3 )
n3 nA )
addr2 n3 )
0)
flag
flag
flag
flag
1-))
w2)
w2 )
flag )
ar)
)
w2 )
w2 )
w2)
n2 )
32b )
) compiling
32b )
)
)
32b 32b )
32b2 32b1 )
) compiling
addr )
3)
w2)
4)
7b )
sys )
)
) compiling
flag )
)
flag )
flag )
addr2 )
block' )
addr )
num
)
addr2 )
)
addr )
)
)
)
sys ) compiling
0)
16b 16b )
)
addr )
?pairs
?stack
[compile]
[compile]
\
\
\\
\\
\IF
\needs
1
]
abort
Abort"
Abort"
abs
accumulate
activate
Alias
all-buffers
allot
allotbuffer
also
and
Ascii
Ascii
Assembler
at
at?
autoload
B
b/blk
b/buf
bamallocate
base
BEGIN
BEGIN
binary
bl
blk
blk/drv
bload
block
bounds
bsave
buffer
bus!
buse
busclose
busin
businput
busoff
ultraFORTHö3
104
104
100
100
100
100
100
103
103
103
103
129
103
103
103
104
104
104
74
86
117
88
108
108
93
76
99
99
93
122
122
129
62
108
108
133
122
96
96
129
122
101
108
129
108
96
129
108
112
112
112
112
112
112
“c) 1985 bp/ksfre/we
Fehler
Fehler
Speicher
Compiler
Compiler
Compiler
Compiler
Compiler
Compiler
Interpreter
Interpreter
Interpreter
Interpreter
Kassetten
Interpreter
Interpreter
Interpreter
Fehler
Fehler
Fehler
Arithmetik
Strings
Multitasking
Datentypen
Massensp.
Dictionary
Massensp.
Vocabulary
Logik/Vergl.
Conpiler
Compiler
Vocabulary
In/Output
In/Output
Kassetten
Dekompiler
Massensp.
Massensp.
MaSputil
In/Output
Kontroll
Kontroll
Kassetten
In/Output
Interpreter
Massensp.
Kassetten
Massensp.
Kontroll
Kassetten
Massensp.
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
(niln2
( addr
AA nn nnnnnnnen
{
(
{ £lag
(n
( +d1 addr char
( Taddr
( cfa
(w
( row col
(
(
( addr
(
(
(
(
(
( sys
(u
(
(
(
( addr1 addr3 8b
(u
( start count
( al a2 a3 8b
(u
( 8b
(
( dev# And
( dev# 2nd
( addr u
(
Seite 205
16b )
)
) compiling
) compiling
addr )
compiling
compiling
compiling
zu u uuvuo
compiling
compiling
)
d2 addr )
+2 vw
yo...
3}
) compiling
char )
)
)
row col )
addr )
)
&1024 )
n)
)
addr )
)
) compiling
u)
n)
addr )
n)
addr2 )
addr )
limit start )
)
addr )
)
8b )
un
[Seite 206 _| Anhang H ge
busopen
busout
bustype
bye
ce!
c)
€)
c,
e/l
c64at
c64at?
c64cr
c64decode
c64del
c64emit
c64expect
c64fkeys
c64init
c64key
c64key?
c64page
c64type
c>)7
c@
capital
capitalize
case?
case?
cbm>scr
clear
clearstack
cload
cmove
cmove)>
col
cold
commodore
compess
compile
con!
Constant
context
convert
convey
copy
copy2disk
copydisk
core?
core?
count
cpush
er
Create
Create
Create:
Create:
csave
112
112
113
106
62
78
127
127
91
122
113
113
113
113
113
113
113
114
114
114
114
129
78
86
86
76
16
162
91
82
130
78
718
122
106
130
130
99
114
88
93
86
109
109
133
133
109
109
718
128
122
126
126
126
130
C64-special
C64-special
C64-special
Sonstiges
Dekompiler
Speicher
Cc64-special
C64-special
Dictionary
In/Output
C64-special
Cc64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
C64-special
Kassetten
Speicher
Strings
Strings
Logik/Vergl.
Logik/Vergl.
C64-Special
Dictionary
Stack
Kassetten
Speicher
Speicher
In/Output
Sonstiges
Kassetten
Kassetten
Compiler
C64-special
Datentypen
Vocabulary
Strings
Massensp.
Massensp.
MaSputil
MaSputil
Massensp.
Massensp.
Speicher
Tools
In/Output
Datentypen
Datentypen
Datentypen
Datentypen
Kassetten
( dev# 2nd
( dev# 2nd
( addr u
(
( addr
( 16b addr
(
(
( 16b
(
( row col
(
(
( addr lenO key
(
( 8b
( addr len
{
(
(
{
(
( addr len
( 8b
( addr
( chari
( addr
( 16b1 16b2
( 16b 16b
(
e2
( addri addr3 8b ul
( from to u
( from to u
(
(
(
( addri addr3 ul
(
( 8b
( 16b
(
( +41 addri
( bik1 bl1k2 to.blk
(ul u2
(
(ul u2 u3
( bik file
( blk file
( addr
( addr u
{
(
(
(
(
1
( al a2 a3 8b u
FORTH-Gesellse
ultraFORTHB3
compiling
n)
ow col )
ddr leni )
zu, zu onuo +4 uuun
©
o
=
flag )
)
)
7b )
8b )
char2 )
addr )
16b1 false )
true )
)
A )
addr2 u2 )
)
)
u)
)
)
u2 )
)
)
)
addr )
+d2 addr2 )
)
)
)
)
addr )
false )
addr+1 len )
)
)
) compiling
pfa )
) compiling
pfa )
u2 )
ctoggle
curoff
curon
current
D
d+
d.
d.r
d0=
a
dabs
debug
decimal
decode
Defer
definitions
del
depth
derr?
derror?
device
digidecode
digit?
digit?
digits
diskclose
diskerr
diskopen
display
dnegate
DO
Do
Does>
Does)
dp
drive
drop
drv?
dup
ediboard
edidecode
ediexpect
edit
Editor
ELSE
ELSE
emit
empty
enpty-buffers
end-trace
endloop
erase
Error"
Error"
errorhandler
execute
exit
ultraFoORTH83
718
114
114
93
62
80
122
122
80
80
80
128
123
123
89
93
123
82
130
114
130
159
86
86
159
115
104
115
115
80
96
96
99
99
91
109
82
109
83
159
159
159
151
159
96
96
123
91
109
107
128
719
105
105
105
97
126
“c> 1985 bp/ks/re/ue
Speicher
Cc64-special
C64-special
Vocabulary
Dekonmpiler
32-Bit-Worte
In/Output
In/Output
32-Bit-Worte
32-Bit-Worte
32-Bit-Worte
Tools
In/Output
In/Output
Datentypen
Vocabulary
In/Output
Stack
Kassetten
c64-special
Kassetten
Editor
Strings
Strings
Editor
C64-special
Fehler
C64-special
C64-special
32-Bit-Worte
Kontroll
Kontroll
Compiler
Compiler
Dictionary
Massensp.
Stack
Massensp.
Stack
Editor
Editor
Editor
Editor
Editor
Kontroll
Kontroll
In/Output
Dictionary
Massensp.
Sonstiges
Tools
Speicher
Fehler
Fehler
Fehler
Kontroll
Kontroll
( 8b addr
( addr +nO key
mm E nm n
( adr lenO key
( char
( char
( drv#
( 16b
( block
( 16b
(
( adr lenO key
( adr len
(n
(
(
( sysi
( 16b
Ford Anhang Seite 287
flag )
flag )
ud )
)
)
addr +nl )
)
)
)
n)
flag )
flag )
addr )
adr leni )
digit true )
false )
)
)
)
flag )
)
d2 )
)
sys ) compiling
) compiling
addr )
addr )
)
)
drv# )
16b 16b )
)
adr leni )
)
)
)
)
sys2 ) compiling
compiling
ddr )
u oo ou
[seite 208 Anhang H bp/ks/re/us
expand
expect
extend
false
file
fill
find
findex
first
£loppy
flush
forget
formatdisk
Forth
forth-83
FORTH-Gesellsc
freebuffer
getkey
getstamp
hallot
heap
heap?
here
hex
hide
hold
I
i/o
id"
IF
IF
imnediate
index
ink-pot
input
Input:
interpret
IP
Is
J
K
key
key?
keyboard
1
l/s
last
LEAVE
limit
list
Literal
Literal
FORTH-Gesellsc
ultraFORTH83
130 Kassetten
123 In/Output
80 32-Bit-Worte
76 Logik/Vergl.
109 Massensp.
719 Speicher
101 Interpreter
115 cC64-special
109 Massensp.
130 Kassetten
109 Massensp.
91 Dictionary
133 MaSputil
93 Vocabulary
93 Vocabulary
162 C64-Special
109 Massensp.
115 C64-special
160 Editor
95 Heap
95 Heap
95 Heap
92 Dictionary
123 In/Output
92 Dictionary
86 Strings
97 Kontroll
115 cC64-special
131 Kassetten
97 Kontroll
97 Kontroll
99 Compiler
115 C64-special
116 cC64-special
123 In/Output
89 Datentypen
102 Interpreter
179 Assembler
89 Datentypen
97 Kontroll
62 Dekompiler
123 In/Output
124 In/Output
116 C64-special
151 Editor
124 In/Output
92 Dictionary
97 Kontroll
110 Massensp.
124 In/Output
99 Compiler
99 Compiler
( addri addr2 ul
( addr +n
(n
(
(
( adr u 8b
( addri
( £rom to
(
(
(
(
(
(
(
( 8b0
(
mo
a
AUDEAÄAnAnnDS
u2 )
d)
0)
addr )
)
addr2 n )
addr )
om u _uunn
addr )
flag )
addr )
)
)
)
w)
semaphoraddr )
)
)
sys ) compiling
)
)
addr )
addr )
)
)
addr )
+n )
addr )
)
addr )
)
) compiling
16b )
ultraFoRTH83
ic) 1985 bp/ks/re/ue FORTH-G Anhang Seite 289
load 102 Interpreter (n--)
loadramdisk 131 Kassetten (==)
lock 117 Multitasking ( semaddr -- )
LOOP 97 Kontroll (--)
LOOP 97 Kontroll ( sys -- ) compiling
m* 80 32-Bit-Worte (nin2--d)
m/mod 80 32-Bit-Worte (dnl--n2n3)
max 74 Arithmetik (nn-n)
mentop 131 Kassetten ( -- adr )
min 75 Arithmetik (nin2--n3)
mod 75 Arithmetik (n11n2-n)
move 79 Speicher ( addri addr2 u -- )
multitask 117 Multitasking (=)
N 62 Dekompiler ( addr -- )
N 179 Assembler ( -- addr )
n" 131 Kassetten ( -- addr 8b )
name 102 Interpreter ( -- addr )
name) 92 Dictionary ( addri1 -- addr2 )
negate 75 Arithmetik (nl--n2)
nest 128 Tools 5
Next 178 Assembler ( -- addr )
nip 83 Stack ( 16b1 16b2 -- 16b2 )
noop 107 Sonstiges =-9
not 76 Logik/Vergl. (n1--n2)
notfound 102 Interpreter ( addr -- )
nullstring? 86 Strings ( addr -- addr false )
nullstring? 86 Strings ( addr -- true )
number 86 Strings (addr --d)
number? 87 Strings ( addr -- addr false )
number? 87 Strings (addr --d0 )
number? 87 Strings (addr --n0<)
off 79 Speicher ( addr -- )
offset 110 Massensp. ( -- addr )
on 79 Speicher ( addr -- )
Only 93 Vocabulary tn)
Onlyforth 93 _Vocabulary ("rn
or 76 Logik/Vergl. (nin2--n3)
order 126 Vokabular (a--)
origin 92 Dictionary ( -- addr )
output 124 In/Output ( -- addr )
Output: 90 Datentypen (=)
over 83 Stack ( 16b1 16b2 -- 16b1 16b2 16b1 )
pad 79 Speicher ( -- addr )
page 124 In/Output ( 2)
parse 102 Interpreter ( char -- addr +n )
pass 117 Multitasking ( nO..nr-1 Taddr r -- )
pause 118 Multitasking ))
perform 97 Kontroll ( addr -- )
pick 83 Stack ( 16bn..16b0 +n -- 16bn..16b0 16bn )
place 79 Speicher ( addri +n addr2 -- )
Pop 178 Assembler ( -- addr )
Poptwo 178 Assembler ( -- addr )
prev 110 Massensp. ( -- addr )
printable? 116 C64-special ( 8b -- 8b flag )
push 84 Returnstack ( addr -- )
[seite 218 Anhang H bp/ks/re/we
Push
PushOA
PushA
Puta
query
quit
E
r#
r/w
r0
T
r@®
ram
ramdisk
ramR/W
rd
rdcheck
rddel
rdepth
rdnew
rdrop
rduse
readsector
recursive
recursive
rendezvous
REPEAT
REPEAT
restart
restore"
restrict
reveal
roll
rom
rot
row
RP
rp!
rp@
rvsoff
rvson
5
so
save
save-buffers
saveramdisk
savesystem
scan
scr
scr>cbn
seal
setup
shadow
showload
sign
singletask
FORTH-Gesellsc
ultraFoORTH83
178 Assembler
178 Assembler
178 Assembler
178 Assembler
124 In/Output
102 Interpreter
151 Editor
107 Sonstiges
110 Massensp.
84 Returnstack
84 Returnstack
84 Returnstack
179 Assembler
131 Kassetten
131
131 Kassetten
131 Kassetten
131 Kassetten
84 Returnstack
131 Kassetten
84 Returnstack
131 Kassetten
116 C64-special
100 Compiler
100 Compiler
118 Multitasking
97 Kontroll
97 Kontroll
107 Sonstiges
131 Kassetten
100 Compiler
92 Dictionary
83 Stack
179 Assembler
83 Stack
124 In/Output
179 Assembler
84 Returnstack
84 Returnstack
162 C64-Special
162 C64-Special
62 Dekompiler
83 Stack
92 Dictionary
110 Massensp.
132 Kassetten
133 MaSputil
87 Strings
107 Sonstiges
162 C64-Special
93 Vocabulary
179 Assembler
160 Editor
161 Editor
87 Strings
113 Multitasking
Kassetten( addri1 u addr2 fla
nn nn
(
(
( addr block file n
(
(
(
{
(
I
{
{
(
(
( addri addr2
(
( addr
( addr tra# sect
(
(
( semaddr
( 16bn 16bm..16b0
( 16b1 16b2 16b3
(
(
( addr
(
(
(
( addr
mn. nann
( addri nl char
(
( 8b0
addr
addr
addr
addr
6bm..16b0 16bn )
16b2 16b3 16b1 )
n)
addr )
)
addr )
addr2 n2 )
addr )
8bl )
)
addr )
adr )
)
)
)
5 ultraFORTH83
«c) 1985 bp/ks/re/ue
ron Anhang ESerte ZU]
skip 87 Strings ( addri n1 char -- addr2 n2 )
sleep 118 Multitasking ( Taddr -- )
source 102 Interpreter ( -- addr +n )
SP 179 Assenbler ( -- addr )
sp! 83 Stack ( addr -- )
spe 83 Stack ( -- addr )
space 124 In/Output (--)
spaces 124 In/Output (+n--)
span 125 In/Output ( -- addr )
stamp$ 160 Editor ( -- adr )
standardi/o 125 In/Output => ))
state 102 Interpreter ( -- addr )
stop 118 Multitasking (--)
stop? 125 In/Output ( -- flag )
store 132 Kassetten ( addr -- )
supertape 132 Kassetten (e== )
swap 83 Stack ( 16b1 16b2 -- 16b2 16bl )
sys 179 Assembler ( addr -- )
tapeinit 132 Kassetten =)
Task 119 Multitasking ( rlen slen -- )
tasks 119 Multitasking (u)
THEN 97 Kontroll (--)
THEN 97 Kontroll ( sys -- ) compiling
thru 103 Interpreter (nin2--)
tib 125 In/Output ( -- addr )
toss 94 Vocabulary ==
trace' 128 Tools (==)
true 77 Logik/Vergl. ==1)
type 125 In/Output ( addr tn -- )
u. 125 In/Output (u-)
u.r 125 In/Output (um--)
u/mod 75 Arithmetik (ul u2 -- u3u4)
u 77 Logik/Vergl. (ul u2 -- flag )
u) 77 Logik/Vergl. (ul u2 -- flag )
uallot 92 Dictionary (nl --n2)
ud/mod 80 32-Bit-Worte ( udi1 ul -- u2 ud2 )
udp 92 Dictionary ( -- addr )
um* 80 32-Bit-Worte (ul u2 -- ud)
um/mod 81 32-Bit-Worte (udul --u2 u)
umax 75 Arithmetik (uw2--W3)
umin 75 Arithmetik (un2--W)
unbug 128 Tools =)
under 83 Stack ( 16b1 16b2 -- 16b2 16b1 16b2 )
unlink 162 C64-Special (=)
unlock 119 Multitasking ( semaddr -- )
unnest 128 Tools ==)
UNTIL 98 Kontroll ( flag -- )
UNTIL 98 Kontroll ( sys -- ) compiling
UP 179 Assembler ( -- addr )
up! 120 Multitasking ( addr -- )
up®@ 119 Multitasking ( -- Taddr )
update 110 Massensp. (r==7)
User 9f Datentypen ==)
uwithin 77 Logik/Vergl. (nulu2 -- flag )
v 160 Editor (- Mm)
Variable 90 Datentypen ' (=)
Lseite 217 Anhang H bpiks/re/ue
view
voc-link
Vocabulary
vp
wake
warning
wcmp
WHILE
WHILE
word
words
writesector
zor
xyNext
FORTH-Gesellsch
ultraFoRTH83
151 Editor
94 Vocabulary
90 Datentypen
94 Vocabulary
120 Multitasking
105 Fehler
179 Assembler
98 Kontroll
98 Kontroll
103 Interpreter
94 Vocabulary
116 C64-special
77 Logik/Vergl.
178 Assenbler
95 Heap
(
(
(
(
( Taddr
(
( addri addr2
( flag
( sysi
( char
(
( addr traf seck
(n1n2
(
(
addr )
addr )
addr )
sys2 )
addr )
compiling
flag )
n3 )
addr )
ultraFORTH6Z
Gen 1B0E Deruazrarun Form Anhang Gere 213]
Index Graphikworte für C64
3colored 172 Sprites ( -- adr )
back 173 Turtle (n-)
background 169 Graphik ( color -- )
behind 172 Sprites ( spr# -—-)
bg 169 Graphik { wlor -- )
big 172 Sprites (spr# -- )
bk 173 Turtle en=-=)
blk 169 Graphik ( -- color )
blu 169 Graphik ( -- color )
border 169 Graphik ( color -- )
brn 169 Graphik ( -- color )
clrscreen 169 Graphik ==)
colored 172 Sprites ( spr# color -- )
colors 169 Graphik ( color color -- )
cs 169 Graphik ==)
cyn 169 Graphik ( -- color )
draw 174 Turtle (--)
drawto 170 Graphik (x1yl --)
fd 173 Turtle FR --)
flip 170 Graphik (xrY-)
flipline 170 Graphik (x1y1x0 y0 --)
formsprite 171 Sprites ( men# spr# -- )
forward 173 Turtle (nn -=)
getforn 171 Sprites ( adr mem# -- )
gri 169 Graphik ( -- color )
gr2 169 Graphik ( -- color )
gr3 169 Graphik ( -- color )
graphic 168 Graphik (--)
grn 169 Graphik ( -- color )
heading 173 Turtle ( -- deg )
high 172 Sprites ( spr# -- )
hires 168 Graphik (--)
home 174 Turtle (=)
infront 172 Sprites ( spr# -- )
1bl 169 Graphik ( -- color )
left 173 Turtle ( deg -- )
lgr 169 Graphik ( -- color )
line 170 Graphik (x1y1x0 y0 --)
low 172 Sprites ( spr# -- )
lre 169 Graphik ( -- color )
lt 173 Turtle ( deg -- )
move 172 Sprites (xyspr# --)
nodraw 174 Turtle (--)
nographic 168 Graphik ==)
ora 169 Graphik ( -- color )
pc 169 Graphik ( color -- )
pd 174 Turtle (--)
pencolor 169 Graphik ( color -- )
pendown 174 Turtle (=)
penup 174 Turtle (--)
plot 170 Graphik (xy-)
pointx "170 Graphik ( -- addr )
pointy 170 Graphik ( -- addr )
pu 174 Turtle (--)
pur 169 Graphik ( -- color )
red 169 Graphik ( -- color )
Anhang
EoAusrerme ma UltrafORTNET
Seite 214
reset 171 Sprites ( 3b adr -- )
right 173 Turtle ( deg -- )
rt 173 Turtle (deg -- )
screen 169 Graphik ( color -- )
set 171 Sprites ( 3b adr -- )
setbit 171 Sprites ( 3b adr flag -- )
seth 173 Turtle ( deg -- )
setheading 173 Turtle ( deg -- )
setsprite 171 Sprites( mem# y x color spr -- )
setx 174 Turtle (>
setxy 174 Turtle [$:-)
sety 174 Turtle (vry--)
slim 172 Sprites (spr# -- )
small 172 Sprites (spr# -- )
sprcolors 172 Sprites ( color color -- )
sprite 172 Sprites ( -- adr )
text 168 Graphik g-—)
ts 174 Turtle ( -- pen bg pc )
turtlestate 174 Turtle ( -- pen bg pc )
unplot 170 Graphik (xy--)
wht 169 Graphik ( -- color )
wide 172 Sprites ( spr# -- )
window 168 Graphik („n) ==)
xcor 174 Turtle (--x)
xmove 171 Sprites (x spr# -- )
ycor 174 Turtle (-y)
yel 169 Graphik ( -- color )
ymove 171 Sprites (yspr#t —-)
| ultrafonmnes Formg Anhang B nite 75
ASSENBLER
NODULA
FB PASCAL FORTH79
PLi
C
FORTRAN FIG-FORTH
data b. FORTH
ALGOL
basıc
Seite 16 Ende ultraFORTHBZ
1c) 1955 bp/ks/re/we FORTH-Gesellschafl