{"id":31579081,"url":"https://github.com/pedramcode/myvm","last_synced_at":"2026-05-18T03:11:26.800Z","repository":{"id":313605367,"uuid":"1052004459","full_name":"pedramcode/myvm","owner":"pedramcode","description":"Rust virtual machine and assembler","archived":false,"fork":false,"pushed_at":"2025-09-14T14:06:34.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-05T20:52:25.082Z","etag":null,"topics":["assembly","interpreter","rust","systems-programming","virutal-machine","vm"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pedramcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-07T07:34:09.000Z","updated_at":"2025-09-14T14:06:37.000Z","dependencies_parsed_at":"2025-09-07T18:31:33.830Z","dependency_job_id":null,"html_url":"https://github.com/pedramcode/myvm","commit_stats":null,"previous_names":["pedramcode/myvm"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pedramcode/myvm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedramcode%2Fmyvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedramcode%2Fmyvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedramcode%2Fmyvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedramcode%2Fmyvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pedramcode","download_url":"https://codeload.github.com/pedramcode/myvm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedramcode%2Fmyvm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33163444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"online","status_checked_at":"2026-05-18T02:00:06.436Z","response_time":71,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assembly","interpreter","rust","systems-programming","virutal-machine","vm"],"created_at":"2025-10-05T20:46:13.761Z","updated_at":"2026-05-18T03:11:26.794Z","avatar_url":"https://github.com/pedramcode.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rust Virtual Machine / Assembler and Compiler\n\n## Table of Contents\n- [Tutorial](#-tutorials)\n- [🏗 Architecture](#-architecture)\n  - [What is a Stack-Based VM?](#what-is-a-stack-based-vm)\n  - [Instruction Set: RISC Design](#instruction-set-risc-design)\n  - [Main VM Components](#main-vm-components)\n    - [1. Memory](#1-memory)\n    - [2. Registers](#2-registers)\n    - [3. Flags](#3-flags)\n- [📝 VM Assembly Syntax and Commands](#-vm-assembly-syntax-and-commands)\n  - [Program Entry Point](#program-entry-point)\n  - [Sections](#sections)\n  - [Data Definitions](#data-definitions)\n  - [Numbers](#numbers)\n  - [Memory Addresses](#memory-addresses)\n  - [Metas](#metas)\n  - [Comments](#comments)\n  - [Registers](#registers)\n  - [Opcodes (commands)](#opcodes-commands)\n  - [Labels](#labels)\n  - [Interrupts](#interrupts)\n    - [Syntax](#syntax)\n    - [Example: Module 0 = IO](#example-module-0--io)\n    - [Example Usage](#example-usage)\n  - [Hello World!](#hello-world)\n- [💻 Command-Line Interface (CLI)](#-command-line-interface-cli)\n  - [Installation](#installation)\n  - [Commands](#commands)\n    - [1. Compile](#1-compile)\n    - [2. Exec](#2-exec)\n- [🛠️ Developer TODO / Roadmap](#️-developer-todo--roadmap)\n\n---\n\n## Tutorials\n\nHere is link to MyVM tutorial: [Tutorial](./Tutorial.md)\n\n---\n\n## 🏗 Architecture\n\nThis project is a **stack-based virtual machine (VM)** with a **separate call stack** for managing function calls.\n\n### What is a Stack-Based VM?\n\nA stack-based VM executes instructions primarily by manipulating a **stack data structure**.  \nInstead of operating directly on registers, most instructions **push values onto the stack** and **pop them when needed**.  \n\nFor example, consider the following program:\n\n```assembly\nPUSH 10\nPUSH 20\nADD\n```\n\n- `PUSH 10` pushes the value `10` onto the stack.  \n- `PUSH 20` pushes the value `20`.  \n- `ADD` pops the top two values (`20` and `10`), adds them, and pushes the result (`30`) back onto the stack.  \n\nThis simple model makes it easier to implement compilers and interpreters since there is no need to manage complex register allocations.\n\n---\n\n### Instruction Set: RISC Design\n\nThe VM uses a **Reduced Instruction Set Computing (RISC)** design.  \nRISC focuses on having a **small, well-defined set of simple instructions**, each performing a single operation efficiently.  \n\nEach instruction in the VM is represented as an **Opcode**.\n\n#### What is an Opcode?\n\nAn **Opcode (Operation Code)** is the numeric or symbolic representation of an instruction that tells the VM what operation to perform.  \nOpcodes may also take parameters (operands).  \n\nFor example:\n\n```assembly\nPUSH 42 ; Opcode: PUSH, Operand: 42\nPUSH 32 ; Opcode: PUSH, Operand: 32\nADD ; Opcode: ADD (no operands)\n```\n\nSome Opcodes have **variants**.  \nFor example, the **Jump instruction** has multiple variants that depend on conditions:  \n- `jmp` → Unconditional jump  \n- `jnz` → Jump if not zero  \n- `jz`  → Jump if zero  \n- `jg`  → Jump if greater  \n- `jl`  → Jump if less  \n- `jge` → Jump if greater or equal  \n- `jle` → Jump if less or equal  \n\n---\n\n### Main VM Components\n\nThe VM core is composed of three primary components:\n\n#### 1. Memory\n- The **main storage** that contains:\n  - Uploaded program code  \n  - Variables and data  \n  - Execution stack  \n- The stack is located at the **end of memory** and grows **backwards** to avoid collisions with program data.  \n- If the stack grows beyond its capacity, a **stack overflow** occurs.  \n- Each memory cell is **32-bit wide**.\n\n#### 2. Registers\n- **Registers** are small, fast storage locations inside the VM that hold data during execution.  \n- This VM has:\n  - **8 general-purpose registers**: `r0` ... `r7`  \n  - **Program Counter (PC)** register: stores the address of the **next instruction** to execute  \n\nRegisters allow the VM to perform operations more quickly than relying solely on memory.\n\n#### 3. Flags\n- **Flags** are single-bit indicators that store the outcome of operations.  \n- They are used by conditional instructions (like jumps) to determine execution flow.  \n- This VM defines the following flags:\n  - **Zero (Z)** → Set when the result of an operation is `0`  \n  - **Overflow (O)** → Set when an arithmetic operation produces a value outside the representable range  \n  - **Negative (N)** → Set when the result of an operation is negative  \n  - **Carry (C)** → Set when an arithmetic operation generates a carry/borrow bit beyond the register size  \n\n---\n\n## 📝 VM Assembly Syntax and Commands\n\nThe VM uses a **custom assembly language** for programming, supporting constants, memory addresses, registers, labels, macros, and interrupts.\n\n---\n\n### Program Entry Point\n\nEvery program must have exactly one **`.start` label** that serves as the entry point. This is where execution begins.\n\n- **No `.start` label**: Results in compilation error\n- **Multiple `.start` labels**: Results in compilation error\n\nExample:\n```asm\n[text]\n.start\n    PUSH 10\n    INT 0 0\n    TERM\n```\n\n### Sections\n\nPrograms must be organized into sections using `[section_name]` tags. There are two mandatory sections:\n\n- `[text]` - Contains executable code\n- `[data]` - Contains data definitions and constants\n\nWriting code in the `[data]` section or defining data in the `[text]` section will result in an error.\n\nExample:\n```asm\n[data]\n$name dw \"Pedram\" 0\n$scores w 0x2301 0x1212 19 20\n\n[text]\n.start\n    PUSH $name\n    INT 0 3\n    TERM\n```\n\n### Data Definitions\n\nData can be defined in the `[data]` section using the following syntax:\n\n```\n$[identifier] [data type] [... data separated with space ...]\n```\n\nSupported data types:\n- `b` - Byte: stores data in 1-byte arrays\n- `w` - Word: stores data in 2-byte arrays  \n- `dw` - Double Word: stores data in 4-byte arrays\n\nExamples:\n```asm\n[data]\n$name b \"Pedram\"\n$scores w 0x2301 0x1212 19 20\n$data dw 0xaaaaaaaa 0xbbbbbbbb\n```\n\n**Note on memory storage**: Each memory cell is 32-bit (4 bytes). When using `b` or `w` types, data is packed into memory cells at the bit level. For example:\n- `b 0xaa 0xbb 0xcc` stores as: `0xaabbcc00`\n- `w 0xaabb 0xcc` stores as: `0xaabbcc00`\n\n### Enhanced Memory Access Syntax\n\nThe following syntax is supported for accessing data:\n\n```asm\n; Push operations\npush $name        ; pushes $name address to stack\npush [$name]      ; pushes $name value to stack  \npush [$name + 4]  ; pushes $name value with offset to stack\npush [$name + r0] ; pushes $name value with offset stored in register to stack\n\n; Move operations\nmove r0 $name        ; move address of $name into register r0\nmove r0 [$name]      ; move value of $name into register r0\nmove r0 [$name + 2]  ; move value of $name with offset into register r0\nmove r0 [$name + r1] ; move value of $name with offset stored in r1 into register r0\nmove r0 \u0026r1          ; move value of data that its address stored in register r1 to r0\n```\n\n### Numbers\n- **Decimal:** `42`  \n- **Hexadecimal:** `0x2A`  \n- **Binary:** `0b101010`  \n\n### Memory Addresses\n- Use `\u0026[number]` to reference memory addresses:  \n  - `\u00260x1010`, `\u0026321`, `\u00260b101010`  \n- They point to the value stored at the specified memory address.\n\n### Metas\nMetas are special commands that control how the VM executes or prepares code.  \nThey **start with `@`** and may have parameters:\n\n- `@ORG x` → Sets the origin address in memory for the following code.  \n- `@INCLUDE \"./file.asm\"` → Includes another assembly file into the current file.  \n\n### Comments\n- Start with `;`  \n```asm\n; This is a comment\n```\n\n### Registers\n\nThe VM supports registers:\n\n* General-purpose: r0, r1, r2, r3, r4, r5, r6, r7\n\n* Special-purpose: pc (Program Counter)\n\n### Opcodes (commands)\n\n| Command         | Parameters         | Description                                               |\n| --------------- | ------------------ | --------------------------------------------------------- |\n| `PUSH 10`       | number             | Pushes a constant number to the stack                     |\n| `PUSH r0`       | register           | Pushes value of a register onto the stack                 |\n| `PUSH \u002610`      | address            | Pushes value from memory address onto the stack           |\n| `PUSH $name`    | data label         | Pushes address of data label to stack                     |\n| `PUSH [$name]`  | data label         | Pushes value of data label to stack                       |\n| `PUSH [$name + 1]`  | data label + offset         | Pushes value of data label with offset to stack                       |\n| `PUSH [$name + r0]`  | data label + offset         | Pushes value of data label with offset in register to stack                       |\n| `POP r1`        | register           | Pops value from stack into a register                     |\n| `POP \u002632`       | address            | Pops value from stack into a memory address               |\n| `ADD`           | -                  | Pops two values, adds them, pushes result                 |\n| `SUB`           | -                  | Pops two values, subtracts, pushes result                 |\n| `MUL`           | -                  | Pops two values, multiplies, pushes result                |\n| `DIV`           | -                  | Pops two values, divides, pushes result, puts reminder in R3.                   |\n| `DROP`          | -                  | Drops the top item of the stack                           |\n| `SWAP`          | -                  | Swaps top two items on stack                              |\n| `INC r0 `       | register           | increase register by 1                                    |\n| `DEC r0 `       | register           | decrease register by 1                                    |\n| `MOVE r0 10`    | register, value    | Moves constant into register                              |\n| `MOVE r0 r1`    | register, register | Moves value from one register to another                  |\n| `MOVE r0 \u002612`   | register, address  | Moves value from memory address to register               |\n| `MOVE r0 $name` | register, data     | Moves address of data label to register                   |\n| `MOVE r0 [$name]` | register, data   | Moves value of data label to register                     |\n| `MOVE r0 [$name + 2]` | register, data | Moves value of data label with offset to register       |\n| `MOVE r0 [$name + r1]` | register, data | Moves value of data label with register offset to register |\n| `MOVE r0 \u0026r1`   | register, register | Moves value from address in register to register          |\n| `STORE 1010 32` | address, value     | Stores constant into memory                               |\n| `STORE 1010 r3` | address, register  | Stores register value into memory                         |\n| `JMP .label`    | label              | Unconditional jump                                        |\n| `JNZ .label`    | label              | Jump if not zero                                          |\n| `JZ .label`     | label              | Jump if zero                                              |\n| `JG .label`     | label              | Jump if greater                                           |\n| `JGE .label`    | label              | Jump if greater or equal                                  |\n| `JL .label`     | label              | Jump if less                                              |\n| `JLE .label`    | label              | Jump if less or equal                                     |\n| `AND`           | -                  | Pops two values, bitwise AND, pushes result               |\n| `OR`            | -                  | Pops two values, bitwise OR, pushes result                |\n| `XOR`           | -                  | Pops two values, bitwise XOR, pushes result                |\n| `NOT`           | -                  | Pops one value, bitwise NOT, pushes result                |\n| `SHR 10`        | value              | Pops value, shifts right by constant, pushes result       |\n| `SHR r3`        | value              | Pops value, shifts right by register value, pushes result |\n| `SHL 10`        | value              | Pops value, shifts left by constant, pushes result        |\n| `SHL r3`        | value              | Pops value, shifts left by register value, pushes result  |\n| `CALL 32`       | address            | Calls procedure at address                                |\n| `CALL .label`   | label              | Calls procedure by label                                  |\n| `CALL r0`       | register           | Calls procedure at address in register                    |\n| `CALL \u0026323`     | address            | Calls procedure at memory address                         |\n| `SAFECALL 32`       | address            | Calls procedure at address and preserve machine state (registers and flags)                                |\n| `SAFECALL .label`   | label              | Calls procedure by label and preserve machine state (registers and flags)                                  |\n| `SAFECALL r0`       | register           | Calls procedure at address in register and preserve machine state (registers and flags)                   |\n| `SAFECALL \u0026323`     | address            | Calls procedure at memory address and preserve machine state (registers and flags)                        |\n| `RET`           | -                  | Returns from procedure                                    |\n| `DUP`           | -                  | Duplicates top stack item                                 |\n| `DUP 10`        | number             | Duplicates top stack item `n` times                       |\n| `DUP r3`        | register           | Duplicates top stack item `r3` times                      |\n| `INT 0 2`       | module, function   | Calls an interrupt (see below)                            |\n| `TERM`          | -                  | Terminates code execution                                 |\n\n### Labels\n\n* Labels mark code positions and procedures for jumps and calls.\n\n* Start with . and contain only alphanumeric characters (no spaces):\n\n```asm\n.sayhello\n    ; code here\nRET\n```\n\n### Interrupts\n\nAn interrupt is a pre-defined function in a VM module that performs operations outside normal instructions.\nInterrupts allow modular, system-level functionality like I/O.\n\n#### Syntax\n\n```asm\nINT module_number function_number\n```\n\n#### Example: Module 0 = IO\n\n| Function | Description                                                                    |\n| -------- | ------------------------------------------------------------------------------ |\n| 0        | Pops top of stack and prints it                                                |\n| 1        | Pops number `n` from stack, then pops `n` items and prints them                |\n| 2        | Pops a stop value, then continuously pops and prints until reaching stop value |\n| 3        | Pops address of string in [data] and prints it until reaching 0                |\n| 4        | Pops number from stack and prints it as string                                 |\n\nInterrupts provide a bridge between VM code and system-level functions without complicating the instruction set.\n\n---\n\n#### Example Usage\n\n```asm\n@ORG 0x100\n\n.start\nCALL .f\nTERM\n\n.f\nPUSH 13\nINT 0 0\nRET\n```\n\n## Hello World! (Using data section)\n\n```asm\n[data]\n\n$hello dw \"Hello World!\" 10 13 0\n\n[text]\n\n.start\npush $hello\nint 0 3\nterm\n\n```\n\n## Reverse print number\n\n```asm\n@org 0\n\n.start\npush 123\ncall .split\nTERM\n\n.split\n    push 10\n    swap\n    div\n    push r3\n    call .printdigit\n    dup\n    push 10\n    swap\n    sub\n    drop\n    jge .split\n    call .printdigit\n    call .newline\n    ret\n\n; push digit as parameter\n.printdigit\n    push 48\n    add\n    int 0 0\n    ret\n\n.newline\n    push 10\n    push 13\n    push 10\n    int 0 2\n    ret\n```\n\n## 💻 Command-Line Interface (CLI)\n\nThis project includes a **CLI tool** built with [Rust Clap](https://crates.io/crates/clap) to **compile** assembly code into binary and **execute** binary files on the VM.\n\nThe CLI provides two main commands: `compile` and `exec`.\n\n---\n\n### Installation\n\nAfter cloning the repository, build the CLI with Cargo:\n\n```bash\ncargo build --release\n```\n\nThe compiled executable will be in target/release/. You can run it directly:\n\n```bash\n./myvm [COMMAND] [OPTIONS]\n```\n\n### Commands\n\n#### 1. Compile\n\nCompiles an assembly source file into a binary that can be executed on the VM.\n\nUsage:\n\n```bash\n./myvm compile -p source.asm -o output.bin\n```\n\n##### Options\n\n| Option         | Description                      |\n| -------------- | -------------------------------- |\n| `-p, --path`   | Path to the source assembly file |\n| `-o, --output` | Path to the output binary file   |\n\nHow it works:\n\n* Reads the assembly file at the given path\n* Compiles it using the VM compiler\n* Writes a binary file with:\n  * Header: origin address (u32)\n  * Body: compiled bytecode (u32 per instruction)\n\n#### 2. Exec\n\nExecutes a compiled binary file on the VM.\n\nUsage:\n\n```bash\n./myvm exec -p output.bin --cells 2048 --stack 256\n```\n\nOptions:\n\n| Option        | Description                             | Default |\n| ------------- | --------------------------------------- | ------- |\n| `-p, --path`  | Path to the binary file                 | —       |\n| `-c, --cells` | Number of memory cells in the VM        | 2048    |\n| `-s, --stack` | Number of cells allocated for the stack | 256     |\n| `-d, --dump`  | Dumps the VM's memory layout to stdout  | false   |\n\nHow it works:\n\n* Reads the binary file\n* Parses the origin address from the header\n* Loads the bytecode into VM memory\n* Configures the VM memory and stack size\n* Sets the program counter to the origin\n* Executes instructions sequentially until `TERM` or an error occurs\n\n## 🛠️ Developer TODO / Roadmap\n\nThis project is a hobby but fully open for contributions. Here are some key areas to work on:\n\n- **Error Handling**  \n  - Detect and handle stack overflows, invalid memory access, and illegal opcodes  \n  - Provide descriptive runtime error messages\n\n- **Heap and Memory Management**  \n  - Implement dynamic memory allocation  \n  - Add garbage collection or memory reuse strategies\n\n- **IO Interrupt Module**  \n  - Expand module 0 functionality  \n  - Support reading input, printing formatted output, and file operations\n\n- **Network Interrupt Module**  \n  - Add network communication interrupts for sending/receiving data  \n  - Enable TCP/UDP support for simple network programs\n\n- **More unit tests**\n  - Write unit test for all modules and functions\n\n- **Code docs**\n  - Write better code docs\n\n- **Create a REPL**\n  - REPL in CLI","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedramcode%2Fmyvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedramcode%2Fmyvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedramcode%2Fmyvm/lists"}