An assembler for the uxn virtual computer, written in Chicken scheme.
Update README and slight cleanup.
Moved to Chicken 5, added local nvim config.
More work on subroutines and vectors.



You can also use your local clone with git send-email.


An assembler for the uxn virtual computer embedded in chicken scheme.

I wrote this to be an alternative to the uxnasm assembler for folks who might want to play with the language by manipulating their uxntal in scheme. Some ideas might be to automate generating data blocks in scheme, or writing higher level constructs on top of uxntal.


Code is written in a scheme list, with sublists for certain assembler features. For the most part, opcodes have the same mnemonics as the uxnasm assembler, with the exception that they are all lower case, and the ordering for modifiers is different. A few differences form regular uxntal as supported by uxnasm:

  • short, keep, and return mode are always added in the order k, r, 2.
    • For instance, addkr2 vs ADD2kr
  • Raw bytes and shorts are enclosed in lists starting with either byte, short, or data. For instance:
    • (byte #xf0) places the byte f0 in to the ROM.
    • (short #xf012) places the short f012 in to the ROM.
    • (data #xf0 #x12 #x34) places the bytes f0, 12, and 34 in to the ROM in that order.
  • LIT opcodes must be manually specified. For instance, lit (byte #x45) would push #x45 to the data stack, and lit2 (short #xF0F0) would push the hsort #xF0F0 to the data stack.
  • Regular labels are defined with (label label-name). They may be referenced in the following ways:
    • (label-ref-abs label-name) places the short the label represents into the ROM.
    • (label-ref-rel label-name) places a byte with the distance to the label relative to the current program counter (equivalent of uxnasm's , rune.
  • Zero page labels are defined with (zplabel label-name value) and may be referenced as regular labels. For instance, (zplabel global-var #xf0) would create a label called global-var with the value f0. These can be used for addresses or constants.
  • Sublabels are defined with (sublabel label-name) and must be defined sometime after a regular label is defined.
  • The current address of assembly may be set using (set-addr #x0100) (equivalent of *=$0100 in many 6502 assemblers).
  • Memory segments may be defined and manipulated via (push-segment name) and (pop-segment).
  • Subroutines may be defined via (defsub name op1 op2 ... ). Subroutines create an implicit label name and add implict jmpr2 and brk opcodes at the end. They may be called using (call name).
  • Vectors are like subroutines, but only have an implicit brk at the end. They are defined with (defvec name op1 op2 ...).


The file uxn_asm.scm provides a module which exports one function: uxn-assemble. This function takes a list of assembler as described above, and returns a u8 bytevector of the ROM.