

Simple virtual machine - ranit8
http://syprog.blogspot.com/2011/12/simple-virtual-machine.html

======
gavanwoolery
Interesting...some things to consider when building a VM (not this particular
one, but in general -- and I am by no means an expert, and could be wrong on
some of these things, although I have built my own compiler and VM from the
ground up):

If possible, avoid shorts, bytes, and compressed byte code. Most CPUs work
with 32 and 64 bit numbers, and they will convert bytes/shorts to 32 bits
usually, which takes time (your compiler may do this regardless, depending on
optimization, but anyhow it keeps your VM smaller and cleaner). Also, your VM
would need to support every permutation of action (add a byte to an int, a int
to a short, etc). Also, compressing an instruction into a 32 bit or 64 bit
space is adverse to performance. Memory is plentiful enough (both RAM and
cache) that you should not bother with this unless you are targeting an
embedded device or something.

Use enums for your op codes, and a switch statement (depends on compiler). If
you use enums and a switch, the compiler can generate a jump table because it
knows the enum will always be in a certain range. Much better performance than
a bunch of if/else statements.

It is possible to write a VM that only uses floating point numbers, if you
want to keep the VM as small and simple as possible. This means casting the
floats for things like addressing, but otherwise I think it might perform
well.

~~~
Chirono

      Use enums for your op codes, and a switch statement (depends on compiler). If you use enums and a switch, the compiler can generate a jump table because it knows the enum will always be in a certain range. Much better performance than a bunch of if/else statements.
    

You can generate some beautifully simple interpreters this way, but
switch/dispatch is not the way to go for high performance. Jump tables like
that are not a good candidate for optimisation by compilers and they kill any
sort of branch prediction your CPU is doing.

Here's an post (and follow up discussion) by the author of the Lua, where he
explains why the main loop is written in assembler and why it beats compilers:

<http://news.ycombinator.com/item?id=2588696>

~~~
Estragon

      > the author of the Lua
    

Actually of LuaJIT. (I was confused, because Lua takes great pains to stick to
highly portable C code.)

------
jim_lawless
From the post:

"I would like to touch a slightly different application of this technology -
protect your software/data from being hacked."

I wrote something similar that I posted to my blog a couple of years ago ( my
blog post is titled "An Embedded Mini Interpreter" ).

While I had tinkered with making my own VM's with elaborate file-formats, the
only data-structure I used for my VM was an array of integers that acted as
indices to functions in a C program and an index to the array element next in
line to be interpreted.

The interpreter would begin at the top of the array and would issue the
function relative to the number in the current integer in the array. For some
functions, I would encode data in the integer array. For the sake of example,
I simply encoded a string for a "print string" function as a single character
in each successive integer slot.

~~~
RodgerTheGreat
You've applied/discovered a technique called Threaded Code[1], common in Forth
implementations and the basis of Return-Oriented Programming[2]. :)

    
    
      [1]http://en.wikipedia.org/wiki/Threaded_code
      [2]http://en.wikipedia.org/wiki/Return-oriented_programming

