../../images/zoom.gif

../../images/exit.gifATOM FORTH
Zie ook de originele Engelse handleiding van AcornSoft.

/atom_handleidingen/forth/forth01th.gif

1. Wat is FORTH?

PORTH is een programmeertaal die ongeveer 13 jaar geleden door C.H.Moore is uitgevonden. De taal is zeer geschikt voor het besturen van apparatuur m.b.v. een computer. De meeste hogere programmeertalen zijn daarvoor te traag en het schrijven van machinetaal routines is lastig.

Enkele eigenschappen van FORTH zijn: 
-	FORTH programma's hebben een hoge executie-snelheid. 
-	FORTH heeft weinig geheugenruimte nodig. 
-	FORTH is uitbreidbaar. -FORTH is interactief. 
-	FORTH is een gestructureerde taal. 
Op al deze eigenschappen komen we nog terug. 

2. 	De STACK. 

../../images/terug.gif
Voor de berekeningen gebruikt FORTH een STACK (de parameter-STACK). Dit betekent
- 	Alle getallen die worden ingetypt, komen boven op de STACK. 
- 	Alle operaties halen getallen van de STACK en zetten het resultaat van de bewerking weer
	op de STACK. 
	
We zullen een voorbeeld bekijken. 
We tikken in: 2 4 6 3 
De getallen 2,4,6,3 staan nu op de STACK, de 3 bovenop en de 2 onderop. 
Vervolgens tikken we: 		+ 
Nu worden de 6 en de 3 van de STACK gehaald en de som (6+3=) 9 weer op de STACK gezet.
Deze bevat nu dus de getallen 2,4,9. 
Typen we nu: 		MAX 
dan worden de 4 en de 9 van de STACK gehaald en hun maximum (=9) wordt teruggezet. 
De STACK bevat nu de getallen 2t9. 
We typen nu: 		- 
De getallen 2 en 9 worden van de STACK gehaald en hun verschil (2-9=) -7 
wordt weer teruggezet. 
Als we nu intypen: 		. 
dan wordt het bovenste element (-7) van de STACK gehaald en afgedrukt. 
De STACK is nu leeg. 
Kortom: het uitrekenen en afdrukken van 2-MAX(4t6+3) gaat in FORTH 
met: 246 3 + MAX -.(Ret.) 
Op het beeldscherm zal dan te zien zijn: 246 3 + MAX -.-7 OK 
Als de opdracht op de juiste manier is uitgevoerd reageert FORTH altijd met "OK". 
Van dit voorbeeld kunnen we verschillende dingen leren: 
-	De STACK werkt volgens het "Last-in first-out" principe. 
	Dit betekent dat het getal, dat het laatst op de STACK is gezet t er als eerste 
	weer wordt afgehaald. We kunnen dit vergelijken met een stapel borden! ! 
-	De spatie is in PORTH een scheidingsteken. 
	De verschillende getallen worden alleen door een spatie gescheiden. 
-	ACORN-FORTH werkt alleen met integer getallen. 
Er bestaan FORTH-versies die ook met "floating-point" getallen kunnen werken.
ACORN-FORTH kent zowel enkele- als dubbele-precisie integers. 
Op het verschil komen we terug: voorlopig beperken wij ons tot de enkele precisie getallen. 
Dit zijn 16-BIj getallen, zodat de waarde die ze kunnen aannemen ligt tussen -32768 en 327E
(ofwel tussen 0 en 65535. indien we ze beschouwen als getallen zonder teken)

-	FORTH is op de manier zoals we hebben voorgedaan te gebruiken alsof het een
	rekenmachine is. PORTH gebruikt een post-fix  notatie, die de gebruikers var H.P.
	rekenmachines bekend zal voorkomen. 
	
