XXIIVV

Uxntal is a stack-machine assembly language targeting the Uxn virtual machine.

Let's Begin.

( Uxn uses 32 opcodes, a working stack and a return stack
	[a b c] Stack
	[PC]    Program Counter
	[M]     Memory
	[D]     Devices
	[rs]    Return Stack )

LIT a b c M[PC+1] EQU a b?c             LDZ a b M[c8]      ADD a b+c
INC a b c+1       NEQ a b!c             STZ a {M[c8]=b}    SUB a b-c
POP a b           GTH a b>c             LDR a b M[PC+c8]   MUL a b*c
NIP a c           LTH a b<c             STR a {M[PC+c8]=b} DIV a b/c
SWP a c b         JMP a b {PC+=c}       LDA a b M[c16]     AND a b&c
ROT b c a         JCN a {(b8)PC+=c}     STA a {M[c16]=b}   ORA a b|c
DUP a b c c       JSR a b {rs.PC PC+=c} DEI a b D[c8]      EOR a b^c
OVR a b c b       STH a b {rs.c}        DEO a {D[c8]=b}    SFT a b>>c8l<<c8h

( Each opcode has 3 possible modes
	[2] The short mode operates on shorts instead of bytes
	[r] The return mode operate on the return stack
	[k] The keep mode operates without consuming items )

#12 #34 ADD ( 46 )
#12 #34 ADDk ( 12 34 46 )

( Modes can be combined )

#1234 #5678 ADD2k ( 12 34 56 78 68 ac )

( New words can be created using macros )

%MOD2 { DIV2k MUL2 SUB2 }
#1234 #0421 MOD2 ( 01 b0 )

( -------------------------------------------------------------------------- )

( All programming in Unxtal is done by manipulating the stacks )

#12 ( working-stack: 12 )
#3456 ( working-stack: 34 56 )
#12 STH ( return-stack: 12 )
LIT2r 1234 ( return-stack: 12 34 )
LIT2r 1234 STH2r ( working-stack: 12 34 )

( Shorts are made of two bytes, each byte can be manipulated )

#1234 SWP ( 34 12 )
#1234 #5678 SWP2 ( 56 78 12 34 )
#1234 #5678 SWP ( 12 34 78 56 )

( Each byte can be removed )

#1234 POP ( 12 )
#1234 NIP ( 34 )

( -------------------------------------------------------------------------- )

( Comparison will push 01 for true, 00 for false )

#12 #34 EQU ( 00 )
#12 #12 EQU ( 01 )

( Comparing shorts will also push a byte )

#1234 #7856 LTH2 ( 01 )

( Skip a piece of code when two bytes are not equal )

#12 #34 NEQ ,skip JCN
	( body )
	@skip

( -------------------------------------------------------------------------- )

( Uxn's memory contains 65536 bytes )

#12 #0200 STA ( 0x0200=12 )
#3456 #0400 STA2 ( 0x0400=34, 0x0401=56 )
#0400 LDA2 ( 34 56 )

( The zero-page can be addressed with a single byte )

#1234 #80 STZ2 ( 0x0080=12, 0x0081=34 )
#80 LDZ2 ( 12 34 )

( Devices are ways for Uxn to communicate with the outside world )

%Console/write { #18 }
%EMIT { Console/write DEO }
#31 EMIT ( print ascii "1" to console )

( A label is equal to a position in the program )

@parent ( defines a label "parent" )
	&child ( defines a sublabel "parent/child" )

( Label positions can be pushed on stack )

;parent ( push the absolute position, 2 bytes )
,parent ( push the relative position, 1 byte )
.parent ( push the zero-page position, 1 byte )

( -------------------------------------------------------------------------- )

( Create a for-loop )

#3a #30
@loop
	DUP EMIT ( print "123456789" to console )
	INC GTHk ,loop JCN
POP2

( Create a while-loops )

;word
@while
	LDAk EMIT ( print "vermillion" to console )
	INC2 LDAk ,while JCN
POP2
BRK
@word "vermillion $1

( Subroutines can be jumped to with JSR2, and returned from with JMP2r )

;word ;print-word JSR2
BRK

@print-word ( word* -- )
	@while
		LDAk EMIT
		INC2 LDAk ,while JCN
	POP2
JMP2r
@word "cerulean

( -------------------------------------------------------------------------- )

( Arithmetic macros )

%MOD  { DIVk MUL SUB }
%MOD2 { DIV2k MUL2 SUB2 }
%MIN2 { LTH2k JMP SWP2 POP2 }
%MAX2 { GTH2k JMP SWP2 POP2 }

( Signed macros )

%LTS2 { #8000 STH2k ADD2 SWP2 STH2r ADD2 GTH2 }
%GTS2 { #8000 STH2k ADD2 SWP2 STH2r ADD2 LTH2 }

( Binary macros )

%ROL { DUP #07 SFT SWP #10 SFT ADD }
%ROR { DUP #70 SFT SWP #01 SFT ADD }
%ROL2 { DUP2 #0f SFT2 SWP2 #10 SFT2 ADD2 }
%ROR2 { DUP2 #f0 SFT2 SWP2 #01 SFT2 ADD2 }

( A clever hack )

%PC { #00 JSR STH2r }

Try the HTML5 Interpreter in your browser.

Incoming: uxntal