\ Lesson 1 - Introducing Forth \ The Forth Course \ by Richard E. Haskell \ Dept. of Computer Science and Engineering \ Oakland University, Rochester, MI 48309 comment: Lesson 1 INTRODUCING FORTH 1.1 INTRODUCTING FORTH 1-2 1.2 FORTH ARITHMETIC 1-3 1.3 FORTH ARITHMETIC OPERATORS 1-4 1.4 STACK MANIPULATION WORDS 1-5 1.5 MORE FORTH WORDS 1-8 1.6 COLON DEFINITIONS 1-10 EXERCISES 1-12 1.1 INTRODUCING FORTH Everything in Forth is a word. Forth words must be separated by a space. Forth words are stored in a dictionary. Forth words may be either interpreted or compiled. When in the interpret mode, a Forth word is executed. When in the compile mode, a Forth word is stored in the dictionary. You form Forth phrases by stringing Forth words together. If you type a Forth word and press <Enter>, it will be executed. (Interpret mode). If you type a number (e.g. 6) and press <Enter>, the number will be stored on the stack as a 16-bit signed integer. Forth uses the stack extensively to pass parameters from one word to the next. This means that the need for variables in Forth is greatly reduced. You can define new words in Forth (made up of previously defined Forth words) that become part of the Forth dictionary, and can be used like any other Forth word. 1.2 FORTH ARITHMETIC Forth uses the stack to perform arithmetic operations using postfix notation. The stack stores 16-bit values in most Forths including F-PC. 32-bit Forths, such as MacForth, store 32-bit values on the stack. Thus, values on the stack will occupy 2 bytes in 16-bit Forths and 4 bytes in 32-bit Forths. When you type a number, it is placed on the stack. You can enter numbers in any base. We will see how to change the base later. The default base is decimal. Therefore, if you type 35, the hex value 23h (the suffix h indicates a hex value) will be stored on the stack as follows ___________ ___________________ | 0 0 2 3 | | 0 0 0 0 0 0 2 3 | |---------| |-----------------| 16-bit stack value 32-bit stack value If you type two numbers, separated by a space, they will both be stored on the stack. For example, if you type 127 256 the two hex values 7Fh and 100h will be stored on the stack as follows: ___________ | 0 1 0 0 |<--- top of stack |---------| | 0 0 7 F | |---------| Typing .S (or .s) displays the contents of the stack non-destructively. 127 256 .s 127 256 ok The word ok is the Forth prompt. Values are stored on the stack as signed two's complement numbers. Thus, for 16-bit Forths the values stored on the stack can range from -32,768 to +32,767. For 32-bit Forths the values stored on the stack can range from -2,147,483,648 to +2,147,483,647. 1.3 FORTH ARITHMETIC OPERATORS The Forth word . (dot) will print the value on top of the stack. 7 9 . . will print 9 7 Carriage returns are generally ignored by Forth and are treated as a blank. These can be used to make your program more readable. By writing your program in a "vertical" fashion you can indicate the "stack picture" to the right of your program following a backslash \. Anything following a backslash on a line is treated as a comment and is ignored. For example, to illustrate what is on the stack at each stage of the above example, we could write Stack picture (top of stack to right) 7 \ 7 9 \ 7 9 . \ 7 . \ Note that the dot removes the value from the stack. The Forth word + (plus) adds the top two values on the stack and leaves the result on the stack. For example, 7 9 + . will print 16 7 \ 7 9 \ 7 9 + \ 16 . \ The Forth word - (minus) will subtract the value on top of the stack from the second value on the stack and leave the difference on the stack. 8 5 - . will print 3 8 \ 8 5 \ 8 5 - \ 3 . \ The Forth word * (star) will multiply the top tow values on the stack and leave the product on the stack. 4 7 * . will print 28 4 \ 4 7 \ 4 7 * \ 28 . \ The Forth word / (slash) will divide the second value on the stack by the value on top of the stack and leave the integer quotient on top of the stack. 8 3 / . will print 2 8 \ 8 3 \ 8 3 / \ 2 . 1.4 STACK MANIPULATION WORDS Stack picture ( before -- after ) before = elements on stack before word is executed. after = elements on stack after word is executed. DUP ( n -- n n ) Duplicates the top element on the stack 5 DUP . . will print 5 5 5 \ 5 DUP \ 5 5 . \ 5 . \ SWAP ( n1 n2 -- n2 n1 ) Interchanges the top two elements on the stack. 3 7 SWAP . . will print 3 7 3 \ 3 7 \ 3 7 SWAP \ 7 3 . \ 7 . \ DROP ( n -- ) Removes the top element from the stack. 6 2 DROP . will print 6 6 \ 6 2 \ 6 2 DROP \ 6 . OVER ( n1 n2 -- n1 n2 n1 ) Duplicates the second element on the stack. 6 1 OVER . . . will print 6 1 6 6 \ 6 1 \ 6 1 OVER \ 6 1 6 . \ 6 1 . \ 6 . TUCK ( n1 n2 -- n2 n1 n2 ) Duplicates the top element on the stack under the second element. This is equivalent to SWAP OVER. 6 1 TUCK . . . will print 1 6 1 6 \ 6 1 \ 6 1 TUCK \ 1 6 1 . \ 1 6 . \ 1 . ROT ( n1 n2 n3 -- n2 n3 n1 ) Rotates the top three elements on the stack. The third element becomes the first element. 3 5 7 ROT . . . will print 3 7 5 3 \ 3 5 \ 3 5 7 \ 3 5 7 ROT \ 5 7 3 . \ 5 7 . \ 5 . -ROT ( n1 n2 n3 -- n3 n1 n2 ) Rotates the top three elements on the stack backwards. The top element is rotated to third place. 3 5 7 -ROT . . . will print 5 3 7 3 \ 3 5 \ 3 5 7 \ 3 5 7 -ROT \ 7 3 5 . \ 7 3 . \ 7 . NIP ( n1 n2 -- n2 ) Removes the second element from the stack. This is equivalent to SWAP DROP. 6 2 NIP . will print 2 6 \ 6 2 \ 6 2 NIP \ 2 . 2DUP ( n1 n2 -- n1 n2 n1 n2 ) Duplicates the top 2 elements on the stack. 2 4 2DUP .S will print 2 4 2 4 2SWAP ( n1 n2 n3 n4 -- n3 n4 n1 n2 ) Interchanges the top two numbers on the stack with the third and fourth numbers on the stack. 2 4 6 8 2SWAP .S will print 6 8 2 4 2DROP ( n1 n2 -- ) Removes the top two elements from the stack. PICK ( n1 -- n2 ) Duplicates the value at position n1 from the top of the stack (not counting n1). The top of the stack corresponds to n1 equal to 0. 0 PICK is the same as DUP 1 PICK is the same as OVER 2 4 6 8 2 PICK .S will print 2 4 6 8 4 ROLL ( n -- ) Rotate the value at position n (not counting n) to the top of the stack. n must be greater than 0. 1 ROLL is the same as SWAP 2 ROLL is the same as ROT 2 4 6 8 3 ROLL .S will print 4 6 8 2 1.5 MORE FORTH WORDS MOD ( n1 n2 -- n3 ) Divides n1 by n2 and leaves the remainder n3 on the stack. 8 3 MOD . will print 2 /MOD ( n1 n2 -- n3 n4 ) Divides n1 by n2 and leaves the quotient n4 on top of the stack and the remainder n3 as the second element on the stack. 10 3 /MOD .S will print 1 3 MIN ( n1 n2 -- n3 ) Leaves the smaller of n1 and n2 on the stack. 8 3 MIN . will print 3 MAX ( n1 n2 -- n3 ) Leaves the larger of n1 and n2 on the stack. 8 3 MAX . will print 8 NEGATE ( n1 -- n2 ) Changes the sign of n1. 8 NEGATE . will print -8 ABS ( n1 -- n2 ) Leaves the absolute value of n1 on the stack. -8 ABS . will print 8 2* ( n1 -- n2 ) Multiplies n1 by 2 by performing an arithmetic shift left. 8 2* . will print 16 This is equivalent to 8 2 * but is faster. 2/ ( n1 -- n2 ) Divides n1 by 2 by performing an arithmetic shift right. 8 2/ . will print 4 This is equivalent to 8 2 / but is faster. U2/ ( n1 -- n2 ) Performs a 16-bit logical shift right. 40000 U2/ . will print 20000 but 40000 2/ . will print -12768 8* ( n1 -- n2 ) Multiplies n1 by 8 by performing a 3-bit arithmetic shift left. 7 8* . will print 56 This is equivalent to 7 8 * but is faster. 1+ ( n1 -- n2 ) Increments the top of the stack by one. 1- ( n1 -- n2 ) Decrements the top of the stack by one. 2+ ( n1 -- n2 ) Increments the top of the stack by two. 2- ( n1 -- n2 ) Decrements the top of the stack by two. U/16 ( u -- u/16 ) \ u signifies an unsigned 16-bit integer Divides the unsigned integer u by 16 by performing a 4-bit logical shift right. 1.6 COLON DEFINITIONS You can define your own Forth words, made up of other Forth words, by using the Forth word : (colon) in the following form: : <name> --- --- --- --- ; where the colon : begins the definition <name> is the name of your Forth word --- --- are the Forth words making up you definition the semi-colon ; ends the definition. Examples: If you don't like the period to print the value of the top of the stack, you could redefine it to be == (We'll use the double equal sign because the single equal sign = is already a Forth word). Note: Paren ( is a Forth word that treats everything to the closing paren ) as a comment. Therefore, there MUST be a space after the (. comment; \ the words comment: --- comment; have bracketed all of \ Lesson 1 up to this point. When you type FLOAD LESSON1 \ all of the words between comment: and comment; will be \ treated as a comment and ignored. However, the following \ colon definitions will be compiled by loading them into \ the dictionary. You can type them in one at a time by \ yourself from the keyboard, or you can just type \ FLOAD LESSON1. : == ( n -- ) \ print the top value of the stack . ; \ Type in this colon definition and then try it by \ typing 5 7 + == : squared ( n -- n**2 ) \ compute the square of n DUP * ; \ Try typing \ 5 squared == \ 3 squared == \ 7 squared == : cubed ( n -- n**3 ) \ compute the cube of n DUP \ n n squared \ n n**2 * ; \ n**3 \ Try typing \ 3 cubed == \ 5 cubed == \ 10 cubed == comment: The following are two useful Forth words: CR ( -- ) ( "carriage return" ) Produces a "carriage return" and line feed on the screen. ." ( -- ) ( "dot-quote" ) Prints a string consisting of characters to closing ". comment; \ Define the following words: : bar ( -- ) \ print a bar CR ." *****" ; \ Type bar : post ( -- ) \ print a post CR ." *" CR ." *" ; \ Type post : C ( -- ) \ print a C bar post post bar ; \ Type C : E ( -- ) \ print an E bar post bar post bar ; \ Type E comment: Note that new Forth words are defined in terms of previously defined words. This is the way Forth works. New, more powerful words are continually being defined. When you get done, your entire main program will be just one word. The words you define are stored in the Forth dictionary along with all the pre-defined Forth words. They become part of the Forth language and are treated just like any other Forth word. The Forth interpreter cannot tell the difference between words that you define and words that come as part of the language. This means that every Forth application program is really a specialized language that is designed to solve a particular problem. EXERCISE 1.1 A rectangle can be defined by giving its top-left (t l) and bottom-right (b r) coordinates. Let the x-coordinate increase from left to right and the y-coordinate increase from top to bottom. Define three Forth words, AREA, CIRCUM and CENTER that will calculate the area, circumference and center of the rectangle given the top, left, bottom and right values on the stack as follows: AREA ( t l b r -- area ) CIRCUM ( t l b r -- circum ) CENTER ( t l b r -- xc yc ) Test your three words using the following two sets of values for top, left, bottom and right: top: 31 10 left: 16 27 bottom: 94 215 right: 69 230 comment;