We zullen een aantal STACK-operaties op een rijtje zetten: 
+	Berekent de som van de bovenste twee elementen. 
-	Berekent het verschil van de bovenste twee elementen. 
*	Berekent het product van de bovenste twee e1ementen. 
/	Berekent het quotiënt van de bovenste twee elementen. 
MOD	Berekent de rest van de deling van de bovenste twee elementen. 
MAX	Neemt de grootste van de bovenste twee elementen. 
MIN 	Neemt de kleinste van de bovenste twee elementen. 
ABS	Berekent de absolute waarde van het bovenste getal. 
MINUS 	Draait het teken van het bovenste element om. 
1+ 	Telt 1 op bij het bovenste element. 
2+ 	Telt 2 op bij het bovenste element. 
2* 	Vermenigvuldigt het bovenste element met 2. Dit is sneller dan: 2 * 

Dit waren enkele rekenkundige bewerkingen, maar er zijn ook andere bewerkingen op de STACK mogelijk: 
DUP 	Dupliceert het bovenste element. 1 2 DUP geeft: 122 
DROP 	Verwijdert het bovenste element. 1 Z J DROP geeft: 12 
SWAP 	Verwisselt de bovenste twee elementen. 12 SWAP geeft: 2 1 
OVER 	Kopieert het 2e element van de STACK bovenop de STACK. 64 J 2 OVER geeft: ó 4 J 2 J 
ROT 	Verwijdert het 3e element en plaatst het boven op de STACK. 45678 ROT geeft: 457 ~ 6 
I PICK 	Kopieert het I-de element van de STACK naar de top van de STACK. 
	1 2 J 4564 FICK geeft: 1234563 
I ROLL 	Verwijdert het I-de element en plaatst het boven op de STACK. 
	1 234 564 ROLL geeft: 124 563 

We zien nu dat: 
1 PICK is equivalent aan DUF 
2 PICK is equivalent aan OVER 
2 ROLL is equivalent aan SWAP 
3 ROLL is equivalent aan ROT 

FORTH kent ook logische operatoren: 
AND 	Berekent de BIT-voor-BIT logische AND van de twee bovenste elementen 
	1521 AND geeft: 5 
OR 	Berekent de BIT-voor-BIT logische OR van de twee bovenste elementen 
	1521 ~ geeft: 31 
XOR 	Berekent de BIT-voor-BIT logische Exclusieve-OR van de bovenste twee elementen.
	1521 XOR geeft: 26 

../../images/terug.gif
3. 	INPUT en OUTPUT in PORTH. 

PORTH kent de volgende INPUT/OUTPUT routines: 
.	Haalt het bovenste getal van de STACK en drukt het af. 
EMIT	Haalt het bovenste getal van de S1'ACK en drukt het af als ASCII character. 
	64 DUF EMIT .geeft: @ 64 OK 
KEY	Leest een character in van het toetsenbord en zet het als getal op de STACK. 
." 	Drukt een tekst af. De tekst moet worden afgesloten met "." HALLO" 
	geeft: HALLO 
CR 	Spring naar het begin van de volgende regel. 

Inwendig rekent ACORN-FORTH altijd BINAIR. De INPUT en OUTPUT kan echter 
geschieden in elk gewenst talstelsel. Standaard zijn aanwezig de "decimale" en de
 "Hexadecimale" basis. Omschakelen gebeurt via d,J commando' s: "HEX en "DECIMAL" . 
Hoe je kan overgaan op een ander talstelsel wordt nog behandeld.
 
../../images/terug.gif
4. 	Het programmeren in FORTH. 

Programmeren in FORTH is eigenlijk.niets anders dan het toevoegen aan de
standaard-FORTH functies van je eigen functies. Als je vindt dat een functie ontbreekt, 
dan maak je hem gewoon zelf. Deze zelfgemaakte functies zijn dan op dezelfde manier te
gebruiken als de standaard-FORTH functies. 
We demonstreren dit weer aan de hand van een voorbeeld. We typen in: : XA2 DUP .; 
Wat hebben we nu eigenlijk gedaan: 
: 	Geeft aan dat we een nieuwe functie gaan definiëren. 
X^2 	Dit is de naam van onze nieuwe operator. Deze wordt altijd meteen 
	na de: gezet. 
DUP* 	Dit is wat de nieuwe operator moet doen. In dit geval moet dus het kwadraat 
	van het bovenste getal op de STACK worden berekend. 
