"interesting" VM in C. Let's see how this goes.

Overview

THIS PROJECT IS UNSTABLE AND DEPRECATED

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.

CarpVM

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!

Build Status     Flattr this

Installation

Getting Carp

If you already have a local copy (cloned before submodule was added)

  • git fetch
  • git rebase
  • git submodule init
  • git submodule update

If you don't already have a local copy

  • git clone --recursive

NOTE: 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.

Building Carp

  1. make
  2. make test (optional)
  3. make install
  4. make clean (optional)

Tested Machines

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

Use

NOTE: See carp -h for help with command-line options.

Interpreter

  1. Write a Carp file - see SYNTAX.md. More formal spec coming.
  2. Run ./carp.out -f your_file.carp.

API

  1. Include carp/carp_machine.h in your program.
  2. Run gcc program.c /usr/local/lib/libcarp.a -o program.out.

Instruction set

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.
NOT Pops top integer from stack and pushes bitwise NOT of that integer.
XOR Pops the top two integers from the stack and pushes bitwise XOR..
OR Pops the top two integers from the stack and pushes bitwise OR.
AND Pops the top two integers from the stack and pushes bitwise AND.
INCR reg Increments value in given register.
DECR reg Decrements value in given register.
INC Increments the value at the top of the stack.
DEC Decrements the value at the top of the stack.
PUSHR reg Pushes value in given register.
PUSH val Pushes given value.
POP reg Pops an integer from the stack and dumps it into given register.
CMP Pops the top two integers from the stack and checks if equal. 0 means equal. Pushes result.
LT Pops the top two integers from the stack and checks if lower < upper. Pushes result.
GT Pops the top two integers from the stack and checks if 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.

Registers

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.

How to contribute

One way:

  1. Check out the TODO.md file to see if anything needs doing.
  2. Write some code (following existing implicit style) and submit a pull request.

Another way:

  1. Write some code for a feature you want to exist and submit a pull request.

License

GPLv3. See LICENSE.txt.

