Rust · own instruction set · one file

A bytecode virtual machine
readable in one sitting.

Mirage assembles plain text into bytecode and runs it on a small stack machine. Its own instruction set, a text assembler, and a runner, with a value stack, a call stack, local variables, and no panics on bad input.

Try the demo View source

Output

-

Disassembly

-

Final stack

-

assembled and run in your browser, a port of the same assembler and stack machine below, not a server call

What it is

Push values, do arithmetic, branch on comparisons, call and return from labeled routines, store variables in local slots, print results. The whole pipeline, assembler and executor, fits in a handful of small files.

Text assembler

Labels, integer literals, and comments, parsed in two passes so forward and backward jumps both resolve.

Typed errors

Stack underflow, division by zero, an unknown opcode, an undefined label, all typed errors, never a panic.

Compact bytecode

A fixed 9 bytes per instruction after a short header, simple enough to disassemble by indexing straight into the stream.

Instruction set

InstructionEffect
PUSH npush integer literal
POP / DUPdiscard or duplicate the top value
ADD SUB MUL DIV MOD NEGarithmetic on the top of stack
EQ LT GTcomparisons, push 1 or 0
LOAD n / STORE nread or write local slot n
JMP JZ JNZunconditional and conditional jumps
CALL / RETcall a labeled routine and return
PRINT / HALTprint the top value, stop execution

Sample program

Sum 1 through 10 on the value stack, using two local slots as accumulator and counter.

loop:
    LOAD 1
    PUSH 10
    GT
    JNZ done
    LOAD 0
    LOAD 1
    ADD
    STORE 0
    LOAD 1
    PUSH 1
    ADD
    STORE 1
    JMP loop
done:
    LOAD 0
    PRINT
    HALT

Run it from the command line.

Assemble and run in one step, or produce a bytecode file and disassemble it back to readable instructions.

mirage run program.asm
mirage asm program.asm -o program.mbc
mirage disasm program.mbc