Uxn Sticker picture
15C06 — Uxn Sticker

Uxn is a 8-bit virtual stack machine.

The goal of the project is to create a portable virtual machine capable of hosting various tools and games. Its design should have, at most, the complexity of the 6502, and its assembly language be both human-readable, and allow for the creation of mouse and keyboard driven applications. The distribution of Uxn projects should be akin to downloading a rom for a console emulator.

The thin layer that is the "Uxn emulator" should be the only part of this project needing to be ported to make the device available on any new platform. For that reason, Uxn has to be designed with a focus on portability such that it welcomes anyone to try their hand at building their own implementation. The current emulator is 400 lines of C89 over SDL2 as only dependecy.

While the aim is to distribute assembled binaries, to respect the philosophy of the tool's ecosystem, the assembly sources should be packaged alongside the rom. Similarly to the emulator, the assembler should be extremely simplistic in its implementation as to not discourage re-implementations. The C89 assembler is also 400 lines with no dependencies.



CoreProgram Counter1 short
Literal Counter1 byte
Balance Counter1 byte
Status Register1 byte
StacksWorking Stack256 bytes
Return Stack256 bytes
MemoryRAM65536 bytes

Status Register

The status register is distributed as follows, it shares the same byte as the register selector. The halt flag is used by the BRK instruction is stops the cpu, the short flag is used for 16-bits operations, the cond flag is set when an instruction requires a non-zero stack value to operate, and the sign flag is set when the operator should use signed integers.

| | | +---- Halt  0x01
| | +------ Short 0x02
| +-------- Sign  0x04
+---------- Cond  0x08

Return Stack

The CPU can tunnel through 128 subroutines and find its way back with the return stack, the opcode to jump into to a subroutine is JSR, the opcode to return from a subroutine is RTS. An item on the work stack can be temporarily sent to the return stack with WSR and returned with RSW. Uxn will automatically keep a count of the items that were moved from one stack to the other, the program will halt if trying to return or jump to a subroutine before all the items transferered have been returned.


There are 32 opcodes, each opcode occupies 5 bits of a byte, the remaining 3 are used to select the addressing mode of the values in the stack.


Opcodes pointing to addresses in memory pull 16-bits from the stack at a time, and are represented like [a b], where the a and b bytes are combined into a short. For example, [0xAB 0xCD] points to the memory address 0xABCD.

I/O Stack
0x00BRK 0x10POPa
0x01--- 0x11DUPaa a
0x02LITlc 0x12SWPa bb a
0x03JMP[a b] 0x13OVRa b ca b a
0x04JSR[a b]rs 0x14ROTa b cb c a
0x05RTSrs 0x15---
0x06LDR[a b]c 0x16WSRars
0x07STRa [b c] 0x17RSWrsa
Logic Arithmetic
0x08--- 0x18ADDa bc
0x09--- 0x19SUBa bc
0x0a--- 0x1aMULa bc
0x0b--- 0x1bDIVa bc
0x0cANDa bc 0x1cEQUa bc
0x0dXORa bc 0x1dNEQa bc
0x0eROLa bc 0x1eLTHa bc
0x0fRORa bc 0x1fGTHa bc

lc stands for literal counter, rs for return stack, mp stands for memory pointer.


Here is an example of the assembly language that prints hello world to stdout.

( hello world )

&Console { pad 8 char 1 byte 1 short 2 }

|0100 @RESET 
	,text1 ,print-label JSR
	,text2 ,print-label JSR
	#ab =dev/console.byte
	#cdef =dev/console.short


@print-label ( text )

		DUP2 LDR =dev/console.char               ( write pointer value to console )
		#0001 ADD2                               ( increment string pointer )
		DUP2 LDR #00 NEQ ,print-label-loop ROT JMP? POP2  ( while *ptr!=0 goto loop )


@text1 [ Hello World 0a00 ] ( store text with a linebreak and null byte )
@text2 [ Welcome to UxnVM 0a00 ]

|c000 @FRAME
|d000 @ERROR 

|FF00 ;dev/console Console

|FFF0 .RESET .FRAME .ERROR ( vectors )
|FFF8 [ 13fd 1ef3 1bf2 ] ( palette )

Literal mode

Each operation is 1 byte(8-bits). To differentiate operations from numbers, the LIT opcode (0x02) toggles the literal mode for a length of 1 evaluation, the 16-bits mode LIT2 opcode (0x22) toggles the literal mode for a length of 2 evaluations.

,120x02 0x12
,abcd0x22 0xab 0xcd
.abcd0xab 0xcd

Short mode

Operations can be used on 16-bits at a time(2 bytes), by using the SHORT2 mode.

0x12 0x34 0x56 0x78SWP2
0x56 0x78 0x12 0x34ADD2
0x68 0xac

Conditional mode

Every operation has the potential to conditionally operate by using the COND? mode, in the following branching example, the value 0xff will be added to the stack if the first value is greater than the second, otherwise 0xee will be added.

ROT is used to bring the result of GTH to the top of the stack, POP2 is used after the conditional JMP to remove the address of the label @there that is left on the stack.

#06 #05 GTH ,there ROT JMP? POP2

@here ( when lesser or equal )

@there ( when greater )


There is a maximum of 16 devices accessible via the last page in memory, each device have 8 bytes to read from, and 8 bytes to write to. Devices are external systems to the Uxn code such as the screen, the mouse, the keyboard, etc.

read 0x00write 0x08
ff30controllerbuttons bytenil
ff40keyboardkey bytenil
button byte
chord byte


A device that works like a NES controller, each button is a bit from a single byte(ff30). To check if the up button is pressed:

,no-up ~dev/ctrl.buttons #f0 AND #10 NEQ JMP? POP2
	( handle when up is pressed )

Sprite Engine

Uxn's sprite device makes it easier to draw characters and icons to the screen by sending a memory address, a position and a color byte.

The sprite device's color byte defines the layer to draw on, the type of data to draw, and the colors to use.

high nibblelow nibble(icn)
— Submit an edit to uxn.htm(212 lines)
An operating system running on UxnVM. picture
goki — An operating system running on UxnVM.

incoming(6): tools nasu gyo goki ayatori forth

Last update on 15E04, edited 16 times. +64/101fh -----|