Comments
  • use chaining for carp_ht instead of linear probe, fix resize

    use chaining for carp_ht instead of linear probe, fix resize

    seemed to work, and printing was updated to reflect chained entries. still some memory leaks in carp_ht_cleanup. just realized that carp_ht_resize is fine for leaks bc the pointers have ownership transferred to the new table. neat!

    opened by Jumhyn 20
  • Fix examples

    Fix examples

    Hi there,

    078a901e703f4a6965346573a6bef14f5deca5b6 fixed compilation problem, however I can't still run carp examples.

    $ ./carp.out -f examples/carp/reg.carp
    Unknown label <add>    
    

    I assume they're not fully implemented yet.

    opened by cengizIO 15
  • Tokenizer/lexer issue

    Tokenizer/lexer issue

    On Arch Linux with GCC 4.9.1:

    λ athena carp → ./carp -f examples/carp/reg.carp
    [0000]   add (  lbl) =    1
    [0001]  load (instr) =    3
    [0002]    -4 (  num) =   -4
    [0003]  load (instr) =    3
    [0004]    -3 (  num) =   -3
    [0005]   add (instr) =    6
    [0006]   pop (instr) =   22
    [0007]    ax (  reg) =   10
    [0008]   ret (instr) =   33
    [0009]  main (  lbl) =    1
    [0010] loadr (instr) =    2
    [0011]    r0 (  reg) =    0
    [0012]     7 (  num) =    7
    [0013] pushr (instr) =   20
    [0014]    r0 (  reg) =    0
    [0015] loadr (instr) =    2
    [0016]    r1 (  reg) =    1
    [0017]     9 (  num) =    9
    [0018] pushr (instr) =   20
    [0019]    r1 (  reg) =    1
    [0020]  call (instr) =   32
    Unknown label <aasd>
    

    Not entirely sure what is going on.

    bug 
    opened by tekknolagi 6
  • Compilation issue in Cygwin

    Compilation issue in Cygwin

    Just wanted to let you know of an issue present when I try to build this on Cygwin 64 bit I run "make" and I get this output:

    cc -c -g3 -std=c99 -Wall -Werror -Wno-unused-variable -Wno-format-security src/ carp_registers.c src/carp_instructions.c src/carp_lexer.c src/carp_machine.c src /carp_tokenizer.c src/lib/carp_stack.c src/lib/carp_ht.c src/carp_tokenizer.c: In function ‘is_num’: src/carp_tokenizer.c:159:3: error: array subscript has type ‘char’ [-Werror=char -subscripts] if (!(is_sign(s[0]) || isdigit(s[0]))) return 0; ^ src/carp_tokenizer.c:162:5: error: array subscript has type ‘char’ [-Werror=char -subscripts] if (!isdigit(s[i])) return 0; ^ cc1: all warnings being treated as errors Makefile:17: recipe for target 'build' failed make: *** [build] Error 1

    opened by stochastic-thread 5
  • Possible bug with jnz instruction

    Possible bug with jnz instruction

    The following example prints out the first 10 Fibonacci numbers, starting with zero.

    main:
      loadr r2, 10
      loadr r0, 0
      loadr r1, 1
      preg r0
      pushr r0
      pushr r1
      add
      mov r0, r1
      pop r1
      decr r2
      pushr r2
      jnz 9
      halt 0
    

    However, it fails with this output when the 10th number is reached.

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34
    Carp stack is empty.
    Carp stack is empty.
    

    I'm not entirely sure, but it looks like the jnz 9 instruction causes the mod instruction to be executed after register r2 reaches zero. The numeral 9 corresponds with the 9th value in the carp_instr enum.

    Any thoughts?

    opened by jbcrail 3
  • Compilation issue in Elementary OS

    Compilation issue in Elementary OS

    Running make yields:

    cc -c -g3 -std=c99 -Wall -Werror -Wno-unused-variable -Wno-format-security src/carp_registers.c src/carp_instructions.c src/carp_lexer.c src/carp_machine.c src/carp_tokenizer.c src/lib/carp_stack.c src/lib/carp_ht.c ar cr libcarp.a .o cc -g3 -std=c99 -Wall -Werror -Wno-unused-variable -Wno-format-security src/carp.c libcarp.a -o carp.out find . -name ".o"
    -o -name "_.dSYM"
    | xargs rm -rf cd tests/libtap && make make[1]: Entering directory /home/arthur/Projects/Github/carp/tests/libtap' make[1]: *_\* No targets. Stop. make[1]: Leaving directory/home/arthur/Projects/Github/carp/tests/libtap' make: *** [libtap] Error 2

    opened by stochastic-thread 3
  • NULL pointer dereference in carp_vm_make()

    NULL pointer dereference in carp_vm_make()

    https://github.com/tekknolagi/carp/blob/master/src/carp_machine.c#L52 dereferences res although https://github.com/tekknolagi/carp/blob/master/src/carp_machine.c#L49 checked for res == NULL and https://github.com/tekknolagi/carp/blob/master/src/carp_machine.c#L50 certainly doesn't quit Carp.

    opened by fredmorcos 2
  • Fails to build...

    Fails to build...

    The current code has two definitions of the MOV instruction, which causes compilation to fail.

     src/carp_instructions.h:29:1: error: redeclaration of enumerator ‘CARP_INSTR_MOV’
     src/carp_instructions.h:12:1: note: previous definition of ‘CARP_INSTR_MOV’ was here
    

    (If you look at src/carp_instructions.c you'll also find two different implementations.)

    Relatedly the REM instruction is undeclared.

    opened by skx 2
  • docs: fix simple typo, thuogh -> though

    docs: fix simple typo, thuogh -> though

    There is a small typo in SYNTAX.md.

    Should read though rather than thuogh.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 1
  • isolate libtap from carp

    isolate libtap from carp

    It looks that some of us (including me :) ) failed to compile Carp since they didn't get the libtap recursively from its repo. I would suggest one of these: 1- remove this dependency from Carp sources and dynamically build the tests against libtap .. so this must be mentioned explicitly. 2- use another test library .. this may encourage us to move to CMake and CTest. 3- keep libtap in the Carp sources, but enhance the readme, and explicitly mention that the recursive step is for libtap, and tests won't be built successfully.

    opened by khaledmdiab 1
  • Miscellaneous cleanup

    Miscellaneous cleanup

    Build was broken and a test was failing on my machine.

    You might want to go over the entire codebase and initialize all uninitialized local variables. Otherwise we're basically playing russian roulette :)

    opened by akkartik 1
  • strtok function?

    strtok function?

    There is something in the below I don't understand...to me the result of strtok is redundant because its inputs are constants. Is there something I am missing out?

    See https://github.com/tekknolagi/carp/blob/master/src/carp_tokenizer.c#L112

    toks = strtok(NULL, delim);
    
        if (toks != NULL) {
          parsed->next = malloc(sizeof *parsed->next);
          lookbehind = parsed;
          parsed = parsed->next;
        }
    
    opened by janus 1
  • A redundant asserts

    A redundant asserts

    Just noticed that assert macro was used twice on the same argument without change of state, any reason for this? Could be found inside carp_reg_inc and carp_reg_dec (https://github.com/tekknolagi/carp/blob/master/src/carp_registers.c#L89):

    carp_bool carp_reg_inc (carp_value regs[], carp_reg reg) {
      assert(regs != NULL);
    
      assert(regs != NULL);
    
    opened by janus 1
  • compilation error on ubuntu 14.04

    compilation error on ubuntu 14.04

    I am using my ubuntu 14.04 virtual machine to compile carp. The used compiler is gcc 4.8.2, I tried gcc 4.6 but got the same error:

    cc -c -g3 -std=c99 -Wall -Werror -Wno-unused-variable -Wno-format-security -static  src/carp_instructions.c src/carp_lexer.c src/carp_machine.c src/carp_tokenizer.c src/lib/carp_stack.c src/lib/carp_ht.c
    src/carp_instructions.c: In function ‘carp_instr_DBS’:
    src/carp_instructions.c:144:15: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
       char *key = (char *) carp_vm_next(m);
                   ^
    src/carp_instructions.c: In function ‘carp_instr_DBG’:
    src/carp_instructions.c:153:15: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
     char *key = (char *) carp_vm_next(m);
                 ^
    cc1: all warnings being treated as errors
    make: *** [build] Error 1
    
    opened by khaledmdiab 29
  • Compiler for Carp

    Compiler for Carp

    I have taken a look at the CARP instruction set and the basic implementation. I consider myself to be proficient in C and C++, and am volunteering to create a compiler fork/branch.

    Suggestions:

    1. Write the compiler in C++ using LLVM as a backend, allowing for maximum flexibility.
    2. Compile CARP to C and leverage existing C compilers.

    A note: When compiling to another language, for example LLVM IR or C, due to the inherent nature of a stack VM, constant folding is trivial. At compile-time. The compiler will have to make tradeoffs between how many operations (e.g. addition, bitwise, etc.) it will do at compile time or how many it will relegate to the backend for code generation.

    opened by firebolt55439 3
Owner
Max Bernstein
Biking around
Max Bernstein
checkedthreads: no race condition goes unnoticed! Simple API, automatic load balancing, Valgrind-based checking

checkedthreads checkedthreads is a fork-join parallelism framework for C and C++ providing: Automated race detection using debugging schedulers and Va

Yossi Kreinin 279 Nov 4, 2022
This is a OOSDK port of flat's ps4_remote_pkg_installer, all credit goes to them and their amazing work!

ps4_remote_pkg_installer-OOSDK This is a OOSDK port of flat's ps4_remote_pkg_installer, all credit goes to them and their amazing work! NOTES Some fun

null 28 Nov 2, 2022
Not related to software bugs and exploits; this repo contains snippets of code that demonstrate some interesting functionality or a handy trick.

Proof-of-Concept Not related to software bugs and exploits; this repo contains snippets of code that demonstrate some interesting functionality or a h

Alisa Esage 32 Nov 19, 2022
weggli is a fast and robust semantic search tool for C and C++ codebases. It is designed to help security researchers identify interesting functionality in large codebases.

weggli is a fast and robust semantic search tool for C and C++ codebases. It is designed to help security researchers identify interesting functionality in large codebases.

Google Project Zero 2k Dec 1, 2022
A INTERESTING CHESS GAME

War Game 一个有趣的棋类游戏。 玩法 在一个地图中,双方预先设置好各自大本营的位置以及地图上的地形。 放置、移动兵种,攻击对方的兵,或是生产更多的兵。 击破对方的大本营,获得游戏的胜利。 操作 在 map.txt 中保存你的地图。 打开游戏后,首先放置双方的大本营,然后左键点击大本营中的某一

null 2 Sep 27, 2021
A play around of mathematical functions to draw interesting objects to the screen.

LibDragonN64 Color Graphics Test A play around of mathematical functions to draw interesting objects to the screen. Compile Script (Windows only) In V

null 1 Dec 11, 2021
Lets try out a few ways to easily create a modern Win32 UI app

UI-Experiments Lets try out a few ways to easily create a modern Win32 UI app This is a VS2019 solution with a handful of single projects, each one tr

Tammo 'kb' Hinrichs 21 Dec 6, 2021
Flutter package that lets you simply animate a widget into a visible state.

Entry This Flutter package introduces a new widget : Entry. It lets you simply animate a widget into a visible state. Don't just display widgets : mak

Mickaël Hernandez 25 Aug 14, 2022
Björn Kalkbrenner 36 Oct 10, 2022
An SSH file manager that lets you edit files like they are local

An SSH file manager that lets you edit files like they are local

Allan Boll 480 Nov 21, 2022
Ipsys Particle System Yey letS go, very cool particle system generator and fast renderer

ipsys - Ipsys Particle System Yey letS go About Ipsys is a piece of software that focuces on running and displaying cool randomly generated particule

Anima Libera 5 May 26, 2022
Lets be creative this hacktober fest. Get started with contributing to open source.

Be Creative this Hacktoberfest 2021 Lets be creative this hacktober fest. Get started with contributing to open source. ?? Web-Ideas ?? How Can I Cont

B L A C K F U R Y 17 Oct 31, 2022
A Geometry Dash mod that lets you select the screen to run the game on

Screen Selector A mod that lets you select the screen to run Geometry Dash on Fully compatible with Mega Hack v6 (except the "Fullscreen" and "Borderl

ConfiG 8 Jun 3, 2022
Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS.

?? Available Translations: ???? ???? ???? ???? ???? ???? ???? ???? . View these docs in other languages at electron/i18n. The Electron framework lets

Electron 104.7k Dec 1, 2022
A npm package that lets you automate your windows desktop.

js-macro A npm package that lets you automate your windows desktop. npm i js-macro Examples Simple cursor usage const { cursor } = require("js-macro"

5 Jul 30, 2022
A npm package that lets you automate your windows desktop.

js-macro A npm package that lets you automate your windows desktop. npm i js-macro Examples Simple cursor usage const { cursor } = require("js-macro"

5 Jul 30, 2022
CodeSpeak is a web-based code editor that lets users code with the power of their voice

Welcome to CodeSpeak! CodeSpeak is a web-based code editor that lets users code with the power of their voice. It's currently in an embryonic stage, b

Seth Wilson 134 Jun 4, 2022
C++ (with python bindings) library for easily reading/writing/manipulating common animation particle formats such as PDB, BGEO, PTC. See the discussion group @ http://groups.google.com/group/partio-discuss

Partio - A library for particle IO and manipulation This is the initial source code release of partio a tool we used for particle reading/writing. It

Walt Disney Animation Studios 411 Nov 23, 2022
https://github.com/json-c/json-c is the official code repository for json-c. See the wiki for release tarballs for download. API docs at http://json-c.github.io/json-c/

\mainpage json-c Overview and Build Status Building on Unix Prerequisites Build commands CMake options Testing Building with vcpkg Linking to libjson-

json-c 2.6k Nov 28, 2022