Building a VM in Ruby

Codegram Lightning Talks

Txus (@txustice) - Twitter, GitHub

What is a VM anyway?

Stack-based vs Register-based

Stack-based VMs

Register-based VMs

VMs are (practically) language-agnostic

Bytecode format

Let's build our own!

But first, let's define what a program for our VM will look like.

Typical procedural program: many routines, one of them being the main entry point.

Now, what does one of these functions look like?

Literals are all user-entered values (strings or fixnums) used inside this function code.

Locals are all local variables used in the function (including the arguments passed to it).

The instructions are formed by an opcode and one operand (in other VMs there may be more operands).


As an example, a function that adds 42 and 5 and returns the result will have 0 locals, its literal table will have two elements (42 and 5) and its instructions will be the following:

push_literal 0
push_literal 1

We push literals 0 and 1 because those are indexes to the literals table (the 0 is the first element and the 1 is the second).

The final "ret" is essential to every function. It tells it to return to the caller the topmost value on the stack (in this case the result of adding 42 and 5).

Introducing MC: our bytecode format


Instruction set

  • 0:push_literal [literal_idx]
  • 1:push_local [local_idx]
  • 3:add
  • 7:call [num_args]
  • 8:ret

_foo_ indicates the start of a function called "foo", and :elem,elem2,elem3 declares a literal table of three elements.

Execution steps

  1. Load a program file.
  2. Parse it and create all the functions.
  3. Find the main function and execute it in a new call frame.
  4. Apply each instruction to the call frame stack. If we find...
    • "call": We execute a function in a new call frame and wait for it to return.
    • "ret": Return the topmost element on the stack to our caller. If we've consumed all the call frames, program terminates printing the returned value.

You are now aware that...

our newly built VM is called MicroVM.

Sunday afternoon. One hour. Less than 150LOC (< 4kb).
$ wget
$ chmod +x microvm
$ wget
$ ./microvm

Go check out the code!

Problem? (I mean, questions?)

By Txus (@txustice) - Twitter, GitHub
Use spacebar or the arrow keys to navigate
See all slides