{"id":15060567,"url":"https://github.com/tteeoo/svc","last_synced_at":"2026-02-27T17:06:51.038Z","repository":{"id":55589193,"uuid":"321175625","full_name":"tteeoo/svc","owner":"tteeoo","description":"🖥️ A 16-bit virtual machine with its own instruction set, assembler, and debugger.","archived":false,"fork":false,"pushed_at":"2021-06-17T00:35:25.000Z","size":234,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-21T22:09:51.805Z","etag":null,"topics":["16-bit","assembler","assembly","assembly-language","cpu","debugger","virtual-machine"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tteeoo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-13T22:45:15.000Z","updated_at":"2021-06-17T00:35:27.000Z","dependencies_parsed_at":"2022-08-15T03:50:26.358Z","dependency_job_id":null,"html_url":"https://github.com/tteeoo/svc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tteeoo%2Fsvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tteeoo%2Fsvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tteeoo%2Fsvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tteeoo%2Fsvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tteeoo","download_url":"https://codeload.github.com/tteeoo/svc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243695589,"owners_count":20332629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["16-bit","assembler","assembly","assembly-language","cpu","debugger","virtual-machine"],"created_at":"2024-09-24T23:00:24.788Z","updated_at":"2026-02-27T17:06:46.007Z","avatar_url":"https://github.com/tteeoo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simple Virtual Computer\n\nCurrently under development; this is a work in progress.\n\nA 16-bit virtual machine written in Go.\n\nIt uses word-based memory, where each memory address maps to a word-length value.\nThis means that while there are only 65,536 memory addresses,\nit technically has 128K of memory since each address points to a 16-bit value instead of a byte.\nThe reasoning for this is simple: simplicity. Most modern computer systems use bytes because they can be more flexible and efficient.\nThose are not the goals of this project.\n\nIt implements a \"VGA text mode\" that reads the contents of memory, using 2,000 contiguous words (which is interpreted as a 80x25 character display).\nIt translates the encoded VGA text colors into ANSI escape codes and prints the colorized ASCII text.\n\nThis repository contains the virtual machine, an assembler to compile programs for it, and a debugger for those programs.\n\n## Instruction Set\n\nThe instruction set resembles a RISC (Reduced Instruction Set Computer) architecture.\n\nIn the opcode, `r` represents the number of a CPU register that is packed into the word which contains the opcode to save memory.\n\n| Opcode   | Name  | Operands                               | Description                                                                                                                                               |\n| -------- | ----- | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `0x0000` | `nop` |                                        | Does nothing.                                                                                                                                             |\n| `0x01rr` | `cop` | `reg to copy to` `reg to copy from`    | Copies the value from one register to another.                                                                                                            |\n| `0x020r` | `cpl` | `reg` `value`                          | Copies a literal value to a register.                                                                                                                     |\n| `0x03rr` | `str` | `reg holding addr` `reg holding value` | Stores the value from a register into memory at the address held in another register.                                                                     |\n| `0x04rr` | `ldr` | `reg to load to` `reg holding addr`    | Loads the value from memory at the address held in one register into another register.                                                                    |\n| `0x050r` | `add` | `reg`                                  | Adds the value held in a register to the accumulator.                                                                                                     |\n| `0x060r` | `sub` | `reg`                                  | Subtracts the value held in a register from the accumulator.                                                                                              |\n| `0x070r` | `twc` | `reg`                                  | Sets a register to the two's complement of the value it holds.                                                                                            |\n| `0x080r` | `inc` | `reg`                                  | Increases the value held in a register by one.                                                                                                            |\n| `0x090r` | `dec` | `reg`                                  | Decreases the value held in a register by one.                                                                                                            |\n| `0x0A0r` | `mul` | `reg`                                  | Multiplies the accumulator with the value held in a register.                                                                                             |\n| `0x0B0r` | `div` | `reg`                                  | Divides the accumulator by the value held in a register, storing the modulus in the `ex` register.                                                        |\n| `0x0C0r` | `dcv` | `reg`                                  | Divides the accumulator by the value held in a register, taking into account two's complement negative numbers, storing the modulus in the `ex` register. |\n| `0x0D0r` | `xor` | `reg`                                  | Performs the \"xor\" operation on the accumulator with the value held in a register.                                                                        |\n| `0x0E0r` | `and` | `reg`                                  | Performs the bitwise \"and\" operation on the accumulator with the value held in a register.                                                                |\n| `0x0F0r` | `orr` | `reg`                                  | Performs the bitwise \"or\" operation on the accumulator with the value held in a register.                                                                 |\n| `0x100r` | `not` | `reg`                                  | Inverts the value held in a register.                                                                                                                     |\n| `0x110r` | `shr` | `reg` `value`                          | Shifts the value held in a register to the right by a specified value.                                                                                    |\n| `0x120r` | `shl` | `reg` `value`                          | Shifts the value held in a register to the left by a specified value.                                                                                     |\n| `0x1300` | `vga` |                                        | Prints the VGA text buffer to the screen.                                                                                                                 |\n| `0x140r` | `psh` | `reg`                                  | Decreases the stack pointer and sets the top value of the stack to the value held in a register.                                                          |\n| `0x150r` | `pop` | `reg`                                  | Stores the top value of the stack in a register and increases the stack pointer.                                                                          |\n| `0x1600` | `ret` |                                        | Pops the program counter off of the stack.                                                                                                                |\n| `0x1700` | `cal` | `addr`                                 | Pushes the program counter onto the stack and sets the program counter to an address.                                                                     |\n| `0x18rr` | `cmp` | `reg` `reg`                            | If the values of two registers are the same, the boolean index (`bi` register) is set to `0xffff`, else `0xfffe`.                                         |\n| `0x1900` | `cle` | `addr`                                 | Equivalent to `cal`, but only executes if the `bi` register is set to `0xffff`.                                                                           |\n| `0x1A00` | `cln` | `addr`                                 | Equivalent to `cal`, but only executes if the `bi` register is set to `0xfffe`.                                                                           |\n| `0x1B00` | `gto` | `addr`                                 | Sets the program counter to an address.                                                                                                                   |\n| `0x1C00` | `gte` | `addr`                                 | Equivalent to `gto`, but only executes if the `bi` register is set to `0xffff`.                                                                           |\n| `0x1D00` | `gtn` | `addr`                                 | Equivalent to `gto`, but only executes if the `bi` register is set to `0xfffe`.                                                                           |\n| `0x1E0r` | `cml` | `reg` `value`                          | Equivalent to `cmp`, but the second operand is a literal value, not a register.                                                                           |\n\n## CPU Registers\n\nThere are 12 CPU registers, 8 of which are general purpose.\n\n| Number | Alias | Purpose                                                                                                     |\n| ------ | ----- | ----------------------------------------------------------------------------------------------------------- |\n| `0x0`  | `ra`  | General purpose; used for whatever you desire.                                                              |\n| `0x1`  | `rb`  | General purpose.                                                                                            |\n| `0x2`  | `rc`  | General purpose.                                                                                            |\n| `0x3`  | `rd`  | General purpose.                                                                                            |\n| `0x4`  | `re`  | General purpose.                                                                                            |\n| `0x5`  | `rf`  | General purpose.                                                                                            |\n| `0x6`  | `rg`  | General purpose.                                                                                            |\n| `0x7`  | `rh`  | General purpose.                                                                                            |\n| `0x8`  | `ex`  | Extra: holds extra arithmetic output values, used for register expansions (`(value)` syntax).               |\n| `0x9`  | `ac`  | Accumulator: holds the output of most arithmetic operations.                                                |\n| `0xa`  | `sp`  | Stack pointer: holds the address of the top location in memory of the stack.                                |\n| `0xb`  | `pc`  | Program counter: holds the address of the next instruction in memory to be executed.                        |\n| `0xc`  | `bi`  | Boolean index: set to `0xffff` if the last cmp was equal, else `0xfffe`.                                    |\n\n## The Simple Virtual Assembler\n\nThe assembler reads a rudimentary assembly language and outputs a binary format called \"svb\".\nSee the [`sva` directory](https://github.com/tteeoo/svc/tree/main/sva) for documentation on writing in the assembly language and using the assembler.\n\nSee the [`svd` directory](https://github.com/tteeoo/svc/tree/main/svd) for using the debugger and the [`asm` directory](https://github.com/tteeoo/svc/tree/main/asm) for some example programs.\n\n## Memory\n\nSections:\n* VGA text buffer: `0x00`-`0x7d0`\n* Stack: `0x7d1`-`0x8ff`\n* Program (varies in size): `0x900`-`0xX`\n* Heap (everything else): `0xX+1`-`0xffff`\n\nBefore the CPU starts execution, a few things are done in memory:\n* The value `0xffff` is pushed onto the stack. It will be pulled off with the \"main\" subroutine's `ret` instruction. When the program counter is set to `0xffff` the virtual machine will stop.\n* The command-line arguments are loaded into the heap. (The heap is just all of the memory that doesn't have a specific purpose.)\n* The word at `0xfffd` is set to the number of command-line arguments.\n* The word at `0xfffe` is set to the size of the command-line arguments (number of characters + null terminators).\n* The word at `0xffff` is set to the address of the start of the heap.\n\n## To Do\n\n* More example programs and documentation.\n* Better tests (ones that actually exist).\n* Keyboard input.\n* Virtual drive with simple filesystem.\n\n## License\n\nThe contents of this repository are made available under the Unlicense, a public domain equivalent license.\n\nSee the [`LICENSE` file](https://github.com/tteeoo/svc/tree/main/LICENSE) for its text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftteeoo%2Fsvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftteeoo%2Fsvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftteeoo%2Fsvc/lists"}