; 	Hiermee wordt de definitie afgesloten. 

Typen we nu vervolgens: 		5 X^2 . 
Dan zal de computer antwoorden met: 	25 OK 

We zien dat de nieuwe functie op dezelfde manier gebruikt wordt als de 
standaard-FORTH functies. Hij kan dus ook in alle daarna volgende definities 
gebruikt worden. Bijvoorbeeld: 
: X^4 X^2 X^2 ; 
3 X^4 .				geeft nu: 81 OK 

In ACORN-FORTH mag een naam van een functie maximaal 31 karakters lang zijn. 
Een naam kan nooit spaties bevatten. 
Een FORTH programma bestaat uit een rij zelfgemaakte functies, die steeds verder
gecombineerd worden. Het gehele FORTH programma wordt uiteindelijk gerepresenteerd 
door een enkel woord. 
Om een programma in FORTH te schrijven, moet de taak van het programma in steeds
kleinere taakjes worden verdeeld. Uiteindelijk blijven dan zeer kleine taken over, die makkelijk
in FORTH kunnen worden geschreven. Deze worden dan gecombineerd tot een heel
computerprogramma. 
Wij zullen hiervan nog voorbeelden te zien krijgen. 

We zullen nog een operatie definiëren. 

: - 3 * ; 

We hebben nu de operatie "-" gedefinieerd als "vermenigvuldig met J". 
We zien dus dat verschillende functies dezelfde naam mogen hebben. 
Alleen de laatste definitie van een functie kunnen we nu gebruiken, dus: 
Als we intypen:			5 3 - . 
dan zal de computer reageren met: 	9 OK 

We kunnen nu dus niet meer twee getallen van elkaar aftrekken. 
Daarom is er een functie in FORTH, die zorgt dat we deze definitie 
ongedaan kunnen maken: 
FORGET X^4 	FORTH is nu "X^4" en alle latere definities vergeten. 
		De standaard-FORTH functies zijn beschermd: FORGET DROP
		levert een foutmelding op. 

Als we willen weten welke definities we ter beschikking hebben dan kunnen 
we gebruik maken van: 
VLIST 		We krijgen dan een lijst van alle zelfgemaakte en alle 
		standaard-FORTH definities. 
 
../../images/terug.gif
5. 	Variabelen in FORTH. 

Het is in FORTH ook mogelijk om variabelen te gebruiken. 
Ze worden op de volgende manier gedefinieerd:

44    VARIABELEN HOEVEEL 

De variabelen met de naam "HOEVEEL" hebben we nu gedefinieerd en we hebben 
hem om te beginnen de waarde 44 gegeven. Als we de waarde van "HOEVEEL" willen
gebruiken in een berekening, dan moet deze waarde eerst op de STACK worden gezet.
HOEVEEL @ 
Op de top van de STACK staat nu de waarde van "HOEVEEL" (=44). 
Het veranderen van de waarde van een variabele gaat op de volgende manier: 
HOEVEEL ! 
Het bovenste getal is nu van de STACK gehaald en aan de variabele "HOEVEEL" toegekend.
We kennen nog een bewerking voor variabelen: 
1 HOEVEEL +! 
De waarde van "HOEVEEL" is nu met 1 opgehoogd. 

../../images/terug.gif
6.	De "DO-LOOP" in FORTH. 

We zullen een voorbeeld laten zien: 
: TELLER 6 1 DO I. LOOP ;
Wat is er gebeurd? 
: 	Dit geeft aan dat we een nieuwe functie definiëren. 
TELLER	Dit is de naam van de nieuwe functie. 
6 1 	De getallen 6 en 1 worden op de STACK gezet. 
DO 	Dit is het begin van onze "DO-LOOP". De getallen 6 en 1 worden van de STACK gehaald. 
De LOOP-index krijgt om te beginnen de waarde van het bovenste getal (=1). 
Zodra de LOOP-index de waarde van het tweede getal (=6) bereikt, wordt er gestopt. 
I	De waarde van de LOOP-index wordt op de STACK gezet. 
.	Het bovenste getal wordt van de STACK gehaald en afgedrukt. 
In dit geval is dat dus steeds de LOOP-index. 
LOOP 	Dit markeert het einde van de "DO-LOOP". 
De index wordt met 1 verhoogd en we gaan terug naar “DO". 
; 	Einde van deze definitie. 

