https://wiki.xxiivv.com/site/uxntal.html XXIIVV * turquoise * secd * chip8 * uxn * uxntal * varvara * uxntal syntax * uxntal stacks * uxntal opcodes * uxntal modes * uxntal immediate * uxntal memory * uxntal devices * uxntal software Rostiger's Uxn ZineRostiger's Uxn Zine Tal is the programming language for the Uxn virtual machine. [uxn] Uxn programs are written in a stack-based flavor of assembly designed especially for this virtual machine. TAL files are human-readable source files, ROM files are uxn-compatible binary program files; applications that transform TAL files into ROM files are called Assemblers. To get started, equip yourself with an emulator and assembler for your system. * Download emulator & assembler, 40kb * Introduction to Uxntal, online book Uxntal Syntax In concatenative programming, there are no precedence rules, the calculations are merely performed in the sequence in which they are presented. The order with which elements come off a stack is known as last in, first out. In the stack a b c, the c item was the last to be added, and will be the first to be removed. #01 DUP ADD #03 MUL06 Example Program The first line of our example begins with the padding token |10 which moves the program writing location to the address 0x0010, and will allow us to define @labels, &sublabels and $length for the various ports of the Console device so that we can reference them in our code by name. To learn more, see Uxntal Structs. The following program is not the most efficient way of printing a string, merely a length of code that covers most basic functionalities of the language. The second segment moves the program location to the address 0x0100, which is where the first page of memory ends, and where all Uxn programs begin. Next, inside parentheses, is a comment with the arrow symbol indicating that the following operation is a vector. To learn more, see Uxntal Notation. The ;hello-world token pushes an absolute address, made of two bytes, on the stack pointing to a series of letters in memory. Values pushed to the stack in this fashion are called a literals, as opposed to values stored in memory which are called immediates. Next, we call the @print-text routine. Both &while and @while are ways to define labels, but using the ampersand rune will prefix our new label with the name of the last parent label, creating @print-text/while. Next, the LDAk opcode loads the byte in memory found at that address; the ASCII letter H, to the top of the stack. The k-mode indicates that the operation will not consume the address. That value is sent to the device port #18, defined by our Console label and its sublabels, with DEO which prints that character to the terminal. We then increment the absolute address found on top of the stack with INC2, we use the 2-mode because the address is made of two bytes. We load the byte at the incremented value and do a conditional immediate jump with ?&while for as long as the item on the stack is not zero. We use POP2 to remove the address on the stack and keep the stack clean at the end of the subroutine. Lastly, we encounter JMP2r which jumps to the absolute address that we left on the return stack when we entered the @print-text subroutine. [uxn] To summarize, uppercased opcodes are reserved words, lowercase hexadecimal numbers are bytes and shorts, parentheses are comments, curlies are lambdas, and square brackets are used for organization. Runes are special characters at the start of a word that define its meaning, here is the full list: +------------------------------------------------------------+ | Padding Runes | Literal Hex Rune | |-----------------------------------+------------------------| |||absolute |$|relative |#|literal hex | |-----------------------------------+------------------------| | Label Runes | Ascii Runes | |-----------------------------------+------------------------| |@|parent |&|child |"|raw ascii | |-----------------------------------+------------------------| | Addressing Runes | Pre-processor Runes | |-----------------------------------+------------------------| |,|literal relative |_|raw relative |%|macro-define|~|include| |-+-----------------+-+-------------+-+------------+-+-------| |.|literal zero-page|-|raw zero-page| | | | | |-+-----------------+-+-------------+-+------------+-+-------| |;|literal absolute |=|raw absolute | | | | | |-----------------------------------+-+------------+-+-------| | Immediate Runes | | | | | |-----------------------------------+-+------------+-+-------| |!|jmi |?|jci | | | | | +------------------------------------------------------------+ Uxntal stacks All programming in Unxtal is done by manipulating the working stack, and return stack. Each stack contains 256 bytes, items from one stack can be moved into the other. Here are some stack primitives and their effect: +------------------------------------+ |POP|a b |Discard top item. | |---+-------+------------------------| |NIP|a c |Discard second item. | |---+-------+------------------------| |SWP|a c b |Move second item to top.| |---+-------+------------------------| |ROT|b c a |Move third item to top. | |---+-------+------------------------| |DUP|a b c c|Copy top item. | |---+-------+------------------------| |OVR|a b c b|Copy second item to top.| +------------------------------------+ A byte is a number between 0-255(256 values), a short is made of two bytes, each byte in a short can be manipulated individually: #0a #0b POP 0a #12 #3456 NIP 12 56 #1234 DUP 12 34 34 The two stacks are circular, and so have no depths, to pop an empty stack does not trigger an error, but merely means to set the stack pointer to 255. There are no invalid programs, any sequence of bytes is a potential Uxn program. To learn more about detecting unintended stack effects, see programs validation. Uxntal Opcodes Uxn has 64kb of memory, 16 devices, 2 stacks of 256 bytes, 5-bits opcodes and 3 modes. The list below show the standard opcodes and their effect on a given stack a b c. PC: Program Counter, |: Return Stack, [M]: Memory, [D+*]: Device Memory, a8: a byte, a16: a short. LIT a b c [PC] JCI a b (c8){PC+=[PC]} JMI a b c {PC+=[PC]} JSI a b c | PC {PC+=[PC]} BRK a b c EQU a b==c LDZ a b [c8] ADD a b+c INC a b c+1 NEQ a b!=c STZ a {[c8]=b} SUB a b-c POP a b GTH a b>c LDR a b [PC+c8] MUL a b*c NIP a c LTH a b>c8l< ) ( set vector ) ;on-mouse .Mouse/vector DEO2 BRK @on-mouse ( -> ) ( read state ) .Mouse/state DEI ?&on-touch BRK &on-touch ( -> ) ( A mouse button is pressed ) BRK For example, the address stored in the Mouse/vector ports points to a part of the program to be evaluated when the cursor is moved, or a button state has changed. [varvara] Uxntal Utilities Here's a list of small self-hosted development tools: * Uxnfor is a formatter that standardize the source code, this is the formatting style used across the Uxntal documentation. * Uxnlin is a linter and peephole optimizer that reveals optimizations in opcode sequences, it's also a good way to reflect about the language in novel ways. * Uxnbal is a program validator that warns when routines do not match their definitions. * Uxnrea turns a rom file and its symbols file, back into a textual source code. * UxnUtils is a repository of varied small programs written in Uxntal. incoming left dexe noodle theme bifurcan catclock yufo programming languages brainfuck gly format ufx format ulz format proquints uxn uxntal types uxntal reference uxntal alphabet drifblim bicycle beetbug about computer oscean arvelie CreativeCommonsWebringMerveillesNoNazis!UxnPoweredDevine Lu Linvega (c) 2023 -- BY-NC-SA 4.0