Source: GitHub Repository
Table of Contents
Overview
MITS (Multi Instruction Table Set) is a minimal, stack-less assembly language designed for simplicity and clarity. Unlike traditional assembly languages with complex register management and memory addressing, MITS provides a clean, intuitive interface for low-level programming while maintaining powerful functionality.
Key Features:
- Named registers (variables) - Use meaningful 3-letter names instead of cryptic register numbers (e.g.,
msg,cnt,tmp), with automatic type management that eliminates manual type tracking - Rich type system - Full support for numeric (64-bit signed integers), string (up to 511 characters), and hexadecimal (byte array) data types with seamless conversion operations
- ROM-based static data storage - Store configuration, constants, and lookup data in external .rom files, keeping your program code clean and data separate
- Control flow constructs - Familiar conditional execution (
cond) and looping (for) with readable syntax, pluselseclauses for complex branching logic - User-defined functions - Create reusable code blocks with the
definstruction, supporting argument passing and modular programming practices - Interactive I/O operations - Powerful
rdl(readline) with type flags (-i,-f,-s) for integer, float, and string input, plusvgafor formatted output - Debugging tools - Built-in
readinstruction for inspecting registers and ROM data with hexdump capabilities, making development and troubleshooting easier
Whether you're learning assembly concepts, building educational tools, or creating compact utilities, MITS provides an accessible yet powerful platform for low-level programming.
Getting Started
Getting up and running with MITS is straightforward. The toolchain consists of a compiler and interpreter, both built from C source code using standard make utilities.
Building the Tools
Clone and build from source at syntaxMORG0/MITS:
make # build compiler and interpreter
make clean # remove build artifacts
Running MITS Programs
Once built, use the ./mits launcher to execute your .s assembly files. The interpreter processes your code line-by-line, managing registers, executing instructions, and handling I/O operations.
Basic execution:
# With ROM data file (optional)
./mits program.s data.rom
# Without ROM data file (data.rom is optional)
./mits program.s
Note: The ROM file is completely optional. If your program doesn't use rom= lookups, you can omit it entirely.
ROM Files (Optional)
ROM (Read-Only Memory) files provide a way to store static configuration data, constants, and lookup tables separate from your program logic. This separation of data and code makes programs more maintainable and allows you to change data without recompiling.
ROM files use a simple key-value format with # for comments. Programs can run perfectly fine without ROM files - they're only needed if you use rom= lookups in your code.
Format:
# String values
name="John"
title="MITS"
# Numeric values
count=42
version=100
Access in program: mov dest, rom=key
File Extensions
.s- Assembly source files.rom- ROM data files (optional)
Language Basics
Program Structure
- Entry point: Every program must have a
_start:label - Comments: Start with
;and extend to end of line - Line length: Maximum 512 characters per line
- Case sensitivity: Instructions are lowercase; variables are case-sensitive
Variable Naming Rules
The 3-Letter Rule: ALL variables in MITS must be exactly 3 letters (a-z, A-Z only). This unique constraint enforces concise, memorable variable names and creates a consistent coding style across all MITS programs.
Why 3 letters? This limitation encourages thoughtful naming (like msg for message, cnt for count, idx for index) while keeping code compact and readable. It's similar to how assembly traditionally uses short register names, but with semantic meaning.
Valid names: abc, xyz, msg, tmp, ret, num, str, val
Invalid names: ab (too short), abcd (too long), a1b (contains digit), my_var (too long, has underscore)
ERROR: Using invalid variable names will cause immediate runtime errors with a descriptive message.
Data Types
| Type | Created By | Characteristics |
|---|---|---|
| NUMBER | mov, arithmetic, rdl -i |
64-bit signed integer |
| STRING | char, rdl, conversions |
Text data (max 511 chars) |
| HEX | hex= conversion |
Byte array |
String Literals
Enclosed in double quotes: "hello"
Maximum length: 511 characters
Comments
Use semicolons for comments:
; Full line comment
mov abc, 10 ; Inline comment
ROM Data Storage
ROM files are optional and store static data.
Format:
# Comments use # in ROM files
name="John"
version=100
Access: mov dest, rom=key
Core Instructions
mov dest, src
Move value into register.
mov abc, 10 ; numeric literal
mov def, abc ; copy from register
mov ghi, abc + def ; arithmetic result
mov jkl, rom=count ; from ROM
mov mno, code=1 ; exit code
char dest, "string"
Store string literal.
char msg, "hello world"
vga value
Output to stdout. Format depends on type:
- NUMBER: Decimal number
- STRING: Raw text
- HEX: Space-separated hex bytes
mov num, 42
vga num ; outputs: 42
char msg, "hello"
vga msg ; outputs: hello
exec
exec register - Execute exit code:
mov ext, code=0
exec ext ; exit with code 0
exec sys=help - List all instructions:
exec sys=help
exec function, args... - Call user function:
exec add, 10, 20
Data Conversions
hex= - String to Hex
Convert STRING to HEX bytes:
char msg, "MITS"
mov hex, hex=msg
vga hex ; outputs: 4d 49 54 53
b31 - Hex to String (ANSI)
Convert HEX back to STRING:
char msg, "hello"
mov h1, hex=msg
mov h2, b31 h1
vga h2 ; outputs: hello
i32 / b32 - Hex to Integer
Convert HEX bytes to integer:
char msg, "MITS"
mov hex, hex=msg
mov num, i32 hex
vga num ; outputs: 1296651347
c26 - To Character Data
Convert number or hex to string:
mov num, 12345
mov txt, c26 num
vga txt ; outputs: 12345
flt - Floating Point
Convert integer to float representation:
mov num, 98765
mov flt, flt num
vga flt ; outputs: 98765.00
UTF - UTF-8 Conversion
Convert to UTF-8 format:
char msg, "UTF-8 Text"
mov utf, UTF msg
vga utf ; outputs: UTF-8 Text
rom= - From ROM
Load value from ROM storage:
mov val, rom=key
code= - Exit Code
Load an exit code:
mov ext, code=0 ; success
mov err, code=1 ; error
Arithmetic Operations
addr dest, expr
ADD numbers or concatenate HEX:
; Addition
mov aaa, 10
mov bbb, 20
addr ccc, aaa + bbb ; ccc = 30
; HEX concatenation
mov h1, hex=msg1
mov h2, hex=msg2
addr res, h1 + h2 ; merged bytes
subr dest, a - b
SUBTRACT right from left:
mov xxx, 100
mov yyy, 35
subr zzz, xxx - yyy ; zzz = 65
mul dest, a * b
MULTIPLY two numbers:
mov naa, 12
mov nbb, 5
mul prd, naa * nbb ; prd = 60
div dest, a / b
INTEGER DIVISION:
mov num, 20
mov den, 3
div qot, num / den ; qot = 6
mod dest, a % b
MODULO (remainder):
mov aaa, 20
mov bbb, 3
mod rem, aaa % bbb ; rem = 2
sda dest, values...
SUM all values:
sda sum, 10, 20, 30 ; sum = 60
mov aaa, 5
mov bbb, 10
sda tot, aaa, bbb ; tot = 15
Input and Output
rdl - Read Line
Read input from stdin with optional type conversion.
rdl -i dest - Read as integer:
rdl -i num ; converts input to NUMBER
rdl -f dest - Read as float:
rdl -f flt ; stores as formatted string "X.XX"
rdl -s dest - Read as string (explicit):
rdl -s str ; reads as STRING
rdl dest - Read as string (default):
rdl txt ; default: STRING type
Complete Input Example
_start:
char prm, "Enter number: "
vga prm
rdl -i num
vga num
char pm2, "Enter float: "
vga pm2
rdl -f flt
vga flt
char pm3, "Enter text: "
vga pm3
rdl txt
vga txt
mov ext, code=0
exec ext
Debugging - read Instruction
The read instruction provides inspection and debugging capabilities.
read -lt -a adr
List all registers:
read -lt -a adr ; shows all defined registers
read -lt adr <register>
Show specific register details:
read -lt adr msg ; detailed info about 'msg'
read -lt -a rom <file>
List all ROM entries:
read -lt -a rom data.rom
read -lt rom <file> <key>
Show specific ROM entry:
read -lt rom data.rom name
Hex Dump Mode (-hxd flag)
Add -hxd to show hexadecimal representation:
read -lt -a -hxd adr ; all registers with hex
read -lt -hxd adr msg ; specific register with hex
read -lt -a -hxd rom data.rom ; ROM entries with hex
Debugging Example
_start:
mov aaa, 100
char bbb, "test"
mov ccc, hex=bbb
; List all registers
read -lt -a adr
; Inspect specific register
read -lt adr ccc
; Show hex dump
read -lt -hxd adr bbb
mov ext, code=0
exec ext
Control Flow
for mov index, start, end, exec: ... end
Loop from start to end (inclusive):
mov cnt, 3
for mov idx, 0, cnt, exec:
vga idx ; outputs: 0, 1, 2, 3
end
cond condition, exec: ... end
Conditional execution. Supports: < > <= >= == !=
mov xxx, 5
mov yyy, 10
cond xxx < yyy, exec:
vga 1 ; executes if xxx < yyy
end
cond xxx == yyy, exec:
vga 2
else
vga 3 ; else clause
end
Functions and Modules
def name, ARGUMENTS, exec: ... end
Define a function:
def add, ARGUMENTS, exec:
sda ret, ARGUMENTS
end
_start:
exec add, 10, 20
vga ret ; outputs: 30
mov ext, code=0
exec ext
req ftype="type", "file"
Import external files. Types: "rom" or "asm"
req ftype="rom", "data.rom"
req ftype="asm", "helpers.s"
Type System
- NUMBER: 64-bit signed integer
- STRING: Text data (max 511 chars)
- HEX: Byte array
Type Conversion Summary
| Conversion | Usage | Result Type |
|---|---|---|
| hex= | STRING → HEX | HEX |
| b31 | HEX → STRING | STRING |
| i32 / b32 | HEX → NUMBER | NUMBER |
| c26 | NUMBER → STRING | STRING |
| flt | NUMBER → FLOAT STRING | STRING |
| UTF | STRING → UTF-8 | STRING |
Error Handling
- Missing _start: Program will not run
- Invalid variable name: Must be exactly 3 letters
- Unknown instruction: Reported with context
- Type mismatch: Cannot mix types in operations
- Division by zero: Results in 0
- Undefined ROM key: Error if key doesn't exist
Examples
Basic Examples
Hello World
_start:
char msg, "Hello, MITS!"
vga msg
mov ext, code=0
exec ext
Basic Arithmetic
_start:
mov aaa, 100
mov bbb, 50
addr ccc, aaa + bbb
vga ccc ; outputs: 150
mov ext, code=0
exec ext
User Input (Integer)
_start:
char prm, "Enter a number: "
vga prm
rdl -i num
vga num
mov ext, code=0
exec ext
User Input (Float)
_start:
char prm, "Enter decimal: "
vga prm
rdl -f flt
vga flt ; formatted as "X.XX"
mov ext, code=0
exec ext
User Input (String)
_start:
char ask, "Enter name: "
vga ask
rdl nam
vga nam
mov ext, code=0
exec ext
Conversions
_start:
; String to hex
char msg, "MITS"
mov hex, hex=msg
vga hex ; 4d 49 54 53
; Hex to string
mov str, b31 hex
vga str ; MITS
; Hex to integer
mov num, i32 hex
vga num ; 1296651347
; Number to string
mov val, 12345
mov txt, c26 val
vga txt ; 12345
; Float representation
mov flt, flt val
vga flt ; 12345.00
mov ext, code=0
exec ext
ROM Data Usage
; data.rom:
; name="MITS"
; version=100
_start:
mov nam, rom=name
vga nam
mov ver, rom=version
vga ver
mov ext, code=0
exec ext
Debugging with read
_start:
mov aaa, 100
char bbb, "test"
mov ccc, hex=bbb
; List all registers
read -lt -a adr
; Inspect specific
read -lt adr ccc
; Hex dump
read -lt -hxd adr bbb
mov ext, code=0
exec ext
Functions
def add, ARGUMENTS, exec:
sda ret, ARGUMENTS
end
_start:
exec add, 10, 20, 30
vga ret ; outputs: 60
mov ext, code=0
exec ext
Control Flow
_start:
mov xxx, 5
mov yyy, 10
cond xxx < yyy, exec:
char msg, "xxx is smaller"
vga msg
end
for mov idx, 0, 3, exec:
vga idx ; outputs: 0, 1, 2, 3
end
mov ext, code=0
exec ext
Complete Program
_start:
; Greeting
char wel, "Welcome to MITS!"
vga wel
; Get name
char prm, "Enter your name: "
vga prm
rdl nam
; Echo name
char msg, "Hello, "
vga msg
vga nam
; Get age
char ag1, "Enter age: "
vga ag1
rdl -i age
; Calculate years to 100
mov hun, 100
subr rem, hun - age
char ag2, "Years to 100: "
vga ag2
vga rem
; Exit
mov ext, code=0
exec ext
Libraries
MITS can be extended with external libraries. Below are examples of how to use different library implementations:
WebAssembly (WASM)
MITS supports building interactive web applications using WebAssembly. The wasm instruction allows you to create pages, define HTML elements, embed scripts (JavaScript and C), and serve them over HTTP.
Quick Start
_start:
req ftype="wasm", lib.webasm
mov home, wasm -np page="home"
wasm -op 8000 -ap page="home"
This loads the WebAssembly library, creates a page, and starts a web server on port 8000.
WebAssembly Instruction Flags
-np (New Page)
Purpose: Creates a new page container for organizing HTML elements.
Syntax: wasm -np page="pagename"
Parameters:
page- String identifier for the page (e.g., "home", "about", "dashboard")
Example:
mov home, wasm -np page="home"
mov about, wasm -np page="about"
-ne (New Element)
Purpose: Creates an HTML DOM element with configurable properties.
Syntax: wasm -ne type="tagname" [txt="content"] [id="identifier"] [class="classname"] [style="css"]
Parameters:
type(required) - HTML tag name (h1, h2, p, span, div, button, input, form, etc.)txt(optional) - Text content or placeholderid(optional) - Unique identifier for CSS/JavaScript targetingclass(optional) - CSS class(es) for stylingstyle(optional) - Inline CSS rules
Available Element Types:
- Headings: h1, h2, h3, h4, h5, h6
- Text: p, span, strong, em, code, pre
- Forms: form, input, button, textarea, label, select, fieldset
- Containers: div, section, article, header, footer, nav, main, aside
- Media: img, a, video, audio
- Tables/Lists: table, thead, tbody, tr, th, td, ul, ol, li, dl
Example:
mov title, wasm -ne type="h1" txt="Welcome!" id="main-title" class="hero"
mov btn, wasm -ne type="button" txt="Click Me" id="cta-btn" class="btn-primary"
mov form, wasm -ne type="form" id="contact-form"
-ns (New Script)
Purpose: Embeds executable code (JavaScript for frontend, C/Clang for backend).
Syntax: wasm -ns ftype="javascript|clang" id="script_id" exec => { /* code */ }
Parameters:
ftype(required) - Script type: "javascript" (client-side) or "clang" (server-side C)id(required) - Script identifierexec => {...}(required) - Code blockdevlabel(optional) - Documentation comment, ignored at runtime
Example:
; Client-side JavaScript
wasm -ns ftype="javascript" id="click-handler" exec => {
document.getElementById("btn").onclick = function() {
alert("Button clicked!");
};
}
; Server-side C backend
wasm -ns ftype="clang" id="backend" exec => {
#include <stdio.h>
void process(char *data) {
printf("Processing: %s\n", data);
}
}
-ae (Attach Element)
Purpose: Associates an element or script with a page for rendering/execution.
Syntax: wasm -ae id="element_or_script_id" page="page_name"
Parameters:
id(required) - Identifier of the element or script to attachpage(required) - Target page name
Note: An element or script can be attached to multiple pages. Elements created with -ne and scripts with -ns must be attached to be rendered or executed.
Example:
mov title, wasm -ne type="h1" txt="Home" id="title"
mov btn, wasm -ne type="button" txt="Submit" id="btn"
mov home, wasm -np page="home"
wasm -ae id="title" page="home"
wasm -ae id="btn" page="home"
-op (Open Port) & -ap (Active Page)
Purpose: Starts the web server and designates the entry page.
Syntax: wasm -op port_number -ap page="page_name"
Parameters:
port(required) - Network port number (typically 8000-9999 for development, 80 for production)-ap page(optional) - Sets which page is served as the root/home page
Behavior: Runs the web server and automatically builds the webpage from all attached elements and scripts. The server is ready to accept connections on localhost:port.
Example:
wasm -op 8000 -ap page="home" ; Development on port 8000
wasm -op 3000 -ap page="dashboard" ; Dashboard on port 3000
wasm -op 80 -ap page="public" ; Production on port 80
Execution Model
When you run a MITS script with WebAssembly instructions:
- Load library:
req ftype="wasm"initializes the WebAssembly runtime - Define structure: Use
-npto create pages,-neto create elements,-nsto register scripts - Organize: Use
-aeto attach elements and scripts to pages - Serve: Run
wasm -op PORT -ap page="NAME"to start the web server - Generated HTML: The interpreter generates complete HTML5 from your element definitions and serves it on the specified port
- JavaScript execution: JavaScript code blocks execute in the browser when the page loads
- C backend: Clang code blocks are compiled and executed server-side for data processing
Complete WebAssembly Example
_start:
req ftype="wasm", lib.webasm
; Create pages
mov home, wasm -np page="home"
mov about, wasm -np page="about"
; Create elements
mov title, wasm -ne type="h1" txt="My Website" id="title" class="header"
mov desc, wasm -ne type="p" txt="Welcome to MITS WebAssembly!" id="desc"
mov form, wasm -ne type="form" id="contact" class="form"
mov name, wasm -ne type="input" txt="Name" id="name-field" class="input"
mov email, wasm -ne type="input" txt="Email" id="email-field" class="input"
mov btn, wasm -ne type="button" txt="Submit" id="submit-btn" class="btn-primary"
; Attach to home page
wasm -ae id="title" page="home"
wasm -ae id="desc" page="home"
wasm -ae id="contact" page="home"
wasm -ae id="name-field" page="home"
wasm -ae id="email-field" page="home"
wasm -ae id="submit-btn" page="home"
; Create interactive script
wasm -ns ftype="javascript" id="form-handler" exec => {
document.getElementById("submit-btn").addEventListener("click", function() {
let name = document.getElementById("name-field").value;
let email = document.getElementById("email-field").value;
alert("Form received: " + name + " (" + email + ")");
});
}
; Backend processor
wasm -ns ftype="clang" id="processor" exec => {
#include <stdio.h>
void validate_email(char *email) {
if (email[0] != '\0') {
printf("Email is valid\n");
}
}
}
; Attach scripts
wasm -ae id="form-handler" page="home"
wasm -ae id="processor" page="home"
; Start web server on port 8000
wasm -op 8000 -ap page="home"