Typen we nu in: 			TELLER
dan zal de computer reageren met: 	12 34 5 OK 
We moeten op de volgende dingen letten: 
-	Een DO-LOOP kan alleen binnen een definitie gebruikt worden. 
-	DO haalt twee waarden van de STACK. Hoe deze waarden daar gekomen zijn doet er niet toe. 
Ze mogen dus ook buiten de definitie, waarin de DO-LOOP voorkomt, op de STACK worden gezet. 
-	DO-LOOP's mogen genest worden. De functie "I. zet altijd de waarde van de index van de 
binnenste DO-LOOP op de STACK. 

Nog een paar voorbeeldjes: 
: TAFEL 11 1 DO DUP I * . LOOP ; 
3 TAFEL geeft: 3 6 9 12 1518 21 24 27 30 OK 
: WACHT 0 DO LOOP ; 
8 WACHT geeft een korte pauze. 
3000 WACHT geeft een lange pauze. 

../../images/terug.gif
7. 	De IF-ELSE-THEN constructie. 

Ook de IF-ELSE-THEN constructie kan alleen binnen een definitie voorkomen. 
We bekijken een voorbeeld: 
: GELIJK? = IF ." GELIJK" ELSE ." ONGELIJK " THEN ;
Wat is er gebeurd? 
: GELIJK? 	Dit is de naam van de definitie. 
= 		De twee bovenste getallen van de STACK worden gehaald. 
Als ze gelijk zijn, dan wordt er een getal op de STACK gezet dat de logische waarde 
"WAAR" representeert, en als ze ongelijk zijn, dan wordt er een getal op de STACK 
gezet met de logische waarde "NIET-WAAR". 
IF 		Er wordt getest of op de STACK de logische waarde "WAAR" staat. 
Als dit zo is dan worden de operaties tussen "IF" en "ELSE" uitgevoerd. 
Staat op de STACK de logische waarde "NIET-'NAAR", dan worden de operaties 
tussen "ELSE" en "THEN" uitgevoerd. 
." GELIJK " 	Druk af "GELIJK". 
ELSE 		Onderdeel van IF-THEN-ELSE constructie. ." ONGELIJK" Druk af "ONGELIJK". 
THEN 		Afsluiting van de IF-ELSE-THEN constructie. 
Na het uitvoeren van de operaties tussen "IF" en "ELSE" of tussen “ELSE" en "THEN", 
gaat het programma verder met de operaties na "THEN". 
; 		Afsluiting van de definitie. 
3 5 GELIJK? 	geeft: 	ONGELIJK OK 
7 7 GELIJK? 	geeft: 	GELIJK OK 

Binnen FORTH wordt de logische waarde "NIET-WAAR" gerepresenteerd door het getal 0. 
Ieder getal ongelijk aan nul representeert" de logische waarde "WAAR”. 
De relationele operaties in FORTH, waartoe ook de operatie "=" 
behoort, zetten op de STACK het getal 1 als de uitkomst moet zijn "WAAR". 
Dus:		7 3 = .	geeft: 0 OK 
5 5 = .	geeft: 1 OK 

FORTH kent de volgende relationele operaties: 
0= 	Zet een 1 op de STACK als het bovenste getal gelijk is aan 0. 
Is het bovenste getal niet gelijk aan 0. dan komt er een 0 op de STACK. 
0< 	Zet een 1 op de STACK als het bovenste getal negatief is. 
Is het bovenste getal niet-negatief dan komt er een 0 op de STACK. 
= 	Zet een 1 op de STACK als de twee bovenste getallen gelijk zijn. 
Zijn de twee getallen ongelijk dan komt er een 0 op de STACK. 
<	Zet een 1 op de STACK als het bovenste getal kleiner is dan het tweede 
getal op de STACK. In alle andere gevallen komt er een 0 op de STA.CK. 
> 	Zet een 1 op de STACK als het bovenste getal groter is dan het 
tweede getal op de STACK. In alle andere gevallen komt er een 0 op de STACK. 

