NOTE: Planning upgrades around 8pm-10pm UTC today. Expect some downtime and possibly read-only wiki. Avoid major editing sessions during that time.
4 trivingits, 529 trivingytes
4 trivingits, 529 trivingytes, another prime-number ASM designed by PSTF.
Also known as TAL assembly language where T stands for trivigintal, Base-23.
This is designed for a 4-trivingit CPU which is named Q23 CPU. Q stands for "quattor", which is 4 in Latin.
If a number isn't written in decimal, it'll be put in parentheses in the document with a subscript showing its base.
Terminology
- Trivingit: a digit23.
- Trivingyte: two trivingits.
- CPU Word Size: 4 trivingits (2 trivingytes)
- Integer Range: 0 to 23⁴ − 1 = 279,840
- Memory Size: 529 trivingytes = 1058 trivingits
- Address Space: 0 to 528 (fits perfectly in 2 trivingits, since (100)23 = 529)
- Registers: 8 general-purpose registers (R0–R7), each 4 trivingits wide. R0 is hardwired to zero.
- Flags: Zero (Z), Negative (N), Carry (C) – set by ADD, SUB, CMP and other arithmetic things.
- Program Counter: 4 trivingits (addresses up to 279,840, though only 0–528 are used)
- I/O: Memory-mapped at address 528 (the last byte). Reading yields input; writing outputs a character.
Codepage
0123456789abcdefghijklm
0␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏␐␑␒␓␔␕␖
1␗␘␙␚␛␜␝␞␟ !"#$%&'()*+,-
2./0123456789:;<=>?@ABCDE
3FGHIJKLMNOPQRSTUVWXYZ[\]
4^_`abcdefghijklmnopqrstu
5vwxyz{|}~␡⎕⍈⌸⌹⌺⌻⌼⍁⍂⍃⍄⍇⍌⍍
6⍐⍓⍔⍗⍞⍠⍯⍰⌷⌽⌾⌿⍀⍅⍆⍊⍉⍋ ¡¢£¥¦
7§¨©ª«¬№®¯°±²³´µ¶·¸¹º»¼
8½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔ
9ÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëì
aíîïðñòóôõö÷øùúûüýþÿ─│┌┐
b└┘├┤┬┴┼━┃┏┓┗┛┣┫┳┻╋╱╲╳═║
c╔╗╚╝╠╣╦╩╬╭╮╯╰╴╵╶╷⍬←↑→↓↖
d↗↘↙↔↕█▀▄▌▐ĀāĂ㥹ĆćĈĉĊċČ
ečĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģ
fĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺ
gĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐő
hŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨ
iũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽžſ
j⅓⅔⅕⅖⅗⅘⅙⅚⅛⅜⅝⅞√∑∈∏∫∴∵≤≥≠≈
k░▒▓ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ™ΣΤΥ
lΦΧΨΩαβγδεζηθικλμνξοπρςσ
mτυφχψωΆΈΉΊΌΎΏάέήίόύώ⅐⅑⅒
Instruction Set Architecture (ISA)
All instructions are exactly 4 trivingits long.
There are three encoding formats:
- Format R (Register–Register)
- [Op] [Rd] [Rs1] [Rs2]
- Format I (Immediate / Address for LDI)
- [Op] [Rd] [Imm_hi] [Imm_lo] — Immediate range = 0 to 528 (23² values)
- Format J (Jump / Branch)
- [Op] [Addr_hi] [Addr_mid] [Addr_lo] — Address range = 0 to 528
Instruction Table
Mnemonic Opcode Format Semantics Flags ADD Rd, Rs1, Rs2 0 R Rd = Rs1 + Rs2 (mod 23⁴) Z, N, C SUB Rd, Rs1, Rs2 1 R Rd = Rs1 - Rs2 (mod 23⁴) Z, N, C CMP Rs1, Rs2 2 R Compute Rs1 - Rs2; discard result, set flags only Z, N, C LOAD Rd, [Rs] 3 R Load 1 word (4 trivingits) from memory address Rs – into Rd. Address must be even. STORE Rs, [Rd] 4 R Store 1 word (4 trivingits) from Rs to memory – address Rd. Address must be even. LDI Rd, Imm 5 I Load a 2-trivigit immediate (0–528) into the – lower half of Rd; upper half zeroed. JMP Addr 6 J Unconditional jump to Addr (0–528) – JZ Addr 7 J Jump to Addr if Zero flag = 1 – JNZ Addr 8 J Jump to Addr if Zero flag = 0 – HALT 9 – Stop execution (opcode 9, rest zeroed) – LDH Rd, Imm A I Load a 2-trivigit immediate (0–528) into the – higher half of Rd; upper half zeroed. MUL Rd, Rs1, Rs2 B R Rd = Rs1 × Rs2 (mod 23⁴) Z, N, C DIV Rd, Rs1, Rs2 C R Rd = Rs1 ÷ Rs2 (mod 23⁴) rounded down Z, N, C MOD Rd, Rs1, Rs2 D R Rd = Rs1 mod Rs2 (mod 23⁴) Z, N, C NOP M – No operation Z, N, C
Note: LOAD/STORE operate on full words (2 trivingytes = 4 trivingits). The address must be even. For byte (trivingyte) access, one can use the pseudo-instructions described later.
Turing Completeness Proof
A CPU of this is Turing-complete if it can simulate a SUBLEQ (Subtract and Branch if Less-than-or-Equal to Zero) instruction, which is known to be universal.
We can simulate SUBLEQ A, B, C (memory locations) using our ISA:
- LOAD R1, [A] – Load value at A into R1
- LOAD R2, [B] – Load value at B into R2
- SUB R3, R1, R2 – R3 = R1 - R2
- STORE R3, [A] – Store result back to A
- CMP R3, R0 – Compare result with zero (R0 is hardwired zero)
- JZ C – If result ≤ 0 (zero flag set), jump to address C
Because we have:
- Arithmetic (SUB)
- Indirect memory access (LOAD/STORE)
- Conditional branching (JZ)
we can implement any SUBLEQ program. Given unbounded memory extension (abstractly), the Q23 ISA is Turing-complete. In practice, with 529 bytes, it is a powerful finite-state machine, but the instruction set itself is universal.
Assembly Language Syntax & Directives
- Comments: ; to end of line
- Labels: label_name:
- Registers: R0 through R7
- Numbers: Trivigintal by default, or use 0b/0d/0x for binary/decimal/hex (converted to base-23 internally)
Directive Description .org N Set the current assembly address to N (0–528) .word V Store a 4-trivigit value (V must be ≤ 279,840) .byte V Store a 2-trivigit value (V must be ≤ 528) .asciiz "str" Store a null-terminated string as trivingytes (Codepage → numeric)
Pseudo-instructions (expanded by the assembler):
- MOV Rd, Rs → ADD Rd, Rs, R0
- LOADB Rd, [Rs] → loads a single trivingyte (uses bit masking with AND – requires a mask constant)
- STOREB Rs, [Rd] → stores a single trivingyte (using OR and AND)
Example Programs
Hello, World!
.org 100 ; Program starts at address 100
start:
LDI R1, str ; R1 = address of string (0)
LDI R2, 0 ; R2 = index counter
LDI R3, io_port ; R3 = 528 (I/O port)
loop:
ADD R4, R1, R2 ; R4 = str + index
LOADB R5, [R4] ; R5 = next character (byte load pseudo-instruction)
CMP R5, R0 ; Compare with R0 (zero)
JZ done ; If null terminator, finish
STOREB R5, [R3] ; Output character to port 528
LDI R6, 1
ADD R2, R2, R6 ; index++
JMP loop
done:
HALT
.org 0 ; String stored at beginning of memory
str:
.asciiz "Hello, World!\n"
io_port:
.byte 528 ; I/O address constant
Fibonacci
.org 200
main:
LDI R1, 0 ; R1 = Fib(0)
LDI R2, 1 ; R2 = Fib(1)
LDI R3, 10 ; R3 = counter (n)
LDI R4, 1 ; R4 = constant 1
LDI R5, result ; R5 = address to store result (500)
loop:
CMP R3, R0 ; Compare counter with 0
JZ done
ADD R6, R1, R2 ; R6 = R1 + R2
MOV R1, R2 ; R1 = R2
MOV R2, R6 ; R2 = R6
SUB R3, R3, R4 ; counter--
JMP loop
done:
STORE R2, [R5] ; Store final Fibonacci number
HALT
.org 500
result:
.word 0 ; Reserve space for result
Machine Code Encoding Example
Let’s encode ADD R1, R2, R3:
- Opcode for ADD = 0
- Rd = 1, Rs1 = 2, Rs2 = 3
- Machine code (base-23 digits): [0] [1] [2] [3] → displayed as "0123"
For JMP 0d100, its machine code is [6] [048] → "6048" since 100 equals (48)23.
Summary
The Q23 CPU with its TAL assembly language provides a clean, mathematically consistent base-23 architecture. With conditional branching, arithmetic, and memory access, it is fully Turing-complete. Its unique 529-byte memory (23²) and 4-trivigit words make it an elegant pedagogical model for non-binary computing.
See Also
- 2 septendigits, 289 septendigytes
- 16 bits, 256 bytes
- 2 undigits, 121 undigytes
- 7 heptits, 49 heptytes
- 4 tridigits, 169 tridigytes
- 8 digits, infinite digytes
- 8 icosigits, 200 icosigytes
- 6 trits, 243 trytes