A simple virtual machine simulator made for fun
- Code relies on Extendable.dll
Adds the value at the specified memory address to the value in the accumulator and stores the result back in the accumulator.
If the accumulator is empty, the instruction does nothing besides increase the program counter
ADD address
| Param | Description |
|---|---|
| address | The memory address of the value to add. |
a = 1
a = a + a
# Store 1 at memory[0x0]
STR 0 1
# Load 1 into accumulator
LDR 0
# Add memory[0x0] to accumulator
ADD 0
# Store result from accumulator into memory[0x0]
STR 0
Divides the value at the specified memory address by the value in the accumulator and stores The result back in the accumulator.
If the accumulator is empty, the instruction does nothing besides increase the program counter
DIV address
| Param | Description |
|---|---|
| address | The memory address of the value to divide the accumulator value by. |
N/A
Performs the modulus operation between the value at the specified memory address and the value in the accumulator, then stores the result back in the accumulator.
If the accumulator is empty, the instruction does nothing besides increase the program counter.
MOD address
| Param | Description |
|---|---|
| address | The memory address containing the value to apply the modulus operation with. |
N/A
Multiplies the value at the specified memory address with the value in the accumulator stores the result back in the accumulator.
If the accumulator is empty, the instruction does nothing besides increase the program counter
MUL address
| Param | Description |
|---|---|
| address | The memory address of the value to multiply. |
N/A
Subtracts the value at the specified memory address from the value in the accumulator and stores the result back in the accumulator.
If the accumulator is empty, the instruction does nothing besides increase the program counter
SUB address
| Param | Description |
|---|---|
| address | The memory address of the value to subtract from the accumulator value. |
N/A
Compares the value at the specified memory address with the value in the accumulator. Depending if they are equal it stores 1 or 0 in the accumulator, If the accumulator is empty, it is always set to 0.
CMP address comparisonMode
| Param | Description |
|---|---|
| address | The memory address of the value to compare the accumulator to. |
| comparisonMode | The mode of comparison, see eComparisonMode.cs |
N/A
Updates the program counter to a specified destination, effectively jumping to a new instruction in the program, however it only does this if the value in the accumulator is EQUAL to 1, otherwise it will simply increase the program counter.
JMPEQ destination
| Param | Description |
|---|---|
| destination | The destination instruction index (Program Counter) to jump to if the value in the accumulator is 1. |
N/A
Updates the program counter to a specified destination, effectively jumping to a new instruction in the program, however it only does this if the value in the accumulator is NOT EQUAL TO 1, otherwise it will simply increase the program counter.
JMPNEQ destination
| Param | Description |
|---|---|
| destination | The destination instruction index (Program Counter) to jump to if the value in the accumulator is NOT EQUAL TO 1. |
N/A
Updates the program counter to a specified destination, effectively jumping to a new instruction in the program.
JMP destination
| Param | Description |
|---|---|
| destination | The destination instruction index (Program Counter) to jump to. |
# 0: Jump over the No-Operation-Instructions
JMP 3
# 1:
NOP
# 2:
NOP
# 3:
STR 0 1000
Copies a value from the source address to the destination address. This operation is non-destructive, meaning the original value at the source address in memory remains intact after the copy.
CPY source destination
| Param | Description |
|---|---|
| source | The source memory address where the value is copied from. |
| destination | The destination memory address where the value is copied to. |
N/A
Represents an instruction to dispose of data at a specific memory address. The instruction deletes the data stored at the given address from memory, if the specified memory address does not contain an value then; this instruction simply increments the program counter
DSPSE source
| Param | Description |
|---|---|
| source | The memory address to be disposed of (deleted) from VM memory. |
# memory[0x0] = 1
STR 0 1
# Get rid of memory[0x0]
DSPSE 0
Represents an instruction to dispose of data in a range of memory addresses. This instruction deletes the data stored at each address between a specified start address and end address from the VM memory, this instruction only works if; all addresses exist, otherwise it only increases the program counter.
DSPRG address endAddress
| Param | Description |
|---|---|
| address | The starting memory address to begin disposing of. |
| endAddress | The ending memory address, where disposal will stop. |
# memory[0x0] = 1
STR 0 1
# memory[0x1] = 2
STR 1 2
# memory[0x2] = 3
STR 2 3
# memory[0x3] = 4
STR 3 4
# Get rid of all memmory from 0x0 to 0x3
DSPRG 0 3
Exchange/Swaps the values between the source and destination addresses. This operation swaps the values stored at the specified memory locations, Both addresses in memory must atleast have a value stored at the memory location, otherwise this will simply increase the program counter
XCHG address destination
| Param | Description |
|---|---|
| source | The memory address of the value to be exchanged from. |
| destination | The memory address of the value to be exchanged to. |
N/A
Loads a value from a specified memory address into the accumulator. This operation does not modify the value in memory.
LDR address
| Param | Description |
|---|---|
| address | The memory address from which the value is loaded. |
N/A
Moves a value from the source address to the destination address. This operation is destructive, meaning the original value at the source address in memory will be removed after the move.
MOV source destination
| Param | Description |
|---|---|
| source | The source memory address where the value is moved from. |
| destination | The destination memory address where the value is moved to. |
N/A
Stores a value at a specified memory address. If a value is provided, it is stored directly. If no value is provided, the value in the accumulator is stored instead, if accumulator is empty the instruction does nothing besides increase the program counter
STR address value
STR address
| Param | Description |
|---|---|
| address | The memory address where the value will be stored. |
| value | The value to store, if provided. Defaults to the value in the accumulator if not provided. |
N/A
Represents a no-operation instruction. This instruction does nothing except increment the instruction counter.
NOP
N/A
N/A
Increment A till it is no longer less than B equal to
int increment = 1;
int i = 0;
int numTimes = 10;
for (i; i < numTimes; i = i + increment)
{
}// Increment memory[0x2] till it is no longer less than 10
List<InstructionBase> instructionsLooping = InstructionParser.ParseInstructions([
// 0: memory[0x1] = 1 // use for equality check or incrementing by 1
"STR 1 1",
// 1: memory[0x2] = 0 // update this value till it hits 10
"STR 2 0",
// 2: memory[0x3] = 10 // which this value is
"STR 3 10",
// 3: accumulator = memory[0x2] (0)
"LDR 2",
// 4: accumulator = accumulator + memory[0x1] (1) // increment the value
"ADD 1",
// 5: memory[0x2] = accumulator (1)
"STR 2",
// 6: accumulator = accumulator < memory[0x3] (10) // (1|0) true or false
"CMP 3 2",
// 7: accumulator == 1 ? programCounter = 3 : programCounter++
"JMPEQ 3"
]);
InstructionExecutorContext context = new(instructionsLooping);
context.Execute();
// Prevent console from automatically closing
Console.ReadKey();Similar to Loop 10 times except with logic
int a = 0;
int b = 1;
int nextNumber = 0;
int numTerms = 10;
int i = 2;
int one = 1;
for (i; i < numTerms; i = i + one) { // Start from the 3rd term
nextNumber = a + b;
a = b;
b = nextNumber;
}List<InstructionBase> fibonacciInstructions = InstructionParser.ParseInstructions([
// Variables
"STR 0 0", // 0: memory[0x0] = 0 // a = 0
"STR 1 1", // 1: memory[0x1] = 1 // b = 1
"STR 2 0", // 2: memory[0x2] = 0 // nextNumber = 0
"STR 3 2", // 3: memory[0x3] = 2 // i = 2
"STR 4 10", // 4: memory[0x4] = 10 // numTerms = 10
"STR 5 1", // 6: memory[0x5] = 1 // one = 1
// Loop afterthought
// i = i + increment
"LDR 3", // 7: accumulator = memory[0x3] // accumulator = i
"ADD 5", // 8: accumulator = accumulator + memory[0x5] // accumulator = accumulator + one
"STR 3", // 9: memory[0x3] = accumulator // i = accumulator
// Code Inside Loop
// nextNumber = a + b;
"LDR 0", // 10: accumulator = memory[0x0] // accumulator = a
"ADD 1", // 11: accumulator = accumulator + memory[0x1] // accumulator = accumulator + b
"STR 2", // 12: memory[0x2] = accumulator // nextNumber = accumulator
"CPY 1 0", // 13: memory[0x0] = memory[0x1] // a = b
"CPY 2 1", // 14: memory[0x1] = memory[0x2] // b = nextNumber;
// Loop Condition
// i < numTerms;
"LDR 3", // 15: accumulator = memory[0x3] // accumulator = i
"CMP 4 2", // 16: accumulator = accumulator < memory[0x4] // accumulator = accumulator < numTerms ( 1 | 0 )
"JMPEQ 6", // 17: accumulator == 1 ? programCounter = 6 : programCounter+
// Cleanup
"DSPRG 0 1", // 18: memory delete 0x0-0x1 // delete a, b
"DSPRG 3 5", // 19: memory delete 0x3-0x5 // delete i, numTerms, increment
"MOV 2 0", // 20: memory[0x0] = memory[0x2], memory delete memory[0x2] // nextNumber
]);
InstructionExecutorContext context = new(fibonacciInstructions);
context.Execute();equal to
int a = 42;
int b = (a + a) * a;LoadInstruction<int> loadInstruction = new LoadInstruction<int>(0);
loadInstruction.Serialize(); // => "LDR 0"
StoreInstruction<float> storeInstruction = StoreInstruction<float>.Deserialize("STR 0 42");
storeInstruction.Serialize(); // => "STR 0 42"
List<InstructionBase> instructions2 = InstructionParser.ParseInstructions([
// 0: memory[0x0] = 42
"STR 0 42",
// 1: accumulator = memory[0x0] (42)
"LDR 0",
// 2: accumulator = accumulator (42) + memory[0x0] (42)
"ADD 0",
// 3: accumulator = accumulator (84) * memory[0x0] (42)
"MUL 0",
// 4: memory[0x1] = 3528
"STR 1"
]
);
InstructionExecutorContext context = new(instructions2);
context.Execute();
// Prevent console from automatically closing
Console.ReadKey();output from Simple Deserialization/Serialization Example)
Accumulator:
Executing instruction 1: StoreInstruction (STR 0 42) at Address 0x0
Accumulator:
Memory State:
Address 0x0: Int32 42
=====================================
Accumulator:
Memory State:
Address 0x0: Int32 42
Executing instruction 2: LoadInstruction (LDR 0) at Address 0x0
Accumulator: 42
Memory State:
Address 0x0: Int32 42
=====================================
Accumulator: 42
Memory State:
Address 0x0: Int32 42
Executing instruction 3: AddInstruction (ADD 0) at Address 0x0
Accumulator: 84
Memory State:
Address 0x0: Int32 42
=====================================
Accumulator: 84
Memory State:
Address 0x0: Int32 42
Executing instruction 4: MultiplyInstruction (MUL 0) at Address 0x0
Accumulator: 3528
Memory State:
Address 0x0: Int32 42
=====================================
Accumulator: 3528
Memory State:
Address 0x0: Int32 42
Executing instruction 5: StoreInstruction (STR 1) at Address 0x1
Accumulator: 3528
Memory State:
Address 0x0: Int32 42
Address 0x1: Int32 3528
=====================================