5 5 <.. 		geeft: 0 OK
0 0 = .		geeft: 1 OK 
8 0 < .		geeft: 0 OK 
-153 0< .	geeft: 1 OK 

../../images/terug.gif
8. 	BEGIN-UNTIL 

We bekijken een voorbeeld. 
: DRUK-AF-TOT-0 BEGIN DUP. O= UNTIL ; 

Verklaring: 
: DRUK-AF-TOT-0	Is het begin van de definitie. 
BEGIN 			Dit is het begin van de BEGIN-UNTIL constructie. 
DUP. 			Druk het bovenste getal van de STACK af. 
0= 			Kijk of dit getal gelijk is aan 0. 
UNTIL 			Ga door totdat de voorgaande test het antwoord "WAAR" oplevert. 
Als de voorgaande test "NIET-WAAR" oplevert ga dan terug naar "BEGIN".  
;			Einde van de definitie. 

1 2 3 0 4 7 3 1 DRUK-AF-TOT-0 geeft: 1 3 7 4 0 OK 
Als illustratie kan het volgende voorbeeld dienen. 
Het berekent de grootste gemene deler van twee getallen. 

: COPY OVER OVER ; 
: G-G-D BEGIN COPY -ABS ROT ROT MIN DUP 0= UNTIL DROP ; 
: GGD CR ." DE G.G.D. VAN " COPY .. ” EN " .." IS " G-G-D .; 
9 15 GGD 		geeft: DE G.G.D. VAN 15 EN 9 IS 3 OK 
221 119 GGD 		geeft: DE G.G.D. VAN 119 EN 221 IS 17 OK 

De berekening van het kleinste gemene veelvoud gaat als volgt: 
: KGV COPY * ROT ROT G-G-D / ; 
8 12 KGV .		geeft: 24 OK 

../../images/terug.gif
9. 	BEGIN-WHILE-REPEAT. 

Ook nu beginnen we met een voorbeeld. 
: DELETEO BEGIN DUP 0= WHILE DROP REPEAT ; 
Verklaring: 
: 		Begin van de definitie. 
DELETEO 	Naam van deze functie. 
BEGIN 		Dit is het begin van de BEGIN-WHILE-REPEAT constructie. 
DUP O= 	We testen of het bovenste getal op de S~CK gelijk is aan 0. 
WHILE 		Als de voorgaande test als resultaat "WAAR" heeft, dan wordt verder gegaan 
met de volgende operatie. Was het resultaat "ONWAAR" ; 
dan springen we naar de operatie die staat achter "REPEAT" . 
DROP 		Als het bovenste getal gelijk is aan 0, verwijder het dan. 
REPEAT 	Spring terug naar “BEGIN”
; 		Einde van de definitie. 

Met deze operatie kunnen we alle nullen boven op de STACK verwijderen. 
1 2 3 0 0 9 0 0 0 DELETEO …… 	 geeft: 9 0 0 3 2 OK 
We kunnen nu een voorbeeld programmaatje laten zien. Het is een spelletje. 
De speler moet een getal tussen 1 en 1023 in gedachten nemen. 
De computer zal proberen het getal te raden. 
: MIDDEL OVER OVER + 2 / ; 
: VRAAG1 CR ." IS HET  " MIDDEL. ." ? " KEY DUP EMIT ;
: VRAAG2 CR .” GROTER OF KLEINER? " KEY DUP EMIT ; : 
RADEN 0  1024 
BEGIN VRAAG1 78 = 		ASCII waarde "N" 
WHILE VRAAG2 71 =		ASCII waarde "G" 
IF MIDDEL ROT DROP SWAP 
ELSE MIDDEL SWAP DROP 
THEN 
REPEAT DROP DROP CR ." GEVONDEN " CR ; 
Het spel zou als volgt kunnen verlopen: 
RADEN 
IS HET 512? N 
GROTER OF KLEINER? K
IS HET 256? J 
GEVONDEN OK 
../../images/terug.gif