The VM is register-based, which means arithmetic operations work with registers directly rather than a stack. This makes it faster and more similar to how real CPUs work.
- 32 general-purpose registers
- 512KB heap for memory operations
- 8KB stack for function calls
- Flags register (zero and negative flags)
Instructions use registers as operands, though the exact format varies per instruction. Arithmetic and bitwise operations work directly on registers, since this is more efficient than stack-based approaches.
ADD,SUB,MUL,DIV,MOD- Standard arithmetic.- All take three registers: destination and two source operands.
- Example:
ADD r0, r1, r2computesr0 = r1 + r2
AND,OR,XOR- Binary logic operations- Takes three registers: destination and two source operands
NOT- One's complement (bitwise negation)- Takes two registers: destination and source
ShiftLeft,ShiftRight- Logical shifts (zeros fill empty bits)- Takes three registers: destination, source, and shift amount (from register)
ShiftRightArithmetic- Arithmetic shift right (preserves sign bit)- Takes three registers: destination, source, and shift amount (from register)
LoadImmediate- Load a constant value directly into a register (8-byte immediate)LoadRegister- Copy value from one register to anotherLoadMemory- Load from heap address (address in register) into registerStoreMemory- Store register value to heap address
JmpImmediate,JmpRegister- Unconditional jumps to address- Conditional jumps based on register value (check if a register value is zero):
JmpImmediateIfZero,JmpImmediateIfNotZero- Takes register to check + immediate address
JmpRegisterIfZero,JmpRegisterIfNotZero- Takes register to check + register with address
- Conditional jumps based on flags (set by
CMPinstruction):JmpImmediateIfEqual,JmpImmediateIfNotEqual,JmpImmediateIfGreater,JmpImmediateIfGreaterOrEqual,JmpImmediateIfLess,JmpImmediateIfLessOrEqual- Takes immediate address (no register argument, just checks flags)
JmpRegisterIfEqual,JmpRegisterIfNotEqual,JmpRegisterIfGreater,JmpRegisterIfGreaterOrEqual,JmpRegisterIfLess,JmpRegisterIfLessOrEqual- Takes register with address (checks flags)
CallImmediate,CallRegister- Function calls that push return address to stack
Return- Pop return address and jump back
Push- Push register value onto stack (for function call conventions)Pop- Pop stack value into register
CMP- Compares two registers and sets flags for conditional jumpsHALT- Stop VM execution gracefullyNOP- No operation
import "github.com/Dobefu/vee-em"
program := []byte{
// Your bytecode instructions here
}
v := vm.New(
program,
vm.WithMagicHeader([]byte("VEE-EM")),
)
err := v.Run()
if err != nil {
log.Fatalf("Error running VM: %s", err.Error())
}Check out the tests in run_test.go for examples of how to construct programs.