vermin_vm
A Virtual Machine + Assembler written in C
SPECS:
REGISTORS
Naming format: R* [ex: R0, R1, ..., R15]
Each registor is 64 bit in size
Accessing specific parts of registors:
Entire registor : R* [ex: R0, R1, ...]
Lower 32-bits : RLH [ex: R0LH, R1LH, ...]
Upper 32-bits : RUH [ex: R0UH, R1UH, ...]
Lower 16-bits of Lower 32-bit : RLQ [ex: R0LQ, R1LQ, ...]
Upper 16-bits of Lower 32-bit : RUQ [ex: R0UQ, R1UQ, ...]
Lower 8-bits of Lower 16-bit : RLT [ex: R0LT, R1LT, ...]
Upper 8-bits of Lower 16-bit : RUT [ex: R0UT, R1UT, ...]
Registor representation:
A registor is representated by a 32 bit integer:
Bits | Purpose |
---|---|
0 - 8 | ID [0 - 15] |
9 - 16 | Size [64 (8), 32 (4), 16 (2), 8 (1)] |
17 - 24 | Lower / Upper part [Lower (0), Upper (1)] |
25 - 32 | Registor Local offset [8-bit integer] |
Sepcial Registors:
Registers | Purpose |
---|---|
R15 | Instruction pointer |
R14 | Stack start pointer |
R13 | Stack top pointer |
R12 | Heap start pointer |
R8 to R11 | Reserved |
MEMORY LAYOUT
ADDRESS INCREASES DOWNWARDS |
---|
BEGIN |
R14 |
STACK |
R13 |
R12 |
HEAP |
END |
Assembly Instructions:
Each instruction has the following format:
[8-bit id][8-bit size in bytes][16-bit sub params] [32 x n-bit params]
NOTE: First 32 bits are compulsory
NOP
ID = 0
Size = 4
SubParams = NULL
MOV
ID = 1
Size = 4 + 2 * 4 [ = 12]
SubParams [first 8 bits] = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3), Reg to Reg Memory (4)
SubParams [second 8 bits] = size to move in bytes
Params = 2
Moves data from param 2 to param 1
ADD
ID = 2
Size = 4 + 2 * 4 [ = 12]
SubParams = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3)
Params = 2
Adds content of param 2 and 1 (1 + 2) and stores in 1
SUB/CMP
ID = 3
Size = 4 + 2 * 4 [ = 12]
SubParams = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3)
Params = 2
Subs content of param 2 and 1 (1 - 2) and stores in 1 and also in R8
MUL
ID = 4
Size = 4 + 2 * 4 [ = 12]
SubParams = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3)
Params = 2
Muls content of param 2 and 1 (1 * 2) and stores in 1
DIV
ID = 5
Size = 4 + 2 * 4 [ = 12]
SubParams = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3)
Params = 2
Divs content of param 2 and 1 (1 / 2) and stores Quotient 1 and remainder in R8
INC
ID = 6
Size = 4 + 4 [ = 8]
SubParams = NULL
Params = 1 [ a registor ]
Increments contents of registor by 1
DEC
ID = 7
Size = 4 + 4 [ = 8]
SubParams = NULL
Params = 1 [ a registor ]
Decrements contents of registor by 1
XOR
ID = 8
Size = 4 + 2 * 4 [ = 12]
SubParams = Reg to Reg (0), Const to Reg (1), Reg Memory to Reg (2), Memory to Reg (3)
Params = 2
Xors content of param 2 and 1 (1 XOR 2) and stores in 1
JMP/(JE or JZ)/(JNE or JNZ)/JGT/JLT/JGE/JLE
ID = 9
Size = 4 + 2 * 4 [ = 12]
SubParams [first 8 bit] = Plain (0), Jump if [R8 = ]Zero or equal (1), Jump if [R8 != ]not Zero or equal (2), Jump if R8 > 0 (3), Jump if R8 < 0 (4), Jump if R8 >= 8 (5), Jump if R8 <= 0 (6)
SubParams [second 8 bit] = To Const (3), To Reg (0), To Reg Mem (1)
Params = 1 64-bit integer [instruction index] or 1 32-bit registor
PUSH
ID = 10
Size = 4 + 4 [ = 8]
SubParams = Reg(0), Mem(2) (push PTR), Const(3)
Params = 1
Push item to stack also increments stack top pointer
POP
ID = 11 Size = 4 + 4 [ = 8] SubParams = Reg(0) Params = 1
Pop item to stack also increments stack top pointer
EXT
ID = 12
Size = 4
SubParams = Const (exit code)
Quit VM
SYSCALL
ID = 13
Size = 4
SubParams = NULL
PRINTREG
ID = 14
Size = 5
SubParams = NULL
Params = 1 (a registor)
NOTE: PRINTREG IS ONLY MEANT TO BE USED FOR DEBUGGING