Lichen assembler manual

Ignored Typographical Features

The following features are stripped out by the assembler. They exist for the convenience of programmers.


comments are prefixed with '//'

// this is a valid comment
12 12 add drop // add 12 + 12 and then discard the answer 

Square brackets

Square brackets are treated as white space. Use them to group immediates for instructions that have them. This makes the code easier to understand.

calli [myProcedure]


Whitespace is ignored by the assembler. This includes spaces, tabs, carriage returns and linefeeds. Line endings and tab preferences are irrelevant. Use whichever meets your requirements.



A label is pointer to somewhere in the program. Its address is the instruction that immediately follows it. Labels begin with a name and end with ':'.
Labels can have their own line

 main: // all by myself 

Or they can be on the same line as the instruction they are bound to.

 main: swap 

They can also prefix a block of code

 main: swap drop roll 

The colon doesn't need to be attached to the label

 mainProcedure : // this is valid
 anotherProcedure      :   // also valid 
: // you can do this too but it's ugly 


An open parenthesis specifies a procedure. A close parenthesis denotes the end of said procedure. A procedure's name is the first block of text in the block. Procedure definitions are not nestable.

// this defines a procedure
(myProcedure 1 2 add drop)

// this is how you call a procedure

// this places the address of the procedure onto the data stack

You can call this function anywhere in the source. Doing so simply inserts the code in the instruction stream. The open parenthesis is translated into 'push [proc address] call' and the close parenthesis is translated into 'ret'. If the procedure has defined local variables, those variables are allocated on the locals stack upon invocation and deallocated upon exit. Their addresses are negative offsets from the locals stack pointer.

If you want to return the address of a procedure instead of calling it ( useful for implement callbacks) you may prefix the procedure's name with the “address of” operator '&'. This is the only valid context in which that operator can be used. This operator may be surrounded by white space, i.e. it does not have to be directly attached to the procedure name (this is also valid usage for all operators).


Loops are defined with curly braces. There is only one loop construct in lichen and it has no configuration. i.e. all loops are infinite.

The following control words are valid within loops:

control word description
break Exit the loop
breakt Exit the loop if A is true
breakf Exit the loop if A is false
continue jump back to the top of the loop
continuet jump back to the top of the loop if A is true
continuef jump back to the top of the loop if A is false

This loops forever:

{ }

This is equivalent to for(i=0;i<10;i++){} in c:

dw i 0x0 {
    *i 10 equal breakt
    i incm   

You can define variables inside a loop. Variables defined within a loop are local to their respective loop.

dw i 0x0 {
    dw stuff 0x0
    *i 10 equal breakt
    // (some more code using stuff)
    i incm   
// stuff no longer exists
// i still exists because it was defined higher in the hierarchy

You can have loops within loops:

dw x 0x0 { 
   *x 10 equal breakt
   dw y 0x0 {
      *y 10 equal breakt
      // ( do some procedure with x and y )
      y incm
   x incm

How loops work: The assembler generates labels for the start and end of the loop. Control words are translated into jumps to those labels.

If you define variables in a loop, those variables will be allocated on the locals stack when the loop begins and they will be deallocated upon termination of the loop. Variables defined in a loop are assigned their initial value at the beginning of each loop iteration regardless of where they are defined within the loop.



Variables begin with a name followed by a variable code and then an initial value.
Variable codes

code width description
db 1B define byte
dw 2B define word
ddw 4B define double word
ds variable define string nul terminated
dsn variable define string, not nul terminated


// a word named counter initialized to 0
dw counter 0x0 

// a message terminated with a nul character
ds hello "Hello world"


Constants are defined by declaring 'const' followed by a name and then a numerical value. If the value of the constant exceeds the width of the container it's being used with, the value will be truncated and the assembler will emit an error message.

const maxVal 0xFF
shoved 0 // we start at zero ...
again: shoved 1 add equal maxVal halt ncall again // and loop until we hit our constant, then halt


Globals are variables and constants defined outside of procedures and loops. Globals are accessible by name anywhere in the program hierarchy. Global variables are statically allocated in memory.


Locals are variables and constants defined within procedures and loops. Locals are allocated on the locals stack upon entry of a procedure or loop. They are deallocated upon exit of their corresponding procedure or loop.


Library files may be included with the include directive. The file name of the library proceeds the include directive. Only procedures and constants are valid within a library file.


 include sfrMap.lib


Specifying a file dumps its raw contents into the assembly stream. This is a convenient way to embed binary data into a program. A file is defined by declaring 'file', the name of the file and then a label. When you specify a file in your code, the assembler inserts the address where the data from the file is embedded. A file is essentially a variable length variable.

file picture.tiff myCat 
myCat // the address of the picture myCat is placed on the data stack 

Obviously you need to be careful of where you declare a file because its contents end up exactly where you define it.

    2 2 add file data.txt myData add // this would be a disaster
// this is a better way to do it
ncall main
file data.txt mydata
main :
    2 2 add

Reserved tokens

word description
const a constant
file a file
include include library
db variable declaration
dw variable declaration
ddw variable declaration
dsn variable declaration
ds variable declaration
* dereference word
** dereference byte
& get the address of a procedure
[ grouping
] grouping
( procedure declaration
) end of procedure specifier
{ start of loop
} end of loop
> jump
>> call
++ increment word memory
-- decrement word memory
break loop control
breakt loop control
breakf loop control
continue loop control
continuet loop control
continuef loop control

Command Line Arguments


lasm [options] -o [output file] [input file]



Default value : 512

Specifies the size of the locals stack in bytes.


Default value : No

say 'Yes' if you want the compiler to generate an assembler listing for you.

Theory of Operation


Syntax Highlighting Mode for Emacs
(require 'generic-x)

  '( "add" "sub" "div" "mul" "sadd" "ssub" "sdiv" "smul" 
     "and" "or" "xor" "not" "bsl" "bsr" "sbsl" "sbsr" 
     "bsnl" "bsnr" "sbsnl" "sbsnr" "rotl" "rotr"
     "nop" "inc" "dec" "drop" "dropa" "swap" "roll" 
     "a2d" "d2a" "dup" "push" "pushb" "spushb" "pusha"
     "store" "storei" "storeb" "fetch" "fetchb" "sfetchb"
     "incm" "incmb" "decm" "decmb" "bfetch" "bfetchb"
     "equal" "less" "great" "equalm" "lessm" "greatm" "equalmb"
     "lessmb" "greatmb" "equali" "lessi" "greati" "sless"
     "sgreat" "slessm" "sgreatm" "slessmb" "slessi" "sgreati" 
     "call" "callt" "calli" "callit" "jmp" "jmpt" "jmpi" "jmpit"
     "ret" "halt" "reset" )
    ("*" . 'font-lock-builtin-face)
    ("(" . 'font-lock-warning-face)
    (")" . 'font-lock-warning-face)
    (">" . 'font-lock-builtin-face)
    (">>" . 'font-lock-builtin-face)
    ("++" . 'font-lock-builtin-face)
    ("const" . 'font-lock-variable-name-face)
    ("file" . 'font-lock-variable-name-face)
    ("include" . 'font-lock-variable-name-face)
    ("db" . 'font-lock-variable-name-face)
    ("dw" . 'font-lock-variable-name-face)
    ("ddw" . 'font-lock-variable-name-face)
    ("dsn" . 'font-lock-variable-name-face)
    ("ds" . 'font-lock-variable-name-face)
    (":" . 'font-lock-builtin-face))
  "lichen assembler mode"
fpga_stack_machine_assembler.txt · Last modified: 2013/03/31 01:49 by millerb
Public Domain Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0