MVM - fast virtual machine written in Rust. It provides simple assembly with fast execution.
Virtual machine process allocates virtual memory and operates it with static memory and stack size.
⚠️ Project is under active development. Please, wait for stable releases and detailed documentation!
Install the project with cargo package manager:
cargo install --git https://github.com/mealet/deenYou can find more examples in examples directory.
; Hello World Example
section .data
hello:
ascii "Hello, World!\n"
len:
[. - hello]
section .text
entry _start
; ===| Functions |===
print:
; -- syscall void write(int output, void *buffer, size_t length) --
mov %r2, %r1 ; size_t length (length variable)
mov %r1, %r0 ; void* buffer (ptr to message)
add %r1, $8 ; string address offset
mov %r0, $1 ; int output (stdout)
mov %call, $2 ; `write` syscall
int $syscall ; system call interrupt
ret
exit:
; -- syscall void exit(int status) --
mov %r0, $0 ; int status
mov %call, $0 ; `exit` syscall
int $syscall ; system call interrupt
ret
; ===| Program Entrypoint |===
_start:
mov %r0, hello
mov %r1, len
call print
call exitVirtual Machine is an instruction interpreter, which allocates certain amount of memory (can be read from program file, or set by user manually with cli).
After memory is allocated and setted up, main process inserts program right at the start and updates registers such as: instruction pointer, memory pointer, frame & stack pointer.
Each instruction is a byte opcode (defined in vm::isa::Opcode). VM reads source binary, skips data section (because it is used only for pointers) to text section and executes the program.
Instructions can edit registers, memory (by pointers), and whole VM state. Registers (like main memory) is a MemoryBuffer, indexing is calculated by the machine.
Each register is a unsigned 64-bit number slot:
r0, r1, ..., r8- General Purposer9- System Callr10- Accumulatorr12- Stack Pointerr13- Frame Pointerr14- Memory Pointer (next byte after program)
Assembler is a separated compiler with pre-installed constants and registers names. It provides lexer, parser, semantical analyzer and codegen (which contains labels, constants and pointers resolver).
Assembler and VM executor are not connected by the idea, but this implementation requires each module exist because of error module and opcode enumeration (for esaier changes and better code readability).
MVM has its own binary format, assembly compiler must follow it to successfully complete task:
- Metadata section (optional):
[0,0,0,0,0,0,0,0] |> 64-bit number (memory size) [0,0,0,0,0,0,0,0] |> 64-bit number (stack size)
- Data Section:
0x01 |> data section start opcode ... 0xff 0x02 |> text section start sequence
- Text Section
... |> program bytesMerging it will give us binary file with program:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x01 ... 0xff 0x02 ... |-----------------------------| | |=======|===|> section `.text` sequence |-----------------------------| |-------------------|> section `.data` sequence |-----------------------------|----------------------|> metadata section
The project is licensed under the MIT License.
See LICENSE for more information.