"interesting" VM in C. Let's see how this goes.
I have since started slow work on a more stable, better thought-out project called RabbitVM. It doesn't quite have the same level of documentation but it should work much better.
This is a project I've been slowly working on for about half a year now. The goal is to try and build a small (and decently reliable) VM from the ground up, learning more and more C as I go.
Right now there are instructions, registers, a stack, data memory, and calls. Not sure if recursion works... it should in theory. Haven't tested.
CONSIDER THIS PRE-ALPHA SOFTWARE. Things change more than they do in Rust!
If you already have a local copy (cloned before submodule was added)
git fetchgit rebasegit submodule initgit submodule updateIf you don't already have a local copy
git clone --recursiveNOTE: If git submodule status doesn't return a SHA1 hash and repository name, you have a problem.
NOTE: Recursive clone is for testing library. If not included, tests will not build.
makemake test (optional)make installmake clean (optional)| Arch (bit) | OS (with version, name) | Compiler (with version) |
|---|---|---|
| 64-bit | Ubuntu 12.04 (precise) | gcc 4.6.3 |
| 64-bit | Ubuntu 14.04 (trusty) | gcc 4.8.2 |
| 32-bit | Ubuntu 14.04 (trusty) | gcc 4.8.2 |
| 64-bit | OS X 10.9.4 (Mavericks) | clang 3.2 |
| 32-bit | OS X 10.9.4 (Mavericks) | gcc 4.2.1 |
| 64-bit | Arch Linux 3.13.6-1 | clang 3.4.2 |
| 64-bit? | Arch Linux 3.13.6-1 | gcc 4.9.0 20140604 |
NOTE: See carp -h for help with command-line options.
./carp.out -f your_file.carp.carp/carp_machine.h in your program.gcc program.c /usr/local/lib/libcarp.a -o program.out.| Opcode | Arguments | Description |
|---|---|---|
| HALT | exit code | Sets ext to given code, halts, and attempts to clean up stack, data memory, and label memory. |
| NOP | Does nothing. Seriously. | |
| LOADR | reg, val | Loads given integer value into given register. |
| LOAD | diff | Loads value at location fp + diff in the stack. |
| STORE | diff, val | Stores value at location fp + diff. |
| MOV | dst, src | Copies contents of src register into dst register. |
| ADD | Pops the top two integers from the stack and pushes their sum. | |
| SUB | Pops the top two integers from the stack and pushes the difference (lower minus upper). | |
| MUL | Pops the top two integers from the stack and pushes their product. | |
| MOD | Pops the top two integers from the stack and pushes lower % upper. | |
| SHR | Pops the top two integers from the stack and pushes lower >> upper. | |
| SHL | Pops the top two integers from the stack and pushes lower upper. Pushes result. | |
| JZ | addr | Jumps to given absolute address if top of the stack is 0. |
| RJZ | diff | Adds differential to ip (relative jump) if top of the stack is 0. |
| JNZ | addr | Jumps to given absolute address if top of the stack is not 0. |
| RJNZ | diff | Adds differential to ip (relative jump) if top of the stack is not 0. |
| JMP | addr | Jumps to given absolute address unconditionally. |
| RJMP | diff | Adds differential to ip (relative jump) unconditionally. |
| CALL | key/addr | Save state and set IP to value in data memory at key. Function may return value in ax. |
| RET | Put top of the stack into ax and load previous state. |
|
| PREG | reg | Prints contents of given register. |
| PTOP | Peeks top of stack and prints top value. |
| Name | Purpose |
|---|---|
r0 ... r9 |
General purpose. |
ax |
Return value for user-defined function. |
bx, cx, dx, rx |
... something in the future. Just taking up space for now. |
ip |
Instruction pointer. Used for keeping place in code, gotos, calling, etc. |
sp |
Stack pointer. |
fp |
Frame pointer. Used to keep state for function calls. |
gbg |
Garbage register mainly used for popping. |
run |
Boolean - is machine running? |
ext |
Exit code. |
One way:
Another way:
GPLv3. See LICENSE.txt.
No open issues yet, or sync has not completed.