Skip to content

Latest commit

 

History

19 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mirage logo

Mirage: a stack-based bytecode virtual machine in Rust

Mirage is a small stack-based bytecode virtual machine written from scratch in Rust, with its own instruction set, a text assembler, a disassembler, and a runner. Programs are written in plain text assembly, assembled into compact .mbc bytecode, and executed or disassembled back to readable form. It is a teaching and reference implementation built to be read in one sitting, showing how a stack VM, bytecode format, assembler, and runner fit together.

Live demo · MIT licensed · written in Rust

Built from scratch by Pavan Nallamothu (LinkedIn, GitHub).

Mirage is a from-scratch VM built to be read in one sitting. It has a value stack, a call stack, a flat local variable slot array, and a compact binary bytecode format. Programs are written in a plain text assembly, assembled into .mbc bytecode, and executed directly or disassembled back to readable form. Bad input never crashes the VM. Stack underflow, division by zero, an unknown opcode, and a jump to an undefined label all come back as typed errors.

Instruction set

Instruction Effect
PUSH n push integer literal n
POP discard the top value
DUP duplicate the top value
ADD SUB MUL DIV MOD pop two, push the result, DIV/MOD by zero is an error
NEG pop one, push its negation
EQ LT GT pop two, push 1 or 0
LOAD n push the value in local slot n
STORE n pop the top value into local slot n
JMP label jump unconditionally
JZ label pop, jump if the value is zero
JNZ label pop, jump if the value is nonzero
CALL label push a return address, jump
RET pop a return address, jump back
PRINT print the top value without popping it
HALT stop execution

Labels look like loop: on their own line. ; starts a comment that runs to end of line.

Sample program

; sum 1..=10, prints 55
    PUSH 0
    STORE 0
    PUSH 1
    STORE 1
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

Usage

# assemble and run a program in one step
mirage run examples/sum_loop.asm

# assemble to a bytecode file
mirage asm examples/factorial.asm -o factorial.mbc

# disassemble a bytecode file back to readable instructions
mirage disasm factorial.mbc

Building and testing

cargo build
cargo test

Tests assemble and run examples/factorial.asm, examples/fibonacci.asm, and examples/sum_loop.asm, then assert on the exact printed output. Separate tests check that stack underflow, division by zero, and undefined labels return errors instead of panicking.

See DESIGN.md for the bytecode format and the assembler and executor pipeline.

Mirage is a teaching and reference project, not a production runtime.

License

MIT. By Pavan Nallamothu.

About

Stack-based bytecode virtual machine in Rust with its own instruction set, assembler, and runner

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages