papierkorb:4th_lesson_9
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| papierkorb:4th_lesson_9 [2025-08-16 19:10] – ↷ Seite von projects:4th_lesson_9 nach papierkorb:4th_lesson_9 verschoben mka | papierkorb:4th_lesson_9 [Unbekanntes Datum] (aktuell) – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | === Lesson 9 === | ||
| - | < | ||
| - | \ | ||
| - | \ The Forth Course | ||
| - | \ by Richard E. Haskell | ||
| - | \ Dept. of Computer Science and Engineering | ||
| - | \ Oakland University, Rochester, MI 48309 | ||
| - | |||
| - | comment: | ||
| - | |||
| - | |||
| - | |||
| - | Lesson 9 | ||
| - | |||
| - | | ||
| - | |||
| - | |||
| - | 9.1 COMPILING VS. INTERPRETING | ||
| - | |||
| - | 9.2 COMPILE AND [COMPILE] | ||
| - | |||
| - | 9.3 LITERALS | ||
| - | |||
| - | 9.4 CONDITIONAL COMPILER WORDS 9-8 | ||
| - | |||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | | ||
| - | |||
| - | 9.5 EXERCISES | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | 9.1 COMPILING VS. INTERPRETING | ||
| - | |||
| - | Compiler words are IMMEDIATE words. | ||
| - | executed immediately when they are encountered in a colon | ||
| - | definition rather than being compiled into the list segment. | ||
| - | Immediate words have the precedence bit in the name field set | ||
| - | (see Lesson 3, Section 3.12). | ||
| - | |||
| - | F-PC can be in one of two possible states: compiling or interpreting. | ||
| - | It is in the compiling state during the compilation of a colon | ||
| - | definition. | ||
| - | executed and the word " | ||
| - | The system variable STATE contains the following possible two values: | ||
| - | |||
| - | TRUE -- if compiling | ||
| - | FALSE -- if interpreting | ||
| - | |||
| - | To test what state exists at different times, consider the following | ||
| - | two definitions: | ||
| - | comment; | ||
| - | |||
| - | : 1state? | ||
| - | STATE @ | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | | ||
| - | THEN | ||
| - | CR ; | ||
| - | |||
| - | : 1test ( -- ) | ||
| - | 1state? ; | ||
| - | |||
| - | comment: | ||
| - | After FLOADing lesson9 type | ||
| - | |||
| - | 1state? | ||
| - | and | ||
| - | 1test | ||
| - | |||
| - | Note that " | ||
| - | |||
| - | It is because you are in the interpreting mode when you type both | ||
| - | 1state? and 1test. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | How can you get " | ||
| - | It is necessary to have 1state? execute during the time that | ||
| - | 1test is being compiled. | ||
| - | immediate word. We do this by adding the word IMMEDIATE to the | ||
| - | definition following the semi-colon. | ||
| - | 2state? and define | ||
| - | comment; | ||
| - | |||
| - | : 2state? | ||
| - | STATE @ | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | | ||
| - | THEN | ||
| - | CR ; IMMEDIATE | ||
| - | |||
| - | comment: | ||
| - | Now type in the following colon definition: | ||
| - | |||
| - | : 2test | ||
| - | |||
| - | Note that when you type this definition, the word " | ||
| - | is printed as soon as you press < | ||
| - | 2state? is executed immediately and does not wait for you to | ||
| - | later type 2test. | ||
| - | |||
| - | 2test | ||
| - | |||
| - | Note that nothing is printed on the screen. | ||
| - | 2state? was not compiled in the dictionary. | ||
| - | immediately. | ||
| - | unless forced to do so. You can force an immediate word to be | ||
| - | compiled, rather than be executed immediately, | ||
| - | word by [COMPILE]. | ||
| - | the word 2state? is compiled and not executed immediately. | ||
| - | comment; | ||
| - | |||
| - | : 3test ( -- ) | ||
| - | [COMPILE] 2state? ; | ||
| - | |||
| - | comment: | ||
| - | What do you think will be printed when you type 3test? | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | It is also possible to turn the compiler off and on within a colon | ||
| - | definition by using the two words [ and ]. | ||
| - | The word [ is an immediate word that turns the compiling state off; | ||
| - | that is, it returns to the interpreting mode. The definition of [ is | ||
| - | |||
| - | : [ ( -- ) | ||
| - | STATE OFF ; IMMEDIATE | ||
| - | |||
| - | The word ] turns the compile mode on and then enters the compiling | ||
| - | loop. The compiling loop consists of the following: | ||
| - | |||
| - | DO Get next word in input stream; | ||
| - | If it is an immediate word, execute it | ||
| - | Else compile it; | ||
| - | If the word is not in the dictionary, | ||
| - | convert it to a number and compile it; | ||
| - | UNTIL end of input stream. | ||
| - | |||
| - | An a final example, type in the following example: | ||
| - | |||
| - | : 4test [ 1state? ] ; | ||
| - | |||
| - | Note that when you press < | ||
| - | Why? | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | 9.2 COMPILE AND [COMPILE] | ||
| - | |||
| - | We have seen that [COMPILE] will compile the following immediate | ||
| - | word into the list segment. | ||
| - | |||
| - | : [COMPILE] | ||
| - | ' X, ; IMMEDIATE | ||
| - | |||
| - | The word " | ||
| - | on the stack and the word X, compiles the integer on the stack | ||
| - | into the next available location in the list dictionary. | ||
| - | [COMPILE] itself is an immediate word so that it is executed at | ||
| - | compile time of the word that contains it. | ||
| - | |||
| - | Sometimes you want to compile a word at run time. The word COMPILE | ||
| - | will do this. For example, the definition of " | ||
| - | basically the following. | ||
| - | |||
| - | : ; ( -- ) | ||
| - | COMPILE UNNEST | ||
| - | REVEAL | ||
| - | [COMPILE] [ \ go to interpreting mode | ||
| - | ; IMMEDIATE | ||
| - | |||
| - | Note that ; is an immediate word so that it will be executed when | ||
| - | it is encountered in a colon definition. | ||
| - | of the UNNEST routine in the list dictionary of the colon word. | ||
| - | After making the colon word available to dictionary searches by the | ||
| - | word REVEAL it switches to the interpreting mode by executing [ | ||
| - | which had been compiled in the definition of ; (even though [ is | ||
| - | an immediate word) by [COMPILE]. | ||
| - | |||
| - | The definition of [COMPILE], which will compile the CFA of the | ||
| - | following non-immediate word when the word containing COMPILE | ||
| - | executes, is the following | ||
| - | |||
| - | : COMPILE | ||
| - | 2R@ SWAP \ get ES:SI of next CFA in list seg | ||
| - | R> 2+ >R \ inc SI past next word in list seg | ||
| - | @L \ get CFA on next word in list seg | ||
| - | ,X ; \ & compile it at run time | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | 9.3 LITERALS | ||
| - | |||
| - | | ||
| - | comment; | ||
| - | |||
| - | : four+ ( n -- n+4 ) | ||
| - | 4 + ; | ||
| - | comment: | ||
| - | This will be compiled into the dictionary as follows: | ||
| - | |||
| - | four+ | ||
| - | ________ | ||
| - | CFA | CODE | <------| | ||
| - | |------| | ||
| - | PFA | LSO | -------- +XSEG -------> | ||
| - | |------| | ||
| - | Code Segment ?CS: | ||
| - | |-------| | ||
| - | | | ||
| - | |-------| | ||
| - | |UNNEST | | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | The word (LIT) is a code word defined as follows: | ||
| - | |||
| - | CODE (LIT) ( -- n ) | ||
| - | LODSW ES: \ get next word at ES:SI, SI=SI+2 | ||
| - | 1PUSH \ push it on stack | ||
| - | END-CODE | ||
| - | |||
| - | Thus the word (LIT) will push the number 4 on the stack and the | ||
| - | instruction pointer ES:SI will then be pointing to the CFA of +. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | If you have a number on the stack and you want to compile it as | ||
| - | a literal in the list dictionary you can use the word LITERAL. | ||
| - | This word is defined as follows: | ||
| - | |||
| - | : LITERAL | ||
| - | COMPILE (LIT) \ compile (LIT) | ||
| - | X, \ plus the value n | ||
| - | ; IMMEDIATE | ||
| - | |||
| - | A useful application of the word LITERAL is when you compute | ||
| - | some constant value in a definition. | ||
| - | the value 5 is computed as 2 + 3 (perhaps for clarity in some | ||
| - | definition). | ||
| - | comment; | ||
| - | |||
| - | : five+ ( n -- n+5 ) | ||
| - | [ 3 2 + ] LITERAL + ; | ||
| - | |||
| - | comment: | ||
| - | Although this produces the same answer as | ||
| - | |||
| - | : five+ 3 2 + + ; | ||
| - | |||
| - | the advantange is that [ 3 2 + ] LITERAL will compile the literal | ||
| - | 5 in the list dictionary at compile time so that at run time only | ||
| - | 5 + is executed. | ||
| - | literal 3 and a literal 2 in the list dictionary and will execute | ||
| - | two plus operations at run time. Therefore, the use of | ||
| - | [ 3 2 + ] LITERAL produces more efficient code that executes faster. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | 9.4 CONDITIONAL COMPILER WORDS | ||
| - | |||
| - | The two conditional compiler words BRANCH and ?BRANCH are used | ||
| - | to define the various conditional branching instructions in F-PC. | ||
| - | The word BRANCH is a code word that is defined as follows: | ||
| - | |||
| - | |-------| | ||
| - | CODE BRANCH | ||
| - | LABEL BRAN1 | ||
| - | MOV ES: SI, 0[SI] |----| addr | IP = ES:SI | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | | ||
| - | | ||
| - | | ||
| - | | ||
| - | |-------| | ||
| - | | | | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | BRANCH is compiled into the list dictionary followed by the | ||
| - | offset address that is to be unconditionally branched to. | ||
| - | |||
| - | The word ?BRANCH will cause a branch to the address following | ||
| - | ?BRANCH if the flag on top of the stack is FALSE. | ||
| - | as follows: | ||
| - | |||
| - | |-------| | ||
| - | CODE ? | ||
| - | POP AX |-------| | ||
| - | OR AX, AX | ||
| - | JE BRAN1 | |-------| | ||
| - | ADD SI, # 2 | | | | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | | ||
| - | | ||
| - | |-------| | ||
| - | | | | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | BEGIN...WHILE...REPEAT | ||
| - | |||
| - | As an example of a BEGIN...WHILE...REPEAT loop recall the | ||
| - | definition of the word " | ||
| - | : factorial | ||
| - | 1 2 ROT \ x i n | ||
| - | BEGIN \ x i n | ||
| - | 2DUP <= \ x i n f | ||
| - | WHILE \ x i n | ||
| - | -ROT TUCK \ n i x i | ||
| - | * SWAP \ n x i | ||
| - | 1+ ROT \ x i n | ||
| - | REPEAT | ||
| - | 2DROP ; \ x | ||
| - | This definition will be stored in the list dictionary as follows: | ||
| - | _________ | ||
| - | | (LIT) | | ||
| - | |-------| | ||
| - | | | ||
| - | |-------| | ||
| - | | (LIT) | | ||
| - | |-------| | ||
| - | | | ||
| - | | ||
| - | | ROT | | ||
| - | |-------| | ||
| - | xhere1 ---> | ||
| - | |-------| | ||
| - | | <= | | ||
| - | |-------| | ||
| - | |?BRANCH| <--- : WHILE COMPILE ?BRANCH | ||
| - | xhere1 | ||
| - | xhere2 ---> | ||
| - | |-------| | ||
| - | | -ROT | | | ||
| - | |-------| | ||
| - | | TUCK | | xhere3 | ||
| - | |-------| | ||
| - | | | ||
| - | |-------| | ||
| - | | SWAP | | | ||
| - | |-------| | ||
| - | | 1+ | ||
| - | |-------| | ||
| - | | ROT | | | ||
| - | |-------| | ||
| - | | BRANCH| | ||
| - | |-------| | ||
| - | | xhere1| | ||
| - | |-------| | ||
| - | xhere3 ---> | ||
| - | seg | ||
| - | xhere2 | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | The word BEGIN leaves the offset address xhere1 on the stack. | ||
| - | The word WHILE compiles ?BRANCH followed by a 0 at xhere2. | ||
| - | This value of 0 will later be replaced with the address xhere3 | ||
| - | of the word 2DROP. | ||
| - | stack under xhere1. | ||
| - | The word REPEAT compiles BRANCH and then commas in the address | ||
| - | xhere1. | ||
| - | stores it at address seg:xhere2. | ||
| - | |||
| - | IF...ELSE...THEN | ||
| - | |||
| - | Consider the following colon definition: | ||
| - | |||
| - | : test ( f -- f ) | ||
| - | IF | ||
| - | TRUE | ||
| - | ELSE | ||
| - | FALSE | ||
| - | THEN ; | ||
| - | |||
| - | This will be stored in the list dictionary as follows: | ||
| - | |||
| - | _________ | ||
| - | |?BRANCH| <--- : IF | ||
| - | |-------| | ||
| - | xhere1 ---> | ||
| - | |-------| | ||
| - | | TRUE | | ||
| - | |-------| | ||
| - | | BRANCH| | ||
| - | |-------| | ||
| - | xhere2 ---> | ||
| - | |-------| | ||
| - | xhere3 ---> | ||
| - | |-------| | ||
| - | xhere4 ---> | ||
| - | |-------| | ||
| - | ; IMMEDIATE | ||
| - | List Segment XSEG | ||
| - | |||
| - | The word IF compiles ?BRANCH followed by a 0 at xhere1. | ||
| - | This value of 0 will later be replaced with the address xhere3 | ||
| - | of the word FALSE. | ||
| - | stack. | ||
| - | |||
| - | The word ELSE compiles BRANCH followed by a 0 at xhere2. | ||
| - | This value of 0 will later be replaced with the address xhere4 | ||
| - | of the word UNNEST. | ||
| - | stack after putting the address xhere3 on the stack and then | ||
| - | storing it at address seg:xhere1. | ||
| - | |||
| - | The word THEN puts the address xhere4 on the stack and then | ||
| - | stores it at address seg:xhere2. | ||
| - | |||
| - | BEGIN...AGAIN | ||
| - | |||
| - | An example of a using BEGIN...AGAIN was given in the pop-up menu | ||
| - | examples in Lesson 8. The typical form was | ||
| - | |||
| - | : main ( -- ) | ||
| - | minit | ||
| - | BEGIN | ||
| - | KEY do.key | ||
| - | AGAIN ; | ||
| - | |||
| - | This will be stored in the list dictionary as follows: | ||
| - | |||
| - | _________ | ||
| - | | minit | | ||
| - | |-------| | ||
| - | xhere1 ---> | ||
| - | |-------| | ||
| - | | do.key| | ||
| - | |-------| | ||
| - | | BRANCH| <--- : AGAIN | ||
| - | |-------| | ||
| - | | xhere1| | ||
| - | |-------| | ||
| - | |UNNEST | | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | The word BEGIN leaves the offset address xhere1 on the stack. | ||
| - | The word AGAIN compiles BRANCH and then commas in the address | ||
| - | xhere1. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | BEGIN...UNTIL | ||
| - | |||
| - | The following example of a using BEGIN...UNTIL was given in | ||
| - | Lesson 4. | ||
| - | |||
| - | : dowrite | ||
| - | BEGIN | ||
| - | KEY | ||
| - | DUP EMIT | ||
| - | 13 = | ||
| - | UNTIL ; | ||
| - | |||
| - | This will be stored in the list dictionary as follows: | ||
| - | |||
| - | _________ | ||
| - | xhere1 ---> | ||
| - | |-------| | ||
| - | | DUP | | ||
| - | |-------| | ||
| - | | EMIT | | ||
| - | |-------| | ||
| - | | (LIT) | | ||
| - | |-------| | ||
| - | | 13 | | ||
| - | |-------| | ||
| - | | | ||
| - | |-------| | ||
| - | |?BRANCH| <--- : UNTIL | ||
| - | |-------| | ||
| - | | xhere1| | ||
| - | |-------| | ||
| - | |UNNEST | | ||
| - | |-------| | ||
| - | List Segment XSEG | ||
| - | |||
| - | The word BEGIN leaves the offset address xhere1 on the stack. | ||
| - | The word UNTIL compiles ?BRANCH and then commas in the address | ||
| - | xhere1. | ||
| - | BEGIN...UNTIL is that in UNTIL ?BRANCH replaces the BRANCH in | ||
| - | AGAIN. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | DO...LOOP | ||
| - | |||
| - | A DO loop will produce the following structure in the list | ||
| - | dictionary: | ||
| - | |||
| - | __________ | ||
| - | | (DO) | <--- : DO | ||
| - | |--------| | ||
| - | xhere1 ---> | | ||
| - | |--------| | ||
| - | xhere1 + 2 ---> | |<--| |xhere2 | ||
| - | |--------| | ||
| - | | | | | | ||
| - | |--------| | ||
| - | | | | | | ||
| - | |--------| | ||
| - | | (LOOP) | | | <--- : LOOP COMPILE (LOOP) | ||
| - | |--------| | ||
| - | |xhere1+2|---| | XHERE | ||
| - | |--------| | ||
| - | xhere2 ---> | | ; IMMEDIATE | ||
| - | |--------| | ||
| - | |||
| - | List Segment XSEG | ||
| - | |||
| - | The word DO compiles (DO) followed by a 0 at xhere1. | ||
| - | This value of 0 will later be replaced with the address xhere2 | ||
| - | of the first word following the DO loop. DO also leaves the | ||
| - | value of xhere1 on the stack. | ||
| - | |||
| - | The word LOOP compiles (LOOP) and then commas in the address | ||
| - | xhere1+2. | ||
| - | then stores it at address seg:xhere1. | ||
| - | |||
| - | The run-time word | ||
| - | (DO) ( limit index -- ) | ||
| - | sets up the return stack as follows: | ||
| - | |||
| - | Return Stack | ||
| - | | ||
| - | | index - (limit + 8000H) | | ||
| - | | ||
| - | | ||
| - | | ||
| - | | ||
| - | | ||
| - | |||
| - | The run-time word (LOOP) adds 1 to the top of the return stack | ||
| - | and jumps to xhere1+2 if the overflow flag is not set. If the | ||
| - | overflow flag is set (i.e. the top of the stack crosses the | ||
| - | 8000H boundary when index = limit) (LOOP) pops the three items | ||
| - | from the return stack and moves the instruction pointer ES:SI | ||
| - | to xhere2. | ||
| - | |||
| - | |||
| - | |||
| - | Having the value of xhere2 as the third item on the return stack | ||
| - | is used by LEAVE to find the address to leave to. Adding the | ||
| - | value of 8000H to the top two values on the return stack when | ||
| - | executing (DO) allows the DO loop to work properly when the limit | ||
| - | is larger than 8000H. | ||
| - | and the initial index were 0. The initial value on top of the | ||
| - | return stack would be -7FFFH. | ||
| - | overflow flag will not be set until the top of the stack becomes | ||
| - | equal to 8000H, that is, after FFFFH loops. | ||
| - | |||
| - | |||
| - | 9.5 EXERCISES | ||
| - | |||
| - | | ||
| - | structure of the following three test words: | ||
| - | comment; | ||
| - | |||
| - | : a.test | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | | ||
| - | THEN ; | ||
| - | |||
| - | : b.test | ||
| - | 5 0 DO | ||
| - | I . | ||
| - | LOOP ; | ||
| - | |||
| - | : c.test | ||
| - | 4 | ||
| - | BEGIN | ||
| - | DUP . | ||
| - | 1- DUP 0= | ||
| - | UNTIL | ||
| - | DROP ; | ||
| - | |||
| - | comment: | ||
| - | For each word draw the dictionary structure indicating the names | ||
| - | and actual values of all entries in the list dictionary. | ||
| - | on these drawings the effects of the words IF, ELSE, THEN, DO, | ||
| - | LOOP, BEGIN and UNTIL. | ||
| - | a.test and how the numbers 5, 0 and 4 are stored in b.test and | ||
| - | c.test. | ||
| - | comment; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | </ | ||
papierkorb/4th_lesson_9.1755364236.txt.gz · Zuletzt geändert: 2025-08-16 19:10 von mka