The Forth stack is a last-in, first-out buffer used for temporarily holding numeric information. Think of it as a stack of books: the last one you put on the top of the stack is the first one you take off. Understanding the stack is essential to using Forth.
To put a number on the stack, simply type its value.
ok 44 (The value 44 is now on top of the stack) ok 7 (The value 7 is now on top, with 44 just underneath) ok
The contents of the stack are normally invisible. However, properly visualizing the current stack contents is important for achieving the desired result. To show the stack contents with every ok prompt, type:
ok showstack 44 7 ok 8 44 7 8ok noshowstack ok
The topmost stack item is always shown as the last item in the list, immediately before the ok prompt. In the above example, the topmost stack item is 8.
If showstack has been previously executed, noshowstack will remove the stack display prior to each prompt.
In some of the examples in this chapter, showstack is enabled. In those examples, each ok prompt is immediately preceded by a display of the current contents of the stack. The examples work the same if showstack is not enabled, except that the stack contents are not displayed.
Nearly all words that require numeric parameters fetch those parameters from the top of the stack. Any values returned are generally left on top of the stack, where they can be viewed or consumed by another command. For example, the Forth word + removes two numbers from the stack, adds them together, and leaves the result on the stack. In the example below, all arithmetic is in hexadecimal.
44 7 8 ok + 44 f ok + 53 ok
Once the two values are added together, the result is put onto the top of the stack. The Forth word . removes the top stack item and displays that value on the screen. For example:
53 ok 12 53 12 ok . 12 53 ok . 53 ok (The stack is now empty) ok 3 5 + . 8 ok (The stack is now empty) ok . Stack Underflow ok
To aid understanding, conventional coding style requires that a stack diagram of the form ( -- ) appear on the first line of every definition of a Forth word. The stack diagram specifies what the execution of the word does to the stack.
Entries to the left of -- represent those stack items that the word removes from the stack and uses during its operation. The right-most of these items is on top of the stack, with any preceding items beneath it. In other words, arguments are pushed onto the stack in left to right order, leaving the most recent one (the right-most one in the diagram) on the top.
Entries to the right of -- represent those stack items that the word leaves on the stack after it finishes execution. Again, the right-most item is on top of the stack, with any preceding items beneath it.
For example, a stack diagram for the word + is:
( nu1 nu2 -- sum )
Therefore, + removes two numbers (nu1 and nu2) from the stack and leaves their sum (sum) on the stack. As a second example, a stack diagram for the word. is:
( nu -- )
The word . removes the number on the top of the stack (nu) and displays it.
Words that have no effect on the contents of the stack (such as showstack or decimal), have a ( -- ) stack diagram.
Occasionally, a word will require another word or other text immediately following it on the command line. The word see, used in the form:
see thisword
is such an example.
Stack items are generally written using descriptive names to help clarify correct usage. See Table 4-2 for stack item abbreviations used in this manual.
Table 4-2 Stack Item Notation
Notation |
Description |
---|---|
| |
Alternate stack results shown with space, e.g. ( input -- addr len false | result true ). |
??? |
Unknown stack item(s). |
... |
Unknown stack item(s). If used on both sides of a stack comment, means the same stack items are present on both sides. |
< > <space> |
Space delimiter. Leading spaces are ignored. |
a-addr |
Variable-aligned address. |
addr |
Memory address (generally a virtual address). |
addr len |
Address and length for memory region |
byte bxxx |
8-bit value (low order byte in a cell). |
char |
7-bit value (low order byte in a cell, high bit of low order byte unspecified). |
cnt |
Count. |
len |
Length. |
size |
Count or length. |
dxxx |
Double (extended-precision) numbers. 2 cells, most significant cell on top of stack. |
<eol> |
End-of-line delimiter. |
false |
0 (false flag). |
n n1 n2 n3 |
Normal signed, one-cell values. |
nu nu1 |
Signed or unsigned one-cell values. |
<nothing> |
Zero stack items. |
o o1 o2 oct1 oct2 |
Octlet (64 bit signed value). |
oaddr |
Octlet (64-bit ) aligned address. |
octlet |
An eight-byte quantity. |
phys |
Physical address (actual hardware address). |
phys.lo phys.hi |
Lower / upper cell of physical address. |
pstr |
Packed string. |
quad qxxx |
Quadlet (32-bit value, low order four bytes in a cell). |
qaddr |
Quadlet (32-bit) aligned address. |
true |
-1 (true flag). |
uxxx |
Unsigned positive, one-cell values. |
virt |
Virtual address (address used by software). |
waddr |
Doublet (16-bit) aligned address. |
word wxxx |
Doublet (16-bit value, low order two bytes in a cell). |
x x1 |
Arbitrary, one cell stack item. |
x.lo x.hi |
Low/high significant bits of a data item. |
xt |
Execution token. |
xxx? |
Flag. Name indicates usage (e.g. done? ok? error?). |
xyz-str xyz-len |
Address and length for unpacked string. |
xyz-sys |
Control-flow stack items, implementation-dependent. |
( C: -- ) |
Compilation stack diagram. |
( -- )( E: -- ) |
Execution stack diagram. |
( R: -- ) |
Return stack diagram. |
Stack manipulation commands (described in Table 4-3) allow you to add, delete, and reorder items on the stack.
Table 4-3 Stack Manipulation Commands
Command |
Stack Diagram |
Description |
---|---|---|
clear |
( ??? -- ) |
Empty the stack. |
depth |
( ... -- ... u ) |
Return the number of items on the stack. |
drop |
( x -- ) |
Remove top item from the stack. |
2drop |
( x1 x2 -- ) |
Remove 2 items from the stack. |
3drop |
( x1 x2 x3 -- ) |
Remove 3 items from the stack. |
dup |
( x -- x x ) |
Duplicate the top stack item. |
2dup |
( x1 x2 -- x1 x2 x1 x2 ) |
Duplicate 2 stack items. |
3dup |
( x1 x2 x3 -- x1 x2 x3 x1 x2 x3 ) |
Duplicate 3 stack items. |
?dup |
( x -- x x | 0 ) |
Duplicate the top stack item if it is non-zero. |
nip |
( x1 x2 -- x2 ) |
Discard the second stack item. |
over |
( x1 x2 -- x1 x2 x1 ) |
Copy second stack item to top of stack. |
2over |
( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 ) |
Copy second 2 stack items. |
pick |
( xu ... x1 x0 u -- xu ... x1 x0 xu ) |
Copy u-th stack item (1 pick = over). |
>r |
( x -- ) (R: -- x ) |
Move a stack item to the return stack. |
r> |
( -- x ) ( R: x -- ) |
Move a return stack item to the stack. |
r@ |
( -- x ) ( R: x -- x ) |
Copy the top of the return stack to the stack. |
roll |
( xu ... x1 x0 u -- xu-1 ... x1 x0 xu ) |
Rotate u stack items (2 roll = rot). |
rot |
( x1 x2 x3 -- x2 x3 x1 ) |
Rotate 3 stack items. |
-rot |
( x1 x2 x3 -- x3 x1 x2 ) |
Inversely rotate 3 stack items. |
2rot |
( x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2 ) |
Rotate 3 pairs of stack items. |
swap |
( x1 x2 -- x2 x1 ) |
Exchange the top 2 stack items. |
2swap |
( x1 x2 x3 x4 -- x3 x4 x1 x2 ) |
Exchange 2 pairs of stack items. |
tuck |
( x1 x2 -- x2 x1 x2 ) |
Copy top stack item below second item. |
A typical use of stack manipulation might be to display the top stack item while preserving all stack items, as shown in this example:
5 77 ok dup (Duplicates the top item on the stack) 5 77 77 ok . (Removes and displays the top stack item) 77 5 77 ok