Doing math with forth
The most notable aspect of Forth is that data (arguments) are passed to the words via a stack. While it is true that many languages use stacks for parameter passing, the developer is usually unaware of this aspect. Forth, however, is quite different. In Forth, arguments required by a word are pushed onto the stack explicitly, and then the word is called. Words return their results to the stack. The values can be pushed or pulled from the stack by other words or manually (and interactively) by the user.
|
A stack is just as the name implies. Think of it like a stack of books. The topmost item on the stack is the last that was placed there, and it’s also the first that will be removed. In Forth, it’s a stack of numbers.
|
|
In Forth, the words that a developer writes directly manipulate the stack, taking parameters off and putting new values (returning parameters) back. In addition, the developer can directly manipulate the stack at the prompt, manually pushing or popping stack values prior to running a given word. This feature encompasses the power and beauty of Forth.
As a consequence of the stack, Forth uses a form of syntax known as Reverse Polish Notation (RPN). Anyone who has used an old-style Hewlett-Packard calculator is familiar with RPN. In this notation, the operator follows the arguments. So, the conventional expression a + b becomes in RPN a b +
First the number represented by a is pushed onto the stack, then b goes onto the stack. In Forth, the + word (operator) takes these values off the stack, performs the addition and places the result back on the stack.
So:
As a consequence of the stack, Forth uses a form of syntax known as Reverse Polish Notation (RPN). Anyone who has used an old-style Hewlett-Packard calculator is familiar with RPN. In this notation, the operator follows the arguments. So, the conventional expression a + b becomes in RPN a b +
First the number represented by a is pushed onto the stack, then b goes onto the stack. In Forth, the + word (operator) takes these values off the stack, performs the addition and places the result back on the stack.
So:
4 5 +
gives a result of 9 on the top of the stack. To display this result, we use . (“dot”) which pulls the topmost value from the stack and prints it to the console as a signed number. To output the top stack value as an unsigned number, use u. rather than the . operator.
As an example, to add three numbers together and print the result, we would type the following at the prompt:
As an example, to add three numbers together and print the result, we would type the following at the prompt:
5 25 98 + + .
The first + adds 98 and 25, leaving the result on the stack. The second + adds this result to 5. This could also be done as:
25 98 + 5 + .
Most versions of Forth use 16-bit numbers, although there are some Forths that are explicitly 32 bits. 16-bit Forths do provide access to 32-bit arithmetic using doubles. (More on that in a later section.)
Standard arithmetic is available using +, -, * and / . These arithmetic operators are Forth words, and so must be separated by spaces.
To multiply 2 and 3:
To multiply 2 and 3:
2 3 *
The / operator performs signed integer division, discarding any fractional remainder. The result is rounded toward zero.
To divide 9 by 3:
To divide 9 by 3:
9 3 /
gives the result of 3 on the stack.
While:
While:
9 2 /
gives the rounded result of 4 on the stack.
For unsigned division, use the u/ operator.
We can increment the top of the stack using the word 1+, or decrement it using 1-. As a nonsensical example, to convert 2 to 3:
For unsigned division, use the u/ operator.
We can increment the top of the stack using the word 1+, or decrement it using 1-. As a nonsensical example, to convert 2 to 3:
2 1+
Base
By default, Forth works in base 10 (decimal). hex changes the base to base 16, and decimal returns it to base 10. Similarly, binary changes it to base 2. As an example, let’s add (hex) $4f to (decimal) 255 and print out the result in decimal:
hex
4f
decimal
255
+ .
which gives a result of 334 on the console.
Regardless of the current base, you can enter a number in another base by using the appropriate prefix. $fec6 is a hex number, #45 is a decimal number and %11010101 is a binary number.
Regardless of the current base, you can enter a number in another base by using the appropriate prefix. $fec6 is a hex number, #45 is a decimal number and %11010101 is a binary number.
|
Note that FlashForth is case sensitive and only lower-case hex numbers are supported. So, entering $fec6 will work, while $FEC6 will generate an error.
|
|
Without changing base, we can perform the previous arithmetic, thus:
$4f #255 + .
Now, let's learn how to look at and work with the stack.