We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

2 undigits, 121 undigytes

From Esolang
Jump to navigation Jump to search

2 undigits, 121 undigytes is another assembly-like programming language sort of like 7 heptits, 49 heptytes and 3 pentits, 25 pentytes made by User:Mutasimos.

When I saw a septenary programming language after I made a quinary programming language, I felt like going further. Since using a composite number as the base would make it a bit easier (octal would just make it binary-ish) I picked the next prime number, 11. Maybe a tridecimal language will be made soon?

Terminology

Undigit
A single base-11 / undecimal digit. We use these characters for the 11 digits: 0123456789X.
Undigyte
Two undigits, and also the word size of the machine.
The 0u prefix
Throughout this page the 0u prefix is added to numbers if it is written in undecimal.

ISA

Registers
Undecimal Register What it is Initial value
0u0 ra General purpose A register 0u00
0u1 rb General purpose B register 0u00
0u2 rc General purpose C register 0u00
0u3 rd General purpose D register 0u00
0u4 re General purpose E register 0u00
0u5 sp Stack pointer register 0uXX
0u6 bp Base pointer register 0u00
Instructions
Opcode Instruction What it does
0u00 nop Do nothing (NOP)
0u01 hlt Halt the program
0u02 mov [dst] [src] Sets [dst] to the value in [src]
0u03 mov [dst] [imm] Sets [dst] to [imm]
0u04 add [dst] [src] Adds the value in [src] to [dst] (can wrap)
0u05 sub [dst] [src] Subtracts the value in [src] from [dst] (can wrap)
0u06 mul [dst] [src] Multiplies [dst] with [src] (can wrap)
0u07 div [dst] [src] Divides [dst] with [src] (crashes on division by zero)
0u08 mod [dst] [src] Remainder of division of [dst] with [src] (crashes on division by zero)
0u09 add [dst] [imm] Adds [imm] to [dst] (can wrap)
0u0X sub [dst] [imm] Subtracts [imm] from [dst] (can wrap)
0u10 mul [dst] [imm] Multiplies [imm] with [src] (can wrap)
0u11 div [dst] [imm] Divides [dst] with [imm] (crashes on division by zero)
0u12 mod [dst] [imm] Remainder of division of [dst] with [imm] (crashes on division by zero)
0u13 Reserved
0u14 jmp [abs] Jumps to the specified absolute address
0u15 ldr [dst] [abs] Loads value from memory into [dst] where address is [abs]
0u16 ldr [dst] [reg] Loads value from memory into [dst] where address is in [reg]
0u17 str [abs] [src] Store value from [src] into memory where address is [abs]
0u18 str [reg] [src] Store value from [src] into memory where address is in [reg]
0u19 push [src] Pushes register [src] onto the stack
0u1X pop [dst] Pops register [dst] off the stack
0u20 call [abs] Calls the specified absolute address, pushing the next instruction's address onto the stack
0u21 ret Pops the new instruction pointer off the stack
0u22 jiz [reg] [abs] If [reg] is 0, go to [abs]
0u23 jnz [reg] [abs] If [reg] is not 0, go to [abs]
0u24 jeq [a] [b] [abs] If [a] register equals [b] register, go to [abs]
0u25 jne [a] [b] [abs] If [a] register does not equal [b] register, go to [abs]
0u26 jlt [a] [b] [abs] If [a] register is less than [b] register, go to [abs] (unsigned comparison)
0u27 jgt [a] [b] [abs] If [a] register is greater than [b] register, go to [abs] (unsigned comparison)
0u28 jlti [a] [b] [abs] If [a] register is less than [b] register, go to [abs] (signed comparison)
0u29 jgti [a] [b] [abs] If [a] register is greater than [b] register, go to [abs] (signed comparison)
0u2X outu [reg] Writes [reg] as undecimal number, prefixed with 0u to standard out
0u30 outd [reg] Writes [reg] as decimal number, without any prefix to standard out
0u31 outs [ptr_reg] [len_reg] Writes the number of undigytes given by [len_reg] from [ptr_reg] according to the text encoding
0u32 outs [ptr_reg] [len_imm] Writes the number of undigytes given by [len_imm] from [ptr_reg] according to the text encoding
0u33 - 0uXX Reserved

Whenever an instruction takes two registers, the first register is the higher undigit and the second register is the lower undigit of an entire undigyte, allowing for 2 undigytes instead of 3 undigytes of memory. For example, assembling "mov ra, rb" into machine code would give us "0u02 0u01".

Text Encoding

0 1 2 3 4 5 6 7 8 9 X
0 null lf cr nbsp ¢ £ ¥ § « »
1 sp ! " # $ % & ' ( ) *
2 + , - . / : ; [ = ] ?
3 @ [ \ ] ^ _ ` { | } ~
4 A B C D E F G H I J K
5 L M N O P Q R S T U V
6 W X Y Z ¡ ¿ · µ ¬
7 a b c d e f g h i j k
8 l m n o p q r s t u v
9 w x y z ¼ ½ ¾ ¹ ² ³ ¦
X 0 1 2 3 4 5 6 7 8 9 ±

Examples

The starting undigytes in memory in the examples given here are separated by spaces, and the ones which start with 0u are in undecimal and if not they are in decimal. There is also comments which start with ";".

Hello, world!

0u03 0u00 0u07 ; mov ra, msg (0u07)
0u32 0u00 14   ; outs ra, 14
0u01           ; hlt

0u47 0u74 0u80 ; msg: du "Hello, World!\n"
0u80 0u83 0u21
0u10 0u60 0u83
0u86 0u80 0u73
0u11 0u01

truth-machine

0u15 0u00 0u09 ; ldr ra, val (0u09)
0u30 0u00      ; loop: outd ra
0u23 0u00 0u03 ; jnz ra, loop (0u03)
0u01           ; hlt

;; Change this value to 1 for the other outcome
0              ; val: du 0

Fibonacci sequence

0u03 0u04 0u29 ; mov re, newline (0u29)
0u03 0u00 0    ; mov ra, 0
0u03 0u01 1    ; mov rb, 1

0u30 0u00      ; loop: outd ra
0u32 0u04 1    ; outs re, 1
0u02 0u20      ; mov rc, ra
0u02 0u01      ; mov ra, rb
0u04 0u12      ; add rb, rc
0u26 0u12 0u23 ; jlt rb, rc, drain (0u23)  -- if rb < rc, it wrapped
0u14 0u09      ; jmp loop (0u09 = 9)

0u30 0u00      ; drain: outd ra   -- print the last still-valid term
0u32 0u04 1    ; outs re, 1
0u01           ; hlt

0u01           ; newline: du '\n'

This program prints numbers until 89, otherwise the number would overflow.

Interpreter

The interpreter is here: [1]. The interpreter supports a debugging mode (very useful!) which can be used with the "--debug" flag.

See also