This is a design for a Virtual Processor Generator. It does not include a Virtual FS.
To obtain

pastebin get jEXWy15Z vms/VM
.
To use, you need to create a new VM. Do this by calling
myVM = VM.initVM([i]name[/i])
. Name doesn't matter.
This will return a Virtual Machine object.
In order to add an operation, you need to call
myVM:addOp({numops=[i]number of operands[/i],opsizes={[i]size of op1 in bytes, [/i][i]size of op2 in bytes,..., [/i][i]size of opn in bytes[/i]},resolve=function(op1,op2,...,opn)[i]code to run[/i]; return [i]values to push onto the stack[/i];end});
To push values onto the stack, call myVM:push(e). e must be a number. To pop a single byte call myVM:pop(). To pop more than one use myVM:pops(size) (size goes up to 8 for 64 bit). The VM provides many utilities, such as coercion between references and pointers in its refPool. References are functions, strings, tables, and threads (and technically userdata, but as far as I know, CC's Lua does not have userdata). To coerce them in both directions call myVM:toPtr(ref) or myVM:toRef(ptr). To coerce a byte to a boolean or vice-versa, involves simply calling myVM:toByte(bool) or myVM:toBool(byte). But you can also achive this on your own via
 (to byte) val and 1 or 0. (to boolean) val == 1 and true or false 
Finally, rather than require you to directly interact with the call-stack (which this architecture keeps separate from the value stack), there are 2 jump functions (one with return (ie. CALL), and one without return (IE. JMP or GOTO)), and one return. myVM:call(addr) jumps to an address and stores the current addr, to the call stack. myVM:jumpNR(addr) jumps to an address, but does not push the current addr to the call stack. myVM:ret() returns to the last address on the call stack. This is actually achieved via jumpNR.
To add a new file to the system call myVM:loadFile(file). The file is a pathname to code to append to the end of data.
Stopping the VM is as easy as calling myVM:stop();
When you finish adding operations, call myVM:readyVM(file). The file is the pathname to the Virtual Machine Code used to run the system.
You can ready a VM while its Initialized or Dead.
The file is added to the set of data, then resets the state of the VM, but does not clean the list of operations.
Finally when you populate with its data, you can call myVM:startVM(). This will return when myVM:stop() occurs, or an error is thrown. There is no protection in place, so wrapping it with pcall, might be in order.

Finally, a notice: The VM system was not made with CC in mind. The code is cross compatible with all implementations of lua which support 5.1. As it stands, the only direct utilities it uses are the global print (in printInfo, used to print all info about the VM), and the io library. This code will work in CC though.