Dictionary
List of words defined in arch-specific boot code and core words.
Glossary
Stack notation: "<stack before> -- <stack after>". Rightmost is
top of stack (TOS). For example, in "a b -- c d", b is TOS
before, d is TOS after. "R:" means that the Return Stack is
modified.
Some words have a variable stack signature, most often in pair
with a flag. These are indicated with "?" to tell that the argu-
ment might not be there. For example, "-- n? f" means that "n"
might or might not be there.
Some words consume contents from input and this is indicated by
"x", "y" and "..." elements next to the word itself, not in the
stack signature. For example, ": x ... ;" means that the word
":" will consume an element "x" (which is usually explained in
the description), followed by an arbitrary length of contents,
which is ended by ";".
Word references (wordref): When we say we have a "word
reference", it's a pointer to a word's entry point. That is,
making native jump to the address contained in the wordref will
execute the word.
For example, the address that "' DUP" puts on the stack is a
word reference to DUP.
"*I*" in description indicates an IMMEDIATE word.
"*A*" in description indicates A register usage.
Symbols
Across words, different symbols are used in different contexts,
but we try to be consistent in their use. Here's their defini-
tions:
! - Store
@ - Fetch
$ - Initialize
^ - Arguments in their opposite order
< - Input
> - 1. Pointer in a buffer 2. Opposite of "<".
( - Lower boundary
) - Upper boundary
' - Address of
* - Word indirection (pointer to word)
? - "Is it ...?" or "do ... if flag"
[...] - Indicates immediateness
Placement of those symbols is often important. In I/O-related
words for example, symbold to the left of the words refer to
input and to the right, output. For "?", placement at the right
refer to the first form, placement at the left refer to the
second form.
System variables
See doc/usage for details. These ones have a "'" pair:
BLK> Currently selected Block.
CURRENT Address of the last word of the dictionary.
HERE Addr of next available space in dict
IN( Beginning of the input buffer.
IN> Current pos in input buffer.
These ones are addresses and must be accessed with @ and !:
IOERR Nonzero when an IO error occurred in some drivers.
NL 1 or 2 chars to spit during NL>, MSB first. If MSB is
0, it's ignored.
LN< Routine that feeds lines to the interpreter. Generally
RDLN.
BLKDTY Whether current block is dirty
Entry management
'? x -- f Find x it in dict. If found, f=1. Otherwise, f=0.
' x -- w Push addr of word x to w. If not found, aborts.
['] x -- *I* Like "'", but spits the addr as a number
literal. If not found, aborts.
FIND sa sl -- w? f
Find "sa sl" in dict. If found, w=wordref, f=1.
Otherwise, f=0.
FORGET x -- Rewind the dictionary (both CURRENT and HERE) up
to x's previous entry.
Defining words
: x ... ; -- Define a new word.
ALIAS x y -- Define an alias y with a starting value of x
CREATE x -- Create cell named x. Doesn't allocate.
CODE x -- Define a new native word.
[COMPILE] x -- *I* Compile word x and write it to HERE.
IMMEDIATE words are *not* executed.
COMPILE x -- *I* Meta compiles: write wordrefs that will
compile x when executed.
CONSTS ... n -- Creates n new constants. See usage.txt.
VALUE x n -- Creates cell x that when called pushes its
value.
VALUES ... n -- Create a serie of n values. See usage.txt
DOER -- See doc/usage
DOES> -- See doc/usage
IMMEDIATE -- Flag the latest defined word as immediate.
LITN n -- Write number n as a literal.
Code generation
JMPi! n a -- len Write a native jump to n at address a
CALLi! n a -- len Write a native call to n at address a
"len" is the length in bytes of the written binary contents.
Flow
Note that flow words can only be used in definitions. In the
INTERPRET loop, they don't have the desired effect because each
word from the input stream is executed immediately. In this
context, branching doesn't work.
f IF A ELSE B THEN: if f is true, execute A, if false, execute
B. ELSE is optional.
[IF] .. [THEN]: Meta-IF. Works outside definitions. No [ELSE].
BEGIN .. f UNTIL: if f is false, branch to BEGIN.
BEGIN .. AGAIN: Always branch to BEGIN.
n >R BEGIN .. NEXT: Loop n times.
( -- *I* Comment. Ignore input until ")" is read.
\ -- *I* Line comment. Ignore input until EOL.
[ -- *I* Begin interpretative mode. In a definition,
execute words instead of compiling them.
] -- End interpretative mode.
ABORT -- Resets PS and RS and returns to interpreter.
ABORT" ..." -- *I* Compiles a ." followed by a ABORT.
EXECUTE a -- Execute wordref at addr a
INTERPRET -- Main interpret loop.
LEAVE -- In a BEGIN..NEXT, exit at the next NEXT call.
QUIT -- Reset RS, return to interpreter prompt.
Parameter Stack
DROP a --
DUP a -- a a
?DUP DUP if a is nonzero
NIP a b -- b
OVER a b -- a b a
ROT a b c -- b c a
ROT> a b c -- c a b
SWAP a b -- b a
TUCK a b -- b a b
2DROP a a --
2DUP a b -- a b a b
Return Stack
>R n -- R:n Pops PS and push to RS
R> R:n -- n Pops RS and push to PS
R@ -- n Copy RS TOS to PS
R~ R:n -- Drop RS TOS
Stacks meta
.S -- *A* Prints stack information as well as the contents
of PS.
SCNT -- n Size of PS in bytes
RCNT -- n Size of RS in bytes
Memory
@ a -- n Set n to value at address a
! n a -- Store n in address a
, n -- Write n in HERE and advance it.
+! n a -- Increase number at addr a by n.
[]= a1 a2 u -- f Compare u bytes between a1 and a2. Returns
true if equal.
[C]? c a u -- i Look for c in the u bytes at addr a. If
found, return index i. Otherwise, i=-1.
C@ a -- c Set c to byte at address a
C@+ a -- a+1 c Fetch c from a and inc a.
C! c a -- Store byte c in address a
C!+ c a -- a+1 Store byte c in a and inc a.
C, b -- Write byte b in HERE and advance it.
nC, n -- Parse next n words and write them as
bytes.
ALLOT n -- Move HERE by n bytes.
ALLOT0 n -- *A* ALLOT and fill with zero.
FILL a n b -- *A* Fill n bytes at addr a with val b.
L, n -- Write n in little-endian regardless of
native endianess (L=LSB first)
M, n -- Write n in big-endian regardless of
native endianess (M=MSB first)
MOVE a1 a2 u -- *A* Copy u bytes from a1 to a2, starting
with a1, going up.
MOVE, a u -- *A* Copy u bytes from a to HERE.
TO -- Next VALUE call will be in write mode.
See doc/usage.
A register
>A n -- A:n
A> A:n -- n A:n
R>A R:n -- A:n
A>R A:n -- R:n A:n
A+ A:n -- A:n+1
A- A:n -- A:n-1
AC@ A:a -- c A:a
AC! c A:a -- A:a
AC@+ A:a -- c A:a+1
AC!+ c A:a -- A:a+1
Arithmetic / Bits
+ a b -- a+b
- a b -- a-b
-^ a b -- b-a
* a b -- a*b
/ a b -- a/b
<> n1 n2 -- l h Sort n1 and n2, highest on TOS.
<< n -- n Shift n left by one bit
<<8 n -- n Shift n left by 8 bits
>> n -- n Shift n right by one bit
>>8 n -- n Shift n right by 8 bit
L|M n -- lsb msb Split n word in 2 bytes, MSB on TOS
1+ n -- n+1
1- n -- n-1
MAX n1 n2 -- hi
MIN n1 n2 -- lo
MOD a b -- a%b
/MOD a b -- r q r:remainder q:quotient
AND a b -- a&b
OR a b -- a|b
XOR a b -- a^b
LSHIFT n u -- n Shift n left by u bits
RSHIFT n u -- n Shift n right by u bits
Logic
= n1 n2 -- f Push true if n1 == n2
< n1 n2 -- f Push true if n1 < n2
> n1 n2 -- f Push true if n1 > n2
>= n1 n2 -- f Push true if n1 >= n2
<= n1 n2 -- f Push true if n1 <= n2
0< n -- f Push true if n-as-signed is negative
0>= n -- f Push true if n-as-signed is positive
NOT f -- f Push the logical opposite of f. Always 0 or 1.
Strings and lines
See doc/usage for the concepts of strings and lines.
S" ..." -- Read following characters and write to HERE as
a string literal.
LNLEN a -- n Return length of line at a, the line ending at
the last visible char of it.
S= sa1 sl1 sa2 sl2 -- f
Returns whether string s1 == s2.
Number formatting
. n -- Print n in its decimal form
.x n -- Print n's LSB in hex form. Always 2
characters.
.X n -- Print n in hex form. Always 4 characters.
Numbers are never considered negative.
"-1 .X" --> ffff
FMTD n a -- sa sl Formats n as decimal in memory and return
its string as "sa sl".
FMTx n a -- sa sl Formats n's LSB in hex form.
FMTX n a -- sa sl Formats n in hex form.
I/O
," ..." -- Write ... to HERE
." ..." -- *I* Compiles string literal ... followed by a
call to STYPE.
CURWORD -- sa sl Yield the last read word (see WORD).
EMIT c -- Spit char c to output stream
EMITLN a -- *A* EMIT line at addr a
IN< -- c Read one char from buffered input, if end of
input is reached, read new line.
IN<? -- c-or-0 Read from buffered input if its end hasn't
been reached, 0 otherwise.
IN( -- a Beginning of input buffer.
IN) -- a End of the input buffer, exclusive.
IN$ -- Flush input buffer
KEY? -- c? f Polls the keyboard for a key. If a key is
pressed, f is true and c is the char. Other-
wise, f is false and c is *not* on the stack.
KEY -- c Get char c from direct input.
NL> -- Emit newline
PARSE sa sl -- n? f *A*
Parses string s as a number and push the result in n if
it can be parsed, with f=1. Otherwise, push f=0.
PC! c a -- Spit c to port a
PC@ a -- c Fetch c from port a
SPC> -- Emit space character
STYPE sa sl -- *A* EMIT all chars of string.
WAITW sa sl -- Call WORD until we get the same string as
sa sl.
WORD -- sa sl Read one word from buffered input and push it.
That word is a string (begins with a length
byte).
WORD! sa sl -- The next WORD call will not read from input
and yield this string instead.
These ASCII consts are defined:
EOT BS CR LF SPC
KEY? and EMIT are aliases to (key?) and (emit) (see doc/drivers)
KEY is a loop over KEY?.
NL> spits CRLF by default, but can be configured to spit an
alternate newline char. See impl.txt.
BLK subsystem (see doc/blk)
\S -- Interrupts LOAD of current block.
BLK( -- a Beginning addr of blk buf.
BLK) -- a Ending addr of blk buf.
BLK@ n -- *A* Read block n into buffer and make n active.
BLK! -- *A* Write currently active block, if dirty.
COPY s d -- *A* Copy contents of s block to d block.
FLUSH -- Write current block to disk if dirty and inval-
idates current block cache.
LIST n -- *A* Prints the contents of the block n on
screen in the form of 16 lines of 64 columns.
LOAD n -- *A* Interprets Forth code from block n
LOADR n1 n2 -- *A* Load block range between n1 and n2,
inclusive.
WIPE -- *A* Empties current block
Note: Most BLK words don't actually use the A register them-
selves, but we want to allow BLK drivers to make usage of it,
so you *should* guard yourself again A changes when using those.
RX/TX subsystem (see doc/rxtx)
RX<? -- c? f If a char is available on RX, return it in c
with f=1. Otherwise, f=0.
RX< -- c Block until a char is available in RX.
RX<< -- Consume RX<? and drop result until there's
nothing to be received.
RX[ -- Replace KEY? with RX<?.
]RX -- Put back the old KEY? handler.
TX> c -- Spit c to TX, blocking until it can do it.
TX[ -- Replace EMIT with TX>.
]TX -- Put back the old EMIT handler.
Other
BOOT -- Boot back to a fresh system.
CRC16 c b -- c Computes byte b into c, a 16-bit CRC with a
$1021 polynomial (XMODEM CRC).
DUMP n a -- *A* Prints n bytes at addr a in a hexdump
format. Prints in chunks of 8 bytes. Doesn't do
partial lines. Output is designed to fit in 32
columns.
NOOP -- Do nothing.
TICKS n -- Wait for approximately n*100 microseconds.
Don't use with n=0.
Loaders
These words load the related application from blocks:
ARCHM Arch-specific loader words and macros
ED Block Editor
VE Visual Editor
ME Memory Editor
RSH Remote shell and XMODEM implementation
XCOMP Cross-compilation tools
Kernel internals
Some words from the kernel are designed to be internal but
ended up being used in "userland". Let's document them:
_bchk n -- n Checks whether n is a valid 8-bit signed
branching offset, that is, in the range -128
to 127. If not, abort with "br ovfl".
This page generated at 2024-12-01 21:05:03 from documentation in CollapseOS snapshot 20230427.