running uxn

work-in-progress appendix for the uxn tutorial: instruction on how to run varvara/uxn.

desktop bundles

in order to run varvara locally and off the grid we need to get an appropriate emulator.

the 100R website allows you to download the emulators for major desktop systems; these come bundled with a selection of programs in the form of "roms":

100R — uxn

depending on your system, you might be able to launch the emulator (Uxn32.exe or uxnemu) with a double-click, or you might need to use a console to navigate to its location and run it:

# in Linux/Unix:
$ ./uxnemu launcher.rom 
# ./uxnemu -1x

that's it! you will be greeted by a screen corresponding to the launcher rom.

from there you will be able to run the other roms by clicking them, pressing Enter, or the Ctrl key. you can go back to the launcher by pressing the F4 key.

uxnemu controls

these are the controls you can use within uxnemu, regardless of the rom that you are running:

building from source

alternatively, you can get the sources from the uxn git repository, where you will also find the building and installation instructions:

~rabbits/uxn - sourcehut git

the toolchain

depending on your system, you might see that besides uxnemu or uxn32 there are a couple of other programs, uxnasm and uxncli.

during this journey we will be writing our programs in uxntal, the assembly language for uxn machines.

these programs will have to be assembled in order to become roms that we will be able to run with an emulator.

using left and the launcher

uxn and the tools that have been built around it allow us to learn and develop completely within the system.

for instance, when you run the emulator you will see that you can open a program called left: a text editor!

100R — left

open it, as we will write our first program there!

first of all, rename the file you are working on. you can use the visual menu or press Ctrl + r, then delete the current filename, replace it with hello.tal, and press Enter to confirm.

now write the following program:

( hello.tal )
|0100 LIT 68 LIT 18 DEO

save it using the visual menu or Ctrl + s, and then go back to the launcher by pressing F4.

you will see now that the listing in the launcher includes your newly created file, hello.tal!

note that this is a text file only, and it's not a rom yet. however, the launcher makes it very easy to convert it to a rom, or more precisely, to assemble it!

just click the hello.tal, or use the arrow keys to reach it and then press Enter or Ctrl: if everything went alright you will see that a hello.tal.rom file appears!

additionally, note that the accompanying console will print something like:

on-reset	0x0100
0x0002 lines of source code.
0x002e bytes of heap used, 0xa35d bytes free

if there are errors during assembly, you will see them there.

now that you have hello.tal.rom you can run it from the launcher as any other rom!

when you run it you will see that the screen will be cleared and that the console will show the output of our program:


interesting, what is happening?

i invite you to try replacing the 68 in the code with, for example, 65.

to do that you'll have to open left again, rename the file to hello.tal so that it opens it, modify the file, save it, return to the launcher, assemble, and then run again!

using another text editor and uxn tools

alternatively, you can use your favorite text editor and the uxn programs to replicate what we just did from within uxnemu.

you can write hello.tal using your text editor, and then save it along the other files bundled with the emulator:

( hello.tal )
|0100 LIT 68 LIT 18 DEO

once you have the file, we can assemble and run it from the console:

$ ./uxnasm hello.tal hello.rom && ./uxnemu hello.rom

a black window will open, and in the console we will see an output that looks like the following:

Assembled hello.rom in 5 bytes(0.01% used), 0 labels, 0 macros.
Loaded hello.rom

as we saw in the previous case, the last 'h' we see is the output of our program.

feel free to use any of these approaches, either working completely from within uxnemu, or using your own tools and the uxn programs.

everything that follows in this journey regarding uxntal is completely agnostic to the tooling you use!

one instruction at a time

we just ran the following program written in uxntal:

( hello.tal )
|0100 LIT 68 LIT 18 DEO

now let's analyze it!

the first line is a comment: comments are enclosed between parenthesis and there have to be spaces in between them. similar to other programming languages, comments are ignored by the assembler.

the second line has several things going on:

reading the program from left to right, we can see the following behavior:

and what is the i/o device with address 18?

looking at the devices table from the varvara reference, we can see that the device with address 1 in the high nibble is the console (standard input and output), and that the column with address 8 in the low nibble corresponds to the "write" port.


so, device address 18 corresponds to "console write", or standard output.

our program is sending the hexadecimal value 68 (character 'h') to standard output!

you can see the hexadecimal values of the ascii characters in the following table:

ascii table

raw numbers

note that the raw numbers that we wrote, 0100, 18 and 68, are written in hexadecimal using either 4 digits corresponding to two bytes, or 2 digits corresponding to one byte.

in uxntal we can only write numbers that are 2 or 4 hexadecimal digits long. if, for example, we were only interested in writing a single hexadecimal digit, we would have to include a 0 at its left.

assembled rom

when we assembled our program, we saw that it was 5 bytes in size.

we can confirm it using the wc (word count) program:

$ wc -c hello.rom
5 hello.rom

for the curious (like you!), we could use a tool like hexdump to see its contents:

$ hexdump -C hello.rom
00000000  80 68 80 18 17                         |.h...|

80 is the "opcode" corresponding to LIT, and 17 is the opcode corresponding to DEO. and there they are our 68 and 18!

so, effectively, our assembled program matches one-to-one the instructions we just wrote!

actually, we could have written our program using these hexadecimal numbers, i.e. the machine code, and it would have worked the same way:

( hello.tal )
|0100 80 68 80 18 17 ( LIT 68 LIT 18 DEO )

maybe not the most practical way of programming, but indeed a fun one :)

you can find the opcodes of all 36 instructions in the uxntal reference

XXIIVV - uxntal

incoming links