Collapse OS Documentation Browser


asm/ code/ hw/ algo.txt arch.txt avr.txt blk.txt blksrv.txt bootstrap.txt cross.txt design.txt dict.txt dis.txt drivers.txt ed.txt emul.txt faq.txt grid.txt grok.txt impl.txt intro.txt me.txt mspan.txt ps2.txt rxtx.txt sdcard.txt sega.txt selfhost.txt spi.txt usage.txt wordtbl.txt


List of words defined in arch-specific boot code and core words.


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

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.


Across words, different symbols are used in different contexts,
but we try to be consistent in their use. Here's their defini-

! - 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
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
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.


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


@        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
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


=    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
.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.


," ..." --        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
WORD!   sa sl --  The next WORD call will not read from input
                  and yield this string instead.

These ASCII consts are defined:

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,
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.


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
NOOP    --       Do nothing.
TICKS   n --     Wait for approximately n*100 microseconds.
                 Don't use with n=0.


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".

Collapse OS and its documentation are created by Virgil Dupras and licensed under the GNU GPL v3.

This documentation browser by James Stanley. Please report bugs on github or to

This page generated at 2024-07-15 21:05:03 from documentation in CollapseOS snapshot 20230427.