This chapter introduces the Forth programming language as it is implemented in OpenBoot. Even if you are familiar with Forth, work through the examples shown in this chapter. The examples provide specific, OpenBoot-related information.
The version of Forth contained in OpenBoot is based on ANS Forth.
Appendix D
lists the complete set of available commands.
Note - This chapter assumes that you know how to start and leave the user interface. At the ok prompt, if you type commands that hang the system and you cannot recover using a key sequence, you may need to perform a power cycle to return the system to normal operation.
|
Forth Commands
Forth has a very simple command structure. Forth commands, also called Forth
words
, consist of any combination of characters that can be printed. For example, letters, digits, or punctuation marks. Examples of legitimate words are shown below:
Forth words must be separated from one another by one or more spaces (blanks). Characters that are normally treated as "punctuation" in some other programming languages do not separate Forth words. In fact, many of those "punctuation" characters are Forth words.
Pressing Return at the end of any command line executes the typed commands. In all the examples shown, a Return at the end of the line is assumed.
You can type more than one word at a command line. Multiple words on a line are executed one at a time, from left to right, in the order in which they were typed. For example:
is equivalent to:
ok testa
ok testb
ok testc
ok
|
In OpenBoot, Forth word names are case-insensitive. Therefore,
testa
,
TESTA
, and
TesTa
all invoke the same command. However, words are conventionally written in lowercase.
Some commands generate large amounts of output (for example,
dump
or
words
). You can interrupt such a command by pressing any key except
q
. If you press
q
, the output is aborted, not suspended. Once a command is interrupted, output is suspended and the following message appears:
Press the space bar (
<space>
) to continue, press Return (
<cr>
) to output one more line and pause again, or type
q
to abort the command. When a command generates more than one page of output, the system automatically displays this prompt at the end of each page.
Data Types
The terms shown in
TABLE 4-1
describe the data types used by Forth.
TABLE 4-1 Forth Data Type Definitions
Notation
|
Description
|
byte
|
An 8-bit value.
|
cell
|
The implementation-defined fixed size of a cell is specified in address units and the corresponding number of bits. Data-stack elements, return-stack elements, addresses, execution tokens, flags, and integers are one cell wide.
On OpenBoot systems, a cell consists of at least 32-bits, and is sufficiently large to contain a virtual address. The cell size may vary between implementations. A 32-bit implementation has a cell size of 4. A 64-bit implementation has a cell size of 8. OpenBoot 4.
x
is a 64-bit implementation.
|
doublet
|
A 16-bit value.
|
octlet
|
A 64-bit value; only defined on 64-bit implementations,
|
quadlet
|
A 32-bit value.
|
Using Numbers
Enter a number by typing its value, for example, 55 or -123. Forth accepts only integers (whole numbers); it does not understand fractional values (for example,
2/3). A period at the end of a number signifies a double number. Periods or commas embedded in a number are ignored, so 5.77 is understood as 577. By convention, such punctuation usually appears every four digits. Use one or more spaces to separate a number from a word or from another number.
Unless otherwise specified, OpenBoot performs integer arithmetic on data items that are one cell in size, and creates results that are one cell in size.
Although OpenBoot implementations are encouraged to use base 16 (hexadecimal) by default, they are not required to do so. Consequently, you must establish a specific number base if your code depends on a given base for proper operation. You can change the number base with the commands
decimal
and
hex
to cause all subsequent numeric input and output to be performed in base 10 or 16, respectively.
For example, to operate in decimal, type:
To change to hexadecimal, type:
To identify the current number base, you can use:
The
16
on the display shows that you are operating in hexadecimal. If
10
appeared on the display, it would mean that you are in decimal base. The
.d
command displays a number in base 10, regardless of the current number base.
Forth Stack
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
|
Displaying Stack Contents
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 8 ok 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
removes the stack display prior to each prompt.
Note Note - 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
|
Stack Diagram
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 the number.
Words that have no effect on the contents of the stack (such as
showstack
or
decimal
), have a
( -- )
stack diagram.
Occasionally, a word requires another word or other text immediately following it on the command line. The word
see
, used in the following form, is such an example:
see
thisword
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,
for example,
(
input -- addr len false
|
result true
).
|
|
|
Alternate stack items shown without space,
for example, (
input -- addr len
|
0 result
).
|
???
|
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 b
xxx
|
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.
|
d
xxx
|
Double (extended-precision) numbers. Two 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 8-byte quantity.
|
phys
|
Physical address (actual hardware address).
|
phys.lo
phys.hi
|
Lower / upper cell of physical address.
|
pstr
|
Packed string.
|
quad q
xxx
|
Quadlet (32-bit value, low order four bytes in a cell).
|
qaddr
|
Quadlet (32-bit) aligned address.
|
true
|
-1 (true flag).
|
u
xxx
|
Unsigned positive, one-cell values.
|
virt
|
Virtual address (address used by software).
|
waddr
|
Doublet (16-bit) aligned address.
|
word w
xxx
|
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.
|
Manipulating the Stack
Stack manipulation commands (described in
TABLE 4-1
) allow you to add, delete, and reorder items on the stack.
TABLE 4-3 Stack Manipulation Commands
Command
|
Stack Diagram
|
Description
|
clear
|
( ??? -- )
|
Empties the stack.
|
depth
|
( ... -- ... u )
|
Returns the number of items on the stack.
|
drop
|
( x -- )
|
Removes top item from the stack.
|
2drop
|
( x1 x2 -- )
|
Removes 2 items from the stack.
|
3drop
|
( x1 x2 x3 -- )
|
Removes 3 items from the stack.
|
dup
|
( x -- x x )
|
Duplicates the top stack item.
|
2dup
|
( x1 x2 -- x1 x2 x1 x2 )
|
Duplicates 2 stack items.
|
3dup
|
( x1 x2 x3 -- x1 x2 x3 x1 x2 x3 )
|
Duplicates 3 stack items.
|
?dup
|
( x -- x x | 0 )
|
Duplicates the top stack item if it is non-zero.
|
nip
|
( x1 x2 -- x2 )
|
Discards the second stack item.
|
over
|
( x1 x2 -- x1 x2 x1 )
|
Copies second stack item to top of stack.
|
2over
|
( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )
|
Copies second 2 stack items.
|
pick
|
( xu ... x1 x0 u -- xu ... x1 x0 xu )
|
Copies
u
-th stack item (
1
pick
=
over
).
|
>r
|
( x -- ) (R: -- x )
|
Moves a stack item to the return stack.
|
r>
|
( -- x ) ( R: x -- )
|
Moves a return stack item to the stack.
|
r@
|
( -- x ) ( R: x -- x )
|
Copies the top of the return stack to the stack.
|
roll
|
( xu ... x1 x0 u -- xu-1 ... x1 x0 xu )
|
Rotates
u
stack items (
2
roll
=
rot
).
|
rot
|
( x1 x2 x3 -- x2 x3 x1 )
|
Rotates 3 stack items.
|
-rot
|
( x1 x2 x3 -- x3 x1 x2 )
|
Inversely rotates 3 stack items.
|
2rot
|
( x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2 )
|
Rotates 3 pairs of stack items.
|
swap
|
( x1 x2 -- x2 x1 )
|
Exchanges the top 2 stack items.
|
2swap
|
( x1 x2 x3 x4 -- x3 x4 x1 x2 )
|
Exchanges 2 pairs of stack items.
|
tuck
|
( x1 x2 -- x2 x1 x2 )
|
Copies top stack item below second item.
|
A typical use of stack manipulation is 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
|
Creating Custom Definitions
Forth provides an easy way to create new command words from sequences of existing words.
TABLE 4-4
shows the Forth words used to create such new words.
TABLE 4-4 Colon Definition Words
Command
|
Stack Diagram
|
Description
|
:
new-name
|
( -- )
|
Starts a new colon definition of the word
new-name
.
|
;
|
( -- )
|
Ends a colon definition.
|
This kind of word is called a
colon definition
,
named after the word that is used
to create them. For example, suppose you want to create a new word,
add4
, that adds any four numbers together and displays the result. You could create the definition as follows:
The ; (semicolon) marks the end of the definition that defines
add4
to have the behavior (
+ + + .
). The three addition operators (
+
) reduce the four stack items to a single sum on the stack; then
.
removes and displays that result. An example follows.
ok 1 2 3 3 + + + .
9
ok 1 2 3 3 add4
9
ok
|
Definitions are forgotten if a system reset takes place. To keep useful definitions, put them into the script or save them in a text file on a host system. This text file can then be loaded as needed. (See
Chapter 5
for more information on loading files.)
When you type a definition from the user interface, the
ok
prompt
becomes a
]
(right square bracket) prompt after you type the
:
(colon)
and before you type the
;
(semicolon). For example, you could type the definition for
add4
like this:
ok : add4
] + + +
] .
] ;
ok
|
The above use of
]
while inside a multi-line definition is a characteristic of Sun's implementation.
-
The stack diagram shows proper use of a word, so include a stack diagram with every definition you create, even if the stack effect is nil ( -- ). Use generous stack comments in complex definitions to trace the flow of execution. For example, when creating
add4
, you could define it as:
ok : add4 ( n1 n2 n3 n4 -- ) + + + . ;
|
Or you could define it as follows:
ok : add4 ( n1 n2 n3 n4 -- )
] + + + ( sum )
] .
] ;
|
Note Note - The "(" is a Forth word meaning ignore the text up to the ")". Like any other Forth word, the "(" must have one or more spaces after it.
|
Using Arithmetic Functions
Single-Precision Integer Arithmetic
The commands listed in
TABLE 4-5
perform single-precision arithmetic.
TABLE 4-5 Single-Precision Arithmetic Functions
Command
|
Stack Diagram
|
Description
|
+
|
( nu1 nu2 -- sum )
|
Adds
nu1
+
nu2
.
|
-
|
( nu1 nu2 -- diff )
|
Subtracts
nu1
-
nu2
.
|
*
|
( nu1 nu2 -- prod )
|
Multiplies
nu1
times
nu2
.
|
*/
|
( n1 n2 n3 -- quot )
|
Calculates
nu1
*
nu2 / n3
. Inputs, outputs and intermediate products are all one cell.
|
/
|
( n1 n2 -- quot )
|
Divides
n1
by
n2
; remainder is discarded.
|
1+
|
( nu1 -- nu2 )
|
Adds one.
|
1-
|
( nu1 -- nu2
)
|
Subtracts one.
|
2+
|
( nu1 -- nu2 )
|
Adds two.
|
2-
|
( nu1 -- nu2 )
|
Subtracts two.
|
abs
|
( n -- u )
|
Absolute value.
|
bounds
|
( start len -- len+start start )
|
Converts start,len to end,start for
do
or
?do
loop.
|
even
|
( n -- n | n+1 )
|
Rounds to nearest even integer >=
n
.
|
max
|
( n1 n2 -- n3 )
|
n3
is maximum of
n1
and
n2
.
|
min
|
( n1 n2 -- n3 )
|
n3
is minimum of
n1
and
n2.
|
mod
|
( n1 n2 -- rem )
|
Remainder of
n1
/
n2
.
|
*/mod
|
( n1 n2 n3 -- rem quot )
|
Remainder, quotient of
n1
*
n2
/
n3
.
|
/mod
|
( n1 n2 -- rem quot )
|
Remainder, quotient of
n1
/
n2
.
|
negate
|
( n1 -- n2 )
|
Changes the sign of
n1
.
|
u*
|
(u1 u2 -- uprod )
|
Multiplies 2 unsigned numbers, yielding an unsigned product.
|
u/mod
|
( u1 u2 -- urem uquot )
|
Divides unsigned one-cell number by an unsigned one-cell number; yields one-cell remainder and quotient.
|
<<
|
( x1 u -- x2 )
|
Synonym for
lshift
.
|
>>
|
( x1 u -- x2 )
|
Synonym for
rshift
.
|
2*
|
( x1 -- x2
)
|
Multiplies by 2.
|
2/
|
( x1 -- x2 )
|
Divides by 2.
|
>>a
|
( x1 u -- x2 )
|
Arithmetic right-shift
x1
by
u
bits.
|
and
|
( x1 x2 -- x3 )
|
Bitwise logical AND.
|
invert
|
( x1 -- x2 )
|
Inverts all bits of
x1
.
|
lshift
|
( x1 u -- x2 )
|
Left-shifts
x1
by
u
bits. Zero-fill low bits.
|
not
|
( x1 -- x2 )
|
Synonym for
invert
.
|
or
|
( x1 x2 -- x3 )
|
Bitwise logical OR.
|
rshift
|
( x1 u -- x2 )
|
Right-shifts
x1
by
u
bits. Zero-fill high bits.
|
u2/
|
( x1 -- x2 )
|
Logical right shift 1 bit; zero shifted into high bit.
|
xor
|
( x1 x2 -- x3 )
|
Bitwise exclusive OR.
|
Double Number Arithmetic
The commands listed in
TABLE 4-6
perform double number arithmetic.
TABLE 4-6 Double Number Arithmetic Functions
Command
|
Stack Diagram
|
Description
|
d+
|
( d1 d2 -- d.sum )
|
Adds
d1
to
d2
, yielding double number
d.sum
.
|
d-
|
( d1 d2 --d.diff )
|
Subtracts
d2
from
d1
, yielding double number
d.diff
.
|
fm/mod
|
( d n -- rem quot )
|
Divides
d
by
n
.
|
m*
|
( n1 n2 -- d )
|
Signed multiply with double-number product.
|
s>d
|
( n1 -- d1 )
|
Converts a number to a double number.
|
sm/rem
|
( d n -- rem quot )
|
Divides
d
by
n
, symmetric division.
|
um*
|
( u1 u2 -- ud )
|
Unsigned multiply yielding unsigned double number product.
|
um/mod
|
( ud u -- urem uprod )
|
Divides
ud
by
u
.
|
Data Type Conversion
The commands listed in
TABLE 4-7
perform data type
conversion.
TABLE 4-7 32-Bit Data Type Conversion Functions
Command
|
Stack Diagram
|
Description
|
bljoin
|
( b.low b2 b3 b.hi -- quad )
|
Joins four bytes to form a quadlet
|
bwjoin
|
( b.low b.hi -- word )
|
Joins two bytes to form a doublet.
|
lbflip
|
( quad1 -- quad2 )
|
Reverses the bytes in a quadlet.
|
lbsplit
|
( quad -- b.low b2 b3 b.hi )
|
Splits a quadlet into four bytes.
|
lwflip
|
( quad1 -- quad2 )
|
Swaps the doublets in a quadlet.
|
lwsplit
|
( quad -- w.low w.hi )
|
Splits a quadlet into two doublets.
|
wbflip
|
( word1 -- word2 )
|
Swaps the bytes in a doublet.
|
wbsplit
|
( word -- b.low b.hi )
|
Splits a doublet into two bytes.
|
wljoin
|
( w.low w.hi -- quad )
|
Joins two doublets to form a quadlet.
|
The data type conversion commands listed in
TABLE 4-8
are available only on 64-bit OpenBoot implementations.
TABLE 4-8 64-Bit Data Type Conversion Functions
Command
|
Stack Diagram
|
Description
|
bxjoin
|
( b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi -- o )
|
Joins eight bytes to form an octlet.
|
lxjoin
|
( quad.lo quad.hi -- o )
|
Joins two quadlets to form an octlet.
|
wxjoin
|
( w.lo w.2 w.3 w.hi -- o )
|
Joins four doublets to form an octlet.
|
xbflip
|
( oct1 -- oct2 )
|
Reverses the bytes in an octlet.
|
xbsplit
|
( o -- b.lo b.2 b.3 b.4 b.5 b.6 b.7 b.hi )
|
Splits an octlet into eight bytes.
|
xlflip
|
( oct1 -- oct2 )
|
Reverses the quadlets in an octlet. The bytes in each quadlet are not reversed.
|
xlsplit
|
( o -- quad.lo quad.hi )
|
Splits an octlet into two quadlets.
|
xwflip
|
( oct1 -- oct2 )
|
Reverses the doublets in an octlet. The bytes in each doublet are not reversed.
|
xwsplit
|
( o -- w.lo w.2 w.3 w.hi )
|
Splits an octlet into four doublets.
|
Address Arithmetic
The commands listed in
TABLE 4-9
perform address arithmetic.
TABLE 4-9 Address Arithmetic Functions
Command
|
Stack Diagram
|
Description
|
aligned
|
( n1 -- n1 | a-addr)
|
Increases
n1
if necessary to yield a variable aligned address.
|
/c
|
( -- n )
|
The number of address units to a byte: 1.
|
/c*
|
( nu1 -- nu2 )
|
Synonym for
chars
.
|
ca+
|
( addr1 index -- addr2 )
|
Increments
addr1
by
index
times the value of
/c
.
|
ca1+
|
( addr1 -- addr2 )
|
Synonym for
char+
.
|
cell+
|
( addr1 -- addr2 )
|
Increments
addr1
by the value of
/n
.
|
cells
|
( nu1 -- nu2 )
|
Multiplies
nu1
by the value of
/n
.
|
char+
|
( addr1 -- addr2 )
|
Increments
addr1
by the value of
/c
.
|
chars
|
( nu1 -- nu2 )
|
Multiplies
nu1
by the value of
/c
.
|
/l
|
( -- n )
|
Number of address units to a quadlet; typically 4.
|
/l*
|
( nu1 -- nu2 )
|
Multiplies
nu1
by the value of
/l
.
|
la+
|
( addr1 index -- addr2 )
|
Increments
addr1
by
index
times the value of
/l
.
|
la1+
|
( addr1 -- addr2 )
|
Increments
addr1
by the value of
/l
.
|
/n
|
( -- n )
|
Number of address units in a cell.
|
/n*
|
( nu1 -- nu2 )
|
Synonym for
cells
.
|
na+
|
( addr1 index -- addr2 )
|
Increments
addr1
by
index
times the value of
/n
.
|
na1+
|
( addr1 -- addr2 )
|
Synonym for
cell+
.
|
/w
|
( -- n )
|
Number of address units to a doublet; typically 2.
|
/w*
|
( nu1 -- nu2 )
|
Multiplies
nu1
by the value of
/w
.
|
wa+
|
( addr1 index -- addr2 )
|
Increments
addr1
by
index
times the value of
/w
.
|
wa1+
|
( addr1 -- addr2 )
|
Increments
addr1
by the value of
/w
.
|
The address arithmetic commands listed in
TABLE 4-10
are available only on 64-bit OpenBoot implementations.
TABLE 4-10 64-Bit Address Arithmetic Functions
Command
|
Stack Diagram
|
Description
|
/x
|
( -- n )
|
Number of address units in an octlet, typically 8.
|
/x*
|
( nu1 -- nu2 )
|
Multiplies
nu1
by the value of
/x
.
|
xa+
|
( addr1 index -- addr2 )
|
Increments
addr1
by
index
times the value of
/x.
|
xa1+
|
( addr1 -- addr2 )
|
Increments
addr1
by the value of
/x.
|
Accessing Memory
Virtual Memory
The user interface provides interactive commands for examining and setting memory. With the user interface, you can:
Memory operators let you read from and write to any memory location. All memory addresses shown in the examples that follow are virtual addresses.
A variety of 8-bit, 16-bit, and 32-bit (and in some systems, 64-bit) operations are provided. In general:
-
a
c
(character) prefix indicates an 8-bit (one byte) operation
-
a
w
(word) prefix indicates a 16-bit (doublet) operation
-
an
l
(longword) prefix indicates a 32-bit (quadlet) operation
-
an
x
prefix indicates a 64-bit (octlet) operation
waddr
,
qaddr
, and
oaddr
indicate addresses with alignment restrictions. For example,
qaddr
indicates 32-bit (4 byte) alignment; on many systems such an address must be a multiple of 4, as shown in the following example:
ok 4028 l@
ok 4029 l@
Memory address not aligned
ok
|
Forth, as implemented in OpenBoot, adheres closely to the ANS Forth Standard. If you explicitly want a 16-bit fetch, a 32-bit fetch or (on some systems) a 64-bit fetch, use
w@
,
l@
or
x@
instead of
@
. Other memory and device register access commands also follow this convention.
TABLE 4-11
lists commands used to access memory.
TABLE 4-11 Memory Access Commands
Command
|
Stack Diagram
|
Description
|
!
|
( x a-addr -- )
|
Stores a number at
a-addr
.
|
+!
|
( nu a-addr -- )
|
Adds
nu
to the number stored at
a-addr
.
|
@
|
( a-addr -- x )
|
Fetches a number from
a-addr
.
|
2!
|
( x1 x2 a-addr -- )
|
Stores 2 numbers at
a-addr
,
x2
at lower address.
|
2@
|
( a-addr -- x1 x2 )
|
Fetches 2 numbers from
a-addr
,
x2
from lower address.
|
blank
|
( addr len -- )
|
Sets
len
bytes of memory beginning at
addr
to the space character (decimal 32).
|
c!
|
( byte addr -- )
|
Stores
byte
at
addr
.
|
c@
|
( addr -- byte )
|
Fetches a
byte
from
addr
.
|
cpeek
|
( addr -- false | byte true )
|
Attempts to fetch the byte at
addr
. Returns the data and
true
if the access was successful. Returns
false
if a read access error occurred.
|
cpoke
|
( byte addr -- okay? )
|
Attempts to store the
byte
to
addr
. Returns
true
if the access was successful. Returns
false
if a write access error occurred.
|
comp
|
( addr1 addr2 len -- diff? )
|
Compares two byte arrays.
diff?
is 0 if the arrays are identical,
diff?
is -1 if the first byte that is different is lesser in the string at
addr1
,
diff?
is 1 otherwise.
|
dump
|
( addr len -- )
|
Displays
len
bytes of memory starting at
addr
.
|
erase
|
( addr len -- )
|
Sets
len
bytes of memory beginning at
addr
to
0
.
|
fill
|
( addr len byte -- )
|
Sets
len
bytes of memory beginning at
addr
to the value
byte
.
|
l!
|
( q qaddr -- )
|
Stores a quadlet
q
at
qaddr
.
|
l@
|
( qaddr -- q )
|
Fetches a quadlet
q
from
qaddr
.
|
lbflips
|
( qaddr len -- )
|
Reverses the bytes in each quadlet in the specified region.
|
lwflips
|
( qaddr len -- )
|
Swaps the doublets in each quadlet in specified region.
|
lpeek
|
( qaddr -- false | quad true )
|
Attempts to fetch the quadlet at
qaddr
. Returns the data and
true
if the access was successful. Returns
false
if a read access error occurred.
|
lpoke
|
( q qaddr -- okay? )
|
Attempts to store the quadlet
q
at
qaddr
. Returns
true
if the access was successful. Returns
false
if a write access error occurred.
|
move
|
( src-addr dest-addr len -- )
|
Copies
len
bytes from
src-addr
to
dest-addr
.
|
off
|
( a-addr -- )
|
Stores
false
at
a-addr
.
|
on
|
( a-addr -- )
|
Stores
true
at
a-addr
.
|
unaligned-l!
|
( q addr -- )
|
Stores a quadlet
q
, any alignment
|
unaligned-l@
|
( addr -- q )
|
Fetches a quadlet
q
, any alignment.
|
unaligned-w!
|
( w addr -- )
|
Stores a doublet
w
, any alignment.
|
unaligned-w@
|
( addr -- w )
|
Fetches a doublet
w
, any alignment.
|
w!
|
( w waddr -- )
|
Stores a doublet
w
at
waddr
.
|
w@
|
( waddr -- w)
|
Fetches a doublet
w
from
waddr
.
|
<w@
|
( waddr -- n )
|
Fetches a doublet
n
from
waddr
, sign-extended.
|
wbflips
|
( waddr len -- )
|
Swaps the bytes in each doublet in the specified region.
|
wpeek
|
( waddr -- false | w true )
|
Attempts to fetch the doublet
w
at
waddr
. Returns the data and
true
if the access was successful. Returns
false
if a read access error occurred.
|
wpoke
|
( w waddr -- okay? )
|
Attempts to store the doublet
w
to
waddr
. Returns
true
if the access was successful. Returns
false
if a write access error occurred.
|
The memory access commands listed in
TABLE 4-12
are available only on 64-bit OpenBoot implementations.
TABLE 4-12 64-Bit Memory Access Functions
Command
|
Stack Diagram
|
Description
|
<l@
|
( qaddr -- n )
|
Fetches quadlet from
qaddr
, sign-extended.
|
x@
|
( oaddr -- o )
|
Fetches octlet from an octlet aligned address.
|
x!
|
( o oaddr -- )
|
Stores octlet to an octlet aligned address.
|
xbflips
|
( oaddr len -- )
|
Reverses the bytes in each octlet in the given region.The behavior is undefined if
len
is not a multiple of
/x
.
|
xlflips
|
( oaddr len -- )
|
Reverses the quadlets in each octlet in the given region. The bytes in each quadlet are not reversed. The behavior is undefined if
len
is not a multiple of
/x
.
|
xwflips
|
(
oaddr len -- )
|
Reverses the doublets in each octlet in the given region. The bytes in each doublet are not reversed. The behavior is undefined if
len
is not a multiple of
/x
.
|
The
dump
command is particularly useful. It displays a region of memory as both bytes and ASCII values. The example below displays the contents of 20 bytes of memory starting at virtual address 10000.
ok 10000 20 dump(Display 20 bytes of memory starting at virtual address 10000)
\/ 1 2 3 4 5 6 7 8 9 a b c d e f v123456789abcdef
10000 05 75 6e 74 69 6c 00 40 4e d4 00 00 da 18 00 00 .until.@NT..Z...
10010 ce da 00 00 f4 f4 00 00 fe dc 00 00 d3 0c 00 00 NZ..tt..~\..S...
ok
|
Some implementations support variants of
dump
that display memory as 16-, 32- and 64-bit values. You can use
sifting
dump
to find out if your system has such variants. See
Searching the Dictionary
.
If you try to access an invalid memory location (with
@
, for example), the operation may abort and display an error message, such as
Data
Access
Exception
or
Bus
Error
.
TABLE 4-13
lists memory mapping commands.
TABLE 4-13 Memory Mapping Commands
Command
|
Stack Diagram
|
Description
|
alloc-mem
|
( len -- a-addr )
|
Allocates
len
bytes of memory; return the virtual address.
|
free-mem
|
( a-addr len -- )
|
Frees memory allocated by
alloc-mem
.
|
The following example shows the use of
alloc-mem
and
free-mem
.
Device Registers
Device registers cannot be reliably accessed using the virtual memory access operators discussed in the last section. There are special operators for accessing device registers, and these operators require that the system be properly set up prior to their use. For a detailed explanation of this topic, see
Writing FCode 3.x Programs
.
Using Defining Words
The dictionary contains all the available Forth words. Forth
defining words
create new Forth words.
Defining words require two stack diagrams. The first diagram shows the stack effect when the new word is created. The second (or "Execution:") diagram shows the stack effect when that word is later executed.
TABLE 4-14
lists the defining words that you can use to create
new Forth words.
If you create a Forth command with the same name as an existing command, the new command is created normally. Depending on the implementation, a warning message
new-name isn't unique
may be displayed. Previous uses of that command name remain unaffected. Subsequent uses of that command name use the latest definition of that command name. To correct the original definition such that
all
uses of the command name get the corrected behavior, make the correction with
patch
. For further details, see
Using patch and (patch)
.
TABLE 4-14 Defining Words
Command
|
Stack Diagram
|
Description
|
:
name
|
( -- )(E: ... -- ??? )
|
Begins creation of a colon definition.
|
;
|
( -- )
|
Ends creation of a colon definition.
|
alias
new-name
old-name
|
( -- ) (E: ... -- ??? )
|
Creates
new-name
with the same behavior as
old-name
.
|
buffer:
name
|
( size -- )(E: -- a-addr )
|
Creates a named data buffer.
name
returns
a-addr
.
|
constant
name
|
( x -- )(E: -- x )
|
Creates a constant (for example,
3
constant
bar
).
|
2constant
name
|
( x1 x2 -- )(E: -- x1 x2 )
|
Creates a 2-number constant.
|
create
name
|
( -- )(E: -- a-addr )
|
Creates a new command whose behavior will be set by further commands.
|
$create
|
( name-str name-len -- )
|
create
using the name specified by
name-str
name-len
.
|
defer
name
|
( -- )(E: ... -- ??? )
|
Creates a command with alterable behavior. Alters with
to
.
|
does>
|
( ... -- ... a-addr )(E: ... -- ??? )
|
Specifies the run-time behavior of a
create
d word.
|
field
name
|
( offset size -- offset+size )(E: addr -- addr+offset )
|
Creates a field offset pointer named
name
.
|
struct
|
( -- 0 )
|
Starts a
struct...field
definition.
|
value
name
|
( x -- )(E: -- x )
|
Creates a named variable. Changes with
to
.
|
variable
name
|
( -- )(E: -- a-addr )
|
Creates a named variable.
name
returns
a-addr
.
|
value
lets you create a name for a numerical value that can be changed. Later execution of that name leaves the assigned value on the stack. The following example creates a word named
foo
with an initial value of 22, and then calls
foo
to use its value in an arithmetic operation.
ok 22 value foo
ok foo 3 + .
25
ok
|
The value can be changed with the word
to
. For example:
ok 43 value thisval
ok thisval .
43
ok 10 to thisval
ok thisval .
10
ok
|
Words created with
value
are convenient, because you do not have to use
@
to retrieve their values.
The defining word
variable
creates a name with an associated one-cell memory location. Later execution of that name leaves the address of the memory on the stack.
@
and
!
are used to read or write to that address. For example:
ok variable bar
ok 33 bar !
ok bar @ 2 + .
35
ok
|
The defining word
defer
creates a word whose behavior can be changed later, by creating a slot that can be loaded with different behaviors at different times. For example:
ok hex
ok defer printit
ok ['] .d to printit
ok ff printit
255
ok : myprint ( n -- ) ." It is " .h
] ." in hex " ;
ok ['] myprint to printit
ok ff printit
It is ff in hex
ok
|
Searching the Dictionary
The dictionary contains all the available Forth words.
TABLE 4-15
lists some useful tools for searching the dictionary. Please note that some of these tools work only with methods or commands while others work with all types of words (including, for example, variables and values).
TABLE 4-15 Dictionary Searching Commands
Command
|
Stack Diagram
|
Description
|
'
name
|
( -- xt )
|
Finds the named word in the dictionary. Returns the execution token. Uses outside definitions.
|
[']
name
|
( -- xt )
|
Similar to
'
but is used either inside or outside definitions.
|
.calls
|
( xt -- )
|
Displays a list of all commands which use the execution token
xt
.
|
$find
|
( str len -- xt true | str len false )
|
Searches for word named by
str,len
. If found, leaves
xt
and
true
on stack. If not found, leaves name string and
false
on stack.
|
find
|
( pstr -- xt n | pstr false )
|
Searches for word named by
pstr
. If found, leaves
xt
and
true
on stack. If not found, leaves name string and
false
on stack.
(We recommend using
$find
to avoid using packed strings.)
|
see
thisword
|
( -- )
|
Decompiles the specified word.
|
(see)
|
( xt -- )
|
Decompiles the word whose execution token is
xt
.
|
$sift
|
( text-addr text-len -- )
|
Displays all command names containing text-string.
|
sifting
text
|
( -- )
|
Displays all command names containing
text
.
text
contains no spaces.
|
words
|
( -- )
|
Displays the names of words in the dictionary as described below.
|
Before you can understand the operation of the dictionary searching tools, you need to understand how words become
visible
. If there is an
active package
at the time a word is defined, the new word becomes a method of the active package, and is visible only when that package is the active package. The commands
dev
and
find-device
can be used to select or change the active package. The command
device-end
deselects the currently active package leaving no active package.
If there is no active package at the time a word is defined, the word is
globally visible
(that is, not specific to a particular package and always available).
The dictionary searching commands first search through the words of the active package, if there is one, and then through the globally visible words.
Note Note - The Forth commands only and also affect which words are visible.
|
You can use
.calls
to locate all of the Forth commands that use a specified word in their definition.
.calls
takes an execution token from the stack and searches the entire dictionary to produce a listing of the names and addresses of every Forth command which uses that execution token. For example:
ok ' input .calls
Called from input at 1e248d8
Called from io at 1e24ac0
Called from install-console at 1e33598
Called from install-console at 1e33678
ok
|
see
, used in the form:
see
thisword
displays a "pretty-printed" listing of the source for
thisword
(without the comments, of course). For example:
ok see see
: see
′ [′] (see) catch if
drop
then
;
ok
|
For more details on the use of
see
, refer to
Using patch and (patch)
.
sifting
takes a string from the input stream and searches vocabularies in the dictionary search order to find every command name that contains the specified string as shown in the following screen.
ok sifting input
In vocabulary options
(1e333f8) input-device
In vocabulary forth
(1e2476c) input (1e0a9b4) set-input (1e0a978) restore-input
(1e0a940) save-input (1e0a7f0) more-input? (1e086cc) input-file
ok
|
words
displays all the visible word names in the dictionary, starting with the most recent definition. If a node is currently selected (as with
dev
), the list produced by
words
is limited to the words in that selected node.
Compiling Data Into the Dictionary
The commands listed in
TABLE 4-16
control the compilation of data into the dictionary.
TABLE 4-16 Dictionary Compilation Commands
Command
|
Stack Diagram
|
Description
|
,
|
( n -- )
|
Places a number in the dictionary.
|
c,
|
( byte -- )
|
Places a byte in the dictionary.
|
w,
|
( word -- )
|
Place a 16-bit number in the dictionary.
|
l,
|
( quad -- )
|
Places a 32-bit number in the dictionary.
|
[
|
( -- )
|
Begins interpreting.
|
]
|
( -- )
|
Ends interpreting, resumes compilation.
|
allot
|
( n -- )
|
Allocates
n
bytes in the dictionary.
|
>body
|
( xt -- a-addr )
|
Finds the data field address from the execution token.
|
body>
|
( a-addr -- xt )
|
Finds the execution token from the data field address.
|
compile
|
( -- )
|
Compiles the next word at run time. (Recommend using
postpone
instead.)
|
[compile] name
|
( -- )
|
Compiles the next (immediate) word. (Recommend using
postpone
instead.)
|
here
|
( -- addr )
|
Address of top of dictionary.
|
immediate
|
( -- )
|
Marks the last definition as immediate.
|
to
name
|
( n -- )
|
Installs a new action in a
defer
word or
value
.
|
literal
|
( n -- )
|
Compiles a number.
|
origin
|
( -- addr )
|
Returns the address of the start of the Forth system.
|
patch
new-word
old-word
word-to-patch
|
( -- )
|
Replaces
old-word
with
new-word
in
word-to-patch
.
|
(patch)
|
( new-n old-n xt -- )
|
Replaces
old-n
with
new-n
in word indicated
by
xt
.
|
postpone
name
|
( -- )
|
Delays the execution of the word name.
|
recurse
|
( ... -- ??? )
|
Compiles a recursive call to the word being compiled.
|
recursive
|
( -- )
|
Makes the name of the colon definition being compiled visible in the dictionary, and thus allows the name of the word to be used recursively in its own definition.
|
state
|
( -- addr )
|
Variable that is non-zero in compile state.
|
The dictionary compilation commands listed in
TABLE 4-17
are available only on 64-bit OpenBoot implementations.
TABLE 4-17 64-Bit Dictionary Compilation Commands
Command
|
Stack Diagram
|
Description
|
x,
|
( o -- )
|
Compiles an octlet,
o
, into the dictionary (doublet-aligned).
|
Displaying Numbers
Basic commands to display stack values are shown in
TABLE 4-18
.
TABLE 4-18 Basic Number Display
Command
|
Stack Diagram
|
Description
|
.
|
( n -- )
|
Displays a number in the current base.
|
.r
|
( n size -- )
|
Displays a number in a fixed width field.
|
.s
|
( -- )
|
Displays contents of data stack.
|
showstack
|
( ??? -- ??? )
|
Executes
.s
automatically before each
ok
prompt.
|
noshowstack
|
( ??? -- ??? )
|
Turns off automatic display of the stack before each
ok
prompt
|
u.
|
( u -- )
|
Displays an unsigned number.
|
u.r
|
( u size -- )
|
Displays an unsigned number in a fixed width field.
|
The
.s
command displays the entire stack contents without disturbing them. It can usually be used safely for debugging purposes. (This is the function that
showstack
performs automatically.)
Changing the Number Base
You can print numbers in a specific number base or change the operating number base using the commands in
TABLE 4-19
.
TABLE 4-19 Changing the Number Base
Command
|
Stack Diagram
|
Description
|
.d
|
( n -- )
|
Displays
n
in decimal without changing base.
|
.h
|
( n -- )
|
Displays
n
in hex without changing base.
|
base
|
( -- addr )
|
Variable containing number base.
|
decimal
|
( -- )
|
Sets the number base to 10.
|
d#
number
|
( -- n )
|
Interprets
number
in decimal; base is unchanged.
|
hex
|
( -- )
|
Set the number base to 16.
|
h#
number
|
( -- n )
|
Interprets
number
in hex; base is unchanged.
|
The
d#
and
h#
commands are useful when you want to input a number in a specific base without explicitly changing the current base. For example:
ok decimal (Changes base to decimal)
ok 4 h# ff 17 2
4 255 17 2 ok
|
The
.d
and
.h
commands act like "
.
" but display the value in decimal or hexadecimal, respectively, regardless of the current base setting. For example:
ok hex
ok ff . ff .d
ff 255
|
Controlling Text Input and Output
This section describes text and character input and output commands.
TABLE 4-20
lists commands to control text input.
TABLE 4-20 Controlling Text Input
Command
|
Stack Diagram
|
Description
|
(
ccc
)
|
( -- )
|
Creates a comment. Conventionally used for stack diagrams.
|
\
rest-of-line
|
( -- )
|
Treats the rest of the line as a comment.
|
ascii
ccc
|
( -- char )
|
Gets numerical value of first ASCII character of next word.
|
accept
|
( addr len1 -- len2 )
|
Gets a line of edited input from the console input device; stores at
addr
.
len1
is the maximum allowed length.
len2
is the actual length received.
|
expect
|
( addr len -- )
|
Gets and displays a line of input from the console; stores at
addr
. (Recommend using
accept
instead.)
|
key
|
( -- char )
|
Read a character from the console input device.
|
key?
|
( -- flag )
|
True if a key has been typed on the console input device.
|
parse
|
( char -- str len )
|
Parses text from the input buffer delimited by
char
.
|
parse-word
|
( -- str len )
|
Skips leading spaces and parses text from the input buffer delimited by white space.
|
word
|
( char -- pstr )
|
Collects a string delimited by
char
from the input buffer and places it as a packed string in memory at
pstr
. (Recommend using
parse
instead.)
|
Comments are used with Forth source code (generally in a text file) to describe the function of the code. The
(
(open parenthesis) is the Forth word that begins a comment. Any character up to the closing parenthesis
)
is ignored by the Forth interpreter. Stack diagrams are one example of comments using
(
.
Note Note - Remember to follow the ( with a space, so that it is recognized as a Forth word.
|
\
(backslash) indicates a comment terminated by the end of the line of text.
key
waits for a key to be pressed, then returns the ASCII value of that key on the stack.
ascii
, used in the form
ascii
x
, returns on the stack the numerical code of the character
x
.
key?
looks at the keyboard to see whether the user has recently typed any key. It returns a flag on the stack:
true
if a key has been pressed and
false
otherwise. See
Conditional Flags
for a discussion on the use of flags.
TABLE 4-21
lists general-purpose text display
commands.
TABLE 4-21 Displaying Text Output
Command
|
Stack Diagram
|
Description
|
.
" ccc"
|
( -- )
|
Compiles a string for later display.
|
(cr
|
( -- )
|
Moves the output cursor back to the beginning of the current line.
|
cr
|
( -- )
|
Terminates a line on the display and goes to the next line.
|
emit
|
( char -- )
|
Displays the character.
|
exit?
|
( -- flag )
|
Enables the scrolling control prompt:
More [<space>,<cr>,q] ?
The return flag is
true
if the user wants the output to be terminated.
|
space
|
( -- )
|
Displays a
space
character.
|
spaces
|
( +n -- )
|
Displays
+n
spaces.
|
type
|
( addr +n -- )
|
Displays the
+n
characters beginning at
addr
.
|
cr
sends a carriage-return or linefeed sequence to the console output device. For example:
ok 3 . 44 . cr 5 .
3 44
5
ok
|
emit
displays the letter whose ASCII value is on the stack.
ok ascii a
61 ok 42
61 42 ok emit emit
Ba
ok
|
TABLE 4-22
shows commands used to manipulate text strings.
TABLE 4-22 Manipulating Text Strings
Command
|
Stack Diagram
|
Description
|
",
|
( addr len -- )
|
Compiles an array of bytes from
addr
of length
len
, at the top of the dictionary as a packed string.
|
" ccc"
|
( -- addr len )
|
Collects an input stream string, either interpreted or compiled.
|
."
ccc
"
|
|
Displays the string
ccc
.
|
.
( ccc)
|
( -- )
|
Displays the string
ccc
immediately.
|
-trailing
|
( addr +n1 -- addr +n2 )
|
Removes trailing spaces.
|
bl
|
( -- char )
|
ASCII code for the space character; decimal 32.
|
count
|
( pstr -- addr +n )
|
Unpacks a packed string.
|
lcc
|
( char -- lowercase-char )
|
Converts a character to lowercase.
|
left-parse-string
|
( addr len char -- addrR lenR addrL lenL )
|
Splits a string at
char
(which is discarded).
|
pack
|
( addr len pstr -- pstr )
|
Stores the string
addr
,
len
as a packed string at
pstr
.
|
upc
|
( char -- uppercase-char )
|
Converts a character to uppercase.
|
Some string commands specify an address (the location in memory where the characters reside) and a length (the number of characters in the string). Other commands use a packed string or
pstr
, which is a location in memory containing a byte for the length, immediately followed by the characters. The stack diagram for the command indicates which form is used. For example,
count
converts a packed string to an address-length string.
The command
."
is used in the form:
."
string
"
. It outputs text immediately when it is encountered by the interpreter. A
"
(double quotation mark) marks the end of the text string. For example:
ok : testing 34 . ." This is a test" 55 . ;
ok
ok testing
34 This is a test55
ok
|
When " is used outside a colon definition, only two interpreted strings of up to 80 characters each can be assembled concurrently. This limitation does not apply in colon definitions.
Redirecting Input and Output
Normally, OpenBoot uses a keyboard for command input, and a frame buffer with a connected display screen for display output. (Server systems may use an ASCII
terminal connected to a serial port.
For more information on how to connect a terminal to your system, see your system's installation manual.) You can redirect the input, the output, or both, to a serial port. This may be useful, for example, when debugging a frame buffer.
TABLE 4-23
lists commands you can use to redirect input and output.
TABLE 4-23 I/O Redirection Commands
Command
|
Stack Diagram
|
Description
|
input
|
( device -- )
|
Selects device, for example
ttya
,
keyboard
, or
device-specifier
, for subsequent input.
|
io
|
( device -- )
|
Selects device for subsequent input and output.
|
output
|
( device -- )
|
Selects device, for example
ttya
,
keyboard
, or
device-specifier
, for subsequent output.
|
The commands
input
and
output
temporarily change the current devices for input and output. The change takes place as soon as you enter a command; you do not
have to reset your system. A system reset or power cycle causes the input and output devices to revert to the default settings specified in the NVRAM configuration variables
input-device
and
output-device
. These variables can be modified, if needed (see
Chapter 3
).
input
must be preceded by one of the following:
keyboard
,
ttya
,
ttyb
, or
device-specifier
text string. For example, if input is currently accepted from the keyboard, and you want to make a change so that input is accepted from a terminal connected to the serial port
ttya
, type:
At this point, the keyboard becomes nonfunctional (except perhaps for
Stop-A
), but any text entered from the terminal connected to
ttya
is processed as input. All commands are executed as usual.
To resume using the keyboard as the input device,
use the terminal keyboard
to type:
Similarly,
output
must be preceded by one of the following:
screen
,
ttya
, or
ttyb
or
device-specifier
. For example, if you want to send output to a serial port instead of the normal display screen, type:
The screen does
not
show the answering
ok
prompt, but the terminal connected to the serial port shows the
ok
prompt and all further output as well.
io
is used in the same way, except that it changes both the input and output to the specified place. For example:
Generally, the argument to
input
,
output
, and
io
is a
device-specifier
, which can be either a device path name or a device alias.
The device must be specified as a Forth string, using double quotation marks
(
"
), as shown in the two examples below:
or:
In the preceding examples,
keyboard
,
screen
,
ttya
, and
ttyb
are predefined Forth words that put their corresponding device alias string on the stack.
Command-Line Editor
OpenBoot implements a command line editor (similar to EMACS, a common text editor), some optional extensions and an optional history mechanism for the user interface. You use these tools to re-execute previous commands without retyping them, to edit the current command line to fix typing errors, or to recall and change previous commands.
TABLE 4-24
lists line-editing commands available at the
ok
prompt.
TABLE 4-24 Command-Line Editor Keystroke Commands
Keystroke
|
Description
|
Return (Enter)
|
Finishes editing of the line and submits the entire visible line to the interpreter regardless of the current cursor position.
|
Control-B
|
Moves backward one character.
|
Escape B
|
Moves backward one word.
|
Control-F
|
Moves forward one character.
|
Escape F
|
Moves forward one word.
|
Control-A
|
Moves backward to beginning of line.
|
Control-E
|
Moves forward to end of line.
|
Delete
|
Erases previous character.
|
Backspace
|
Erases previous character.
|
Control-H
|
Erases previous character.
|
Escape H
|
Erases from beginning of word to just before the cursor, storing erased characters in a save buffer.
|
Control-W
|
Erases from beginning of word to just before the cursor, storing erased characters in a save buffer.
|
Control-D
|
Erases next character.
|
Escape D
|
Erases from cursor to end of the word, storing erased characters in a save buffer.
|
Control-K
|
Erases from cursor to end of line, storing erased characters in a save buffer.
|
Control-U
|
Erases entire line, storing erased characters in a save buffer.
|
Control-R
|
Retypes the line.
|
Control-Q
|
Quotes next character (allows you to insert control characters).
|
Control-Y
|
Inserts the contents of the save buffer before the cursor.
|
The command-line history extension saves previously-typed commands in an EMACS-like command history ring that contains at least 8 entries. Commands may be recalled by moving either forward or backward around the ring. Once recalled, a command may be edited and/or resubmitted (by typing the Return key). The command-line history extension keys are:
TABLE 4-25 Command-Line History Keystroke Commands
Keystroke
|
Description
|
Control-P
|
Selects and displays the previous command in the command history ring.
|
Control-N
|
Selects and displays the next command in the command history ring.
|
Control-L
|
Displays the entire command history ring.
|
The command completion extension enables the system to complete long Forth word names by searching the dictionary for one or more matches based on the already-typed portion of a word. When you type a portion of a word followed by the command completion keystroke, Control-Space, the system behaves as follows:
The command completion extension keys are:
TABLE 4-26 Command Completion Keystroke Commands
Keystroke
|
Description
|
Control-Space
|
Completes the name of the current word.
|
Control-?
|
Displays all possible matches for the current word.
|
Control-/
|
Displays all possible matches for the current word.
|
Conditional Flags
Forth conditionals use flags to indicate true/false values. A flag can be generated in several ways, based on testing criteria. The flag can then be displayed from the stack with the word ".", or it can be used as input to a conditional control command. Control commands can cause one behavior if a flag is true and another behavior if the flag is false. Thus, execution can be altered based on the result of a test.
A
0
value indicates that the flag value is
false
. A
-1
or any other nonzero number indicates that the flag value is
true
.
TABLE 4-27
lists commands that perform relational tests, and leave a
true
or
false
flag result on the stack.
TABLE 4-27 Comparison Commands
Command
|
Stack Diagram
|
Description
|
<
|
( n1 n2 -- flag )
|
True if
n1
<
n2
.
|
<=
|
( n1 n2 -- flag )
|
True if
n1
<=
n2
.
|
<>
|
( n1 n2 -- flag )
|
True if
n1
is not equal to
n2
.
|
=
|
( n1 n2 -- flag )
|
True if
n1
=
n2
.
|
>
|
( n1 n2 -- flag )
|
True if
n1
>
n2
.
|
>=
|
( n1 n2 -- flag )
|
True if
n1
>=
n2
.
|
0<
|
( n -- flag )
|
True if
n
< 0.
|
0<=
|
( n -- flag )
|
True if
n
<= 0.
|
0<>
|
( n -- flag )
|
True if
n
<> 0.
|
0=
|
( n -- flag )
|
True if
n
= 0 (also inverts any flag).
|
0>
|
( n -- flag )
|
True if
n
> 0.
|
0>=
|
( n -- flag )
|
True if
n
>= 0.
|
between
|
( n min max -- flag )
|
True if
min
<=
n
<=
max
.
|
false
|
( -- 0 )
|
The value
FALSE
, which is 0.
|
true
|
( -- -1 )
|
The value
TRUE
, which is -1.
|
u<
|
( u1 u2 -- flag )
|
True if
u1
<
u2
, unsigned.
|
u<=
|
( u1 u2 -- flag )
|
True if
u1
<=
u2
, unsigned.
|
u>
|
( u1 u2 -- flag )
|
True if
u1
>
u2
, unsigned.
|
u>=
|
( u1 u2 -- flag )
|
True if
u1
>=
u2
, unsigned.
|
within
|
( n min max -- flag )
|
True if
min
<=
n
<
max
.
|
>
takes two numbers from the stack, and returns
true
(
-1
) on the stack if the first number was greater than the second number, or returns
false
(
0
) otherwise. An example follows:
ok 3 6 > .
0 (3 is not greater than 6)
ok
|
0=
takes one item from the stack, and returns
true
if that item was 0 or returns
false
otherwise. This word inverts any flag to its opposite value.
Control Commands
The following sections describe words used in a Forth program to control the flow of execution.
The if-else-then Structure
The commands
if
,
else,
and
then
provide a simple control structure.
The commands listed in
TABLE 4-28
control the flow of conditional execution.
TABLE 4-28 if...else...then Commands
Command
|
Stack Diagram
|
Description
|
if
|
( flag -- )
|
Executes the following code when flag is
true
.
|
else
|
( -- )
|
Executes the following code when flag is
false
.
|
then
|
( -- )
|
Terminates
if...else...then
.
|
The format for using these commands is:
flag if
(do this if true)
then
(continue normally)
|
or
flag if
(do this if true)
else
(do this if false)
then
(continue normally)
|
The
if
command consumes a flag from the stack. If the flag is
true
(nonzero), the commands following the
if
are performed. Otherwise, the commands (if any) following the
else
are performed.
ok : testit ( n -- )
] 5 > if ." good enough "
] else ." too small "
] then
] ." Done. " ;
ok
ok 8 testit
good enough Done.
ok 2 testit
too small Done.
ok
|
Note Note - The ] prompt reminds you that you are part way through creating a new colon definition. It reverts to ok after you finish the definition with a semicolon.
|
The case Statement
A high-level
case
command is provided for selecting alternatives with multiple possibilities. This command is easier to read than deeply-nested
if...then
commands.
TABLE 4-29
lists the conditional case commands.
TABLE 4-29 case Statement Commands
Command
|
Stack Diagram
|
Description
|
case
|
( selector -- selector )
|
Begins a
case...endcase
conditional.
|
endcase
|
( selector -- )
|
Terminates a
case...endcase
conditional.
|
endof
|
( -- )
|
Terminates an
of...endof
clause in a case...endcase
|
of
|
( selector test-value -- selector | {empty} )
|
Begins an
of...endof
clause in a
case
conditional.
|
Here is a simple example of a
case
command:
ok : testit ( testvalue -- )
] case
] 0 of ." It was zero " endof
] 1 of ." It was one " endof
] ff of ." Correct " endof
] -2 of ." It was minus-two " endof
] ( default ) ." It was this value: " dup .
] endcase ." All done." ;
ok
ok 1 testit
It was one All done.
ok ff testit
Correct All done.
ok 4 testit
It was this value: 4 All done.
ok
|
Note Note - The (optional) default clause can use the test value which is still on the stack, but should not remove it (use the phrase "dup ." instead of "."). A successful of clause automatically removes the test value from the stack.
|
The begin Loop
A
begin
loop executes the same commands repeatedly until a certain condition is satisfied. Such a loop is also called a conditional loop.
TABLE 4-30
lists commands to control the execution of conditional loops.
TABLE 4-30 begin (Conditional) Loop Commands
Command
|
Stack Diagram
|
Description
|
again
|
( -- )
|
Ends a
begin...again
infinite loop.
|
begin
|
( -- )
|
Begins a
begin...while...repeat
,
begin...until
,
or
begin...again
loop.
|
repeat
|
( -- )
|
Ends a
begin...while...repeat
loop.
|
until
|
( flag -- )
|
Continues executing a
begin...until
loop until
flag
is true.
|
while
|
( flag -- )
|
Continues executing a
begin...while...repeat
loop while
flag
is true.
|
There are two general forms:
begin any commands...flag until
|
and
begin any commands... flag while
more commands repeat
|
In both cases, the commands in the loop are executed repeatedly until the proper flag value causes the loop to be terminated. Then execution continues normally with the command following the closing command word (
until
or
repeat
).
In the
begin...until
case,
until
removes a flag from the top of the stack and inspects it. If the flag is
false
, execution continues just after the
begin
, and the loop repeats. If the flag is
true
, the loop is exited.
In the
begin...while...repeat
case,
while
removes a flag from the top of the stack and inspects it. If the flag is
true
, the loop continues by executing the commands just after the
while
. The
repeat
command automatically sends control back to
begin
to continue the loop. If the flag is
false
when
while
is encountered, the loop is exited immediately; control goes to the first command after the closing
repeat
.
An easy mnemonic for either of these loops is: If true, fall through.
A simple example follows.
ok begin 4000 c@ . key? until (repeat until any key is pressed)
43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43
ok
|
The loop starts by fetching a byte from location 4000 and displaying the value. Then, the
key?
command is called, which leaves a
true
on the stack if the user has pressed any key, and
false
otherwise. This flag is consumed by
until
and, if the value is
false
, then the loop continues. Once a key is pressed, the next call to
key?
returns
true
, and the loop terminates.
Unlike many versions of Forth, the user interface allows the interactive use of loops and conditionals -- that is, without first creating a definition.
The do Loop
A
do
loop (also called a counted loop) is used when the number of iterations of the loop can be calculated in advance. A
do
loop normally exits just
before
the specified ending value is reached.
TABLE 4-31
lists commands to control the execution of counted loops.
TABLE 4-31 do (Counted) Loop Commands
Command
|
Stack Diagram
|
Description
|
+loop
|
( n -- )
|
Ends a
do...+loop
construct; adds
n
to loop index and returns to
do
(if
n
< 0, index goes from
start
to
end
inclusive).
|
?do
|
( end start -- )
|
Begins
?do...loop
to be executed 0 or more times. Index goes from
start
to
end
-1 inclusive. If
end
=
start
, loop is not executed.
|
?leave
|
( flag -- )
|
Exits from a
do...loop
if
flag
is non-zero.
|
do
|
( end start -- )
|
Begins a
do...loop
. Index goes from
start
to
end
-1 inclusive.
Example:
10 0 do i . loop
(prints 0 1 2...d e f).
|
i
|
( -- n )
|
Leaves the loop index on the stack.
|
j
|
( -- n )
|
Leaves the loop index of the next outer enclosing loop on the stack.
|
leave
|
( -- )
|
Exits from
do...loop
.
|
loop
|
( -- )
|
End of
do...loop
.
|
The following screen shows several examples of how loops are used.
ok 10 5 do i . loop
5 6 7 8 9 a b c d e f
ok
ok 2000 1000 do i . i c@ . cr i c@ ff = if leave then 4 +loop
1000 23
1004 0
1008 fe
100c 0
1010 78
1014 ff
ok : scan ( byte -- )
] 6000 5000 (Scan memory 5000 - 6000 for bytes not equal to the specified byte)
] do dup i c@ <> ( byte error? )
] if i . then ( byte )
] loop
] drop ( the original byte was still on the stack, discard it )
] ;
ok 55 scan
5005 5224 5f99
ok 6000 5000 do i i c! loop (Fill a region of memory with a stepped pattern)
ok
ok 500 value testloc
ok : test16 ( -- ) 1.0000 0 ( do 0-ffff ) (Write different 16-bit values to a location)
] do i testloc w! testloc w@ i <> ( error? ) (Also check the location)
] if ." Error - wrote " i . ." read " testloc w@ . cr
] leave ( exit after first error found ) (This line is optional)
] then
] loop
] ;
ok test16
ok 6000 to testloc
ok test16
Error - wrote 200 read 300
ok
|
Additional Control Commands
TABLE 4-32
contains descriptions of additional program execution control commands.
TABLE 4-32 Program Execution Control Commands
Command
|
Stack Diagram
|
Description
|
abort
|
( -- )
|
Aborts current execution and interprets keyboard commands.
|
abort
"
ccc
"
|
( abort? -- )
|
If
abort?
is true, displays message and aborts.
|
eval
|
( addr len -- )
|
Interprets Forth source from
addr
len
.
|
execute
|
( xt -- )
|
Executes the word whose execution token is on the stack.
|
exit
|
( -- )
|
Returns from the current word. (Cannot be used in counted loops.)
|
quit
|
( -- )
|
Same as
abort
, but leaves stack intact.
|
abort
causes immediate termination and returns control to the keyboard.
abort"
is similar to
abort
but is different in two respects.
abort"
removes a flag from the stack and only aborts if the flag is
true
. Also,
abort"
prints any desired message when the abort takes place.
eval
takes a string from the stack (specified as an address and a length). The characters in that string are then interpreted as if they were entered from the keyboard. If a Forth text file has been loaded into memory (see
Chapter 5
), then
eval
can be used to compile the definitions contained in the file.
OpenBoot 4.x Command Reference Manual
|
816-1177-10
|
|
Copyright
© 2002, Sun Microsystems, Inc. All rights reserved.