-
-
Save SouhailHammou/6b4069b07e538a48bb70 to your computer and use it in GitHub Desktop.
Virtual machine with a custom instruction set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
VM by Souhail Hammou : custom instruction set | |
data space and stack space are customizable. | |
Important : In calculations the VM is using unsigned values. | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <conio.h> | |
#define TRUE 1 | |
#define FALSE 0 | |
typedef unsigned char boolean; | |
typedef uint8_t BYTE; | |
typedef uint16_t WORD; | |
typedef uint32_t DWORD; | |
typedef struct | |
{ | |
/*data has also the code*/ | |
BYTE data[4096]; | |
/*stack space , size of one element is WORD in order to be able to push addresses*/ | |
WORD stack[256]; | |
}ADDRESS_SPACE,*PADDRESS_SPACE; | |
typedef struct | |
{ | |
/*General Purpose Registers R0 -> R3*/ | |
WORD GPRs[4]; | |
union | |
{ | |
unsigned char Flags; | |
struct | |
{ | |
unsigned char ZF:1; | |
unsigned char CF:1; | |
unsigned char Unused:6; | |
}; | |
}; | |
WORD IP; | |
WORD SP; | |
}REGS,*PREGS; | |
void VmLoop(PADDRESS_SPACE AS,PREGS Regs) | |
{ | |
int i; | |
boolean exit = FALSE; | |
BYTE opcode,byte_val,byte_val2,byte_val3; | |
WORD word_val,word_val2; | |
while(!exit) | |
{ | |
/*read byte (opcode)*/ | |
//printf("[+] IP : %.4X => ",Regs->IP); | |
opcode = AS->data[Regs->IP++]; | |
/*opcodes switch*/ | |
switch(opcode) | |
{ | |
case 0x90 : | |
//printf("NOP\n"); | |
break; | |
/* | |
Each nibble of the operand represents a General purpose register (GPR) | |
the highest nibble is the destination , the lowest one is the source. | |
Example: | |
10 12 => MOV R1,R2 | |
10 11 => MOV R1,R1 | |
10 01 => MOV R0,R1 | |
*/ | |
case 0x10 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
Regs->GPRs[(byte_val & 0xF0)>>4] = Regs->GPRs[byte_val & 0x0F]; | |
//printf("MOV R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
} | |
else | |
goto exception; | |
break; | |
/* | |
Move and extend byte from memory to register | |
Example: | |
12 03 50 00 => MOVX R3,BYTE [0050] | |
12 00 00 01 => MOVX R0,BYTE [0100] | |
*/ | |
case 0x12 : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val >= sizeof(AS->data)) | |
goto exception; | |
Regs->GPRs[byte_val] = 0; | |
*(BYTE*)&Regs->GPRs[byte_val] = AS->data[word_val]; | |
//printf("MOVX R%d, BYTE [%.4X]\n",byte_val,word_val); | |
break; | |
/* | |
Move word from memory to register | |
14 03 50 00 => MOV R3,WORD [0050] | |
14 00 00 01 => MOV R0,WORD [0100] | |
*/ | |
case 0x14 : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val >= sizeof(AS->data)) | |
goto exception; | |
Regs->GPRs[byte_val] = *(WORD*)&AS->data[word_val]; | |
//printf("MOV R%d, WORD [%.4X]\n",byte_val,word_val); | |
break; | |
/* | |
Move and extend byte to register | |
16 01 15 => MOVX R1,15h | |
*/ | |
case 0x16 : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
Regs->GPRs[byte_val] = 0; | |
*(BYTE*)&Regs->GPRs[byte_val] = AS->data[Regs->IP++]; | |
//printf("MOVX R%d,%.2Xh\n",byte_val,AS->data[Regs->IP - 1]); | |
break; | |
/* | |
Move word to register | |
18 01 15 28 => MOV R1,2815h | |
*/ | |
case 0x18 : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
Regs->GPRs[byte_val] = 0; | |
Regs->GPRs[byte_val] = *(WORD*)&AS->data[Regs->IP]; | |
//printf("MOV R%d,%.4Xh\n",byte_val,*(WORD*)&AS->data[Regs->IP]); | |
Regs->IP += sizeof(WORD); | |
break; | |
/* | |
Move byte from register to memory location | |
ex : | |
1C 01 20 01 => MOV BYTE [0120],R1 | |
1C 03 50 03 => MOV BYTE [0350],R3 | |
*/ | |
case 0x1c : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val >= sizeof(AS->data)) | |
goto exception; | |
AS->data[word_val] = *(BYTE*)&Regs->GPRs[byte_val]; | |
//printf("MOV BYTE [%.4X],R%d\n",word_val,byte_val); | |
break; | |
/* | |
Move word from register to memory location | |
ex : | |
1F 01 20 01 => MOV WORD [0120],R1 | |
1F 03 50 03 => MOV WORD [0350],R3 | |
*/ | |
case 0x1f : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val >= sizeof(AS->data)) | |
goto exception; | |
*(WORD*)&AS->data[word_val] = Regs->GPRs[byte_val]; | |
//printf("MOV WORD [%.4X],R%d\n",word_val,byte_val); | |
break; | |
/* | |
Unconditional Jump | |
example : | |
E0 10 00 => JMP 0010 | |
E0 54 02 => JMP 0254 | |
*/ | |
case 0xE0 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
Regs->IP = word_val; | |
//printf("JMP %.4X\n",word_val); | |
break; | |
/* | |
JZ : Jump if equal | |
E2 54 01 =>JNZ 0154 | |
*/ | |
case 0xE2 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
/*Jump if ZF is set*/ | |
if(Regs->ZF) | |
Regs->IP = word_val; | |
//printf("JZ %.4X\n",word_val); | |
break; | |
/* | |
JNZ : Jump if not equal | |
E3 54 01 => JNZ 0154 | |
*/ | |
case 0xE3 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
if(! Regs->ZF) | |
Regs->IP = word_val; | |
//printf("JNZ %.4X\n",word_val); | |
break; | |
/* | |
JAE : Jump if above or equal | |
E4 54 01 : JAE 0154 | |
*/ | |
case 0xE4 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
if(Regs->ZF || ! Regs->CF) | |
Regs->IP = word_val; | |
//printf("JAE %.4X\n",word_val); | |
break; | |
/* | |
JBE : Jump if below or equal | |
E6 54 01 : JBE 0154 | |
*/ | |
case 0xE6 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
if(Regs->ZF || Regs->CF) | |
Regs->IP = word_val; | |
//printf("JBE %.4X\n",word_val); | |
break; | |
/* | |
JB : Jump if below | |
E8 54 01 : JB 0154 | |
*/ | |
case 0xE8 : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
if(Regs->CF && ! Regs->ZF) | |
Regs->IP = word_val; | |
//printf("JB %.4X\n",word_val); | |
break; | |
/* | |
JA : Jump if above | |
EC 54 01 => JA 0154 | |
*/ | |
case 0xEC : | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
if( ! Regs->CF && ! Regs->ZF) | |
Regs->IP = word_val; | |
//printf("JA %.4X\n",word_val); | |
break; | |
/*=======================================================*/ | |
/*ARITHMETIC OPERATIONS ON THE WHOLE REGISTER (WORD)*/ | |
/* | |
ADD : Add value to register | |
AD 01 15 00 : ADD R1,15h | |
AD 01 01 50 : ADD R1,5001h | |
Updated flags : | |
ZF and CF | |
*/ | |
case 0xAD : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
word_val2 = Regs->GPRs[byte_val] + word_val; | |
if(word_val2 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(word_val2 < Regs->GPRs[byte_val]) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
Regs->GPRs[byte_val] = word_val2; | |
//printf("ADD R%d,%.4X\n",byte_val,word_val); | |
break; | |
/* | |
ADD : Add 2 registers | |
A5 12 : ADD R1,R2 | |
A5 30 : ADD R3,R0 | |
*/ | |
case 0xA5 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
word_val = Regs->GPRs[(byte_val & 0xF0)>>4]; | |
word_val2 = Regs->GPRs[(byte_val & 0xF0)>>4] += Regs->GPRs[byte_val & 0x0F]; | |
if(word_val2 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(word_val2 < word_val) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("ADD R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
ADDL : Add 2 registers (low byte) | |
A2 12 => ADDL R1,R2 | |
*/ | |
case 0xA2 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4]; | |
byte_val3 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] += *(BYTE*)&Regs->GPRs[byte_val & 0x0F]; | |
if(byte_val3 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(byte_val3 < byte_val2) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("ADDL R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
SUB : substract value from register | |
5B 01 15 00 : SUB R1,15h | |
5B 01 01 50 : SUB R1,5001h | |
Updated flags : | |
ZF and CF | |
*/ | |
case 0x5B : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
word_val = *(WORD*)&AS->data[Regs->IP]; | |
Regs->IP += 2; | |
word_val2 = Regs->GPRs[byte_val] - word_val; | |
if(word_val2 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(word_val2 > Regs->GPRs[byte_val]) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
Regs->GPRs[byte_val] = word_val2; | |
//printf("SUB R%d,%.4X\n",byte_val,word_val); | |
break; | |
/* | |
SUB : substract registers (word) | |
5C 01 => SUB R0,R1 | |
*/ | |
case 0x5C : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
word_val = Regs->GPRs[(byte_val & 0xF0)>>4]; | |
word_val2 = Regs->GPRs[(byte_val & 0xF0)>>4] -= Regs->GPRs[byte_val & 0x0F]; | |
if(word_val2 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(word_val2 > word_val) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("SUB R%d,R%d",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
SUBL : Substract 2 registers (low part) | |
5D 12 => SUBL R1,R2 | |
*/ | |
case 0x5D : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4]; | |
byte_val3 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] -= *(BYTE*)&Regs->GPRs[byte_val & 0x0F]; | |
if(byte_val3 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(byte_val3 > byte_val2) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("SUBL R%d,R%d",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
XOR : Xor 2 registers | |
(operand uses nibbles : high = dest , low = source) | |
F0 12 => XOR R1,R2 | |
F0 01 => XOR R0,R1 | |
*/ | |
case 0xF0 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
word_val = Regs->GPRs[(byte_val & 0xF0)>>4] ^= Regs->GPRs[byte_val & 0x0F]; | |
if(word_val == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("XOR R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/*===============================================================*/ | |
/*ARITHMETIC OPERATIONS ON THE LOWER BYTE OF THE REGISTER*/ | |
/* | |
XORL : Xor the lower bytes of 2 registers | |
F1 12 : XORL R1,R2 | |
F1 01 : XORL R0,R1 | |
*/ | |
case 0xF1 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3) | |
{ | |
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] ^= *(BYTE*)&Regs->GPRs[byte_val & 0x0F]; | |
if(byte_val2 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("XORL R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
ADDL : add only to the lower of the register | |
A1 03 20 => ADDL R3,20h | |
*/ | |
case 0xA1: | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
byte_val2 = AS->data[Regs->IP++]; | |
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val] + byte_val2; | |
if(byte_val3 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(byte_val3 < *(BYTE*)&Regs->GPRs[byte_val]) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
*(BYTE*)&Regs->GPRs[byte_val] = byte_val3; | |
//printf("ADDL R%d,%.2X\n",byte_val,byte_val2); | |
break; | |
/* | |
SUBL : Substract only from the lower byte of the register | |
51 03 20 => SUBL R3,20h | |
*/ | |
case 0x51: | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
byte_val2 = AS->data[Regs->IP++]; | |
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val] - byte_val2; | |
if(byte_val3 == 0) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(byte_val3 > *(BYTE*)&Regs->GPRs[byte_val]) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
*(BYTE*)&Regs->GPRs[byte_val] = byte_val3; | |
//printf("SUBL R%d,%.2X\n",byte_val,byte_val2); | |
break; | |
/*===============================================================*/ | |
/* | |
Store register (low byte) at [Rx]. | |
55 21 => MOV BYTE [R2],R1 | |
*/ | |
case 0x55 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0xF0)>>4] < sizeof(AS->data)) | |
AS->data[Regs->GPRs[(byte_val & 0xF0)>>4]] = *(BYTE*)&Regs->GPRs[byte_val & 0x0F]; | |
else | |
goto exception; | |
//printf("MOV BYTE [R%d],R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
Load and extend low byte of register from memory pointed by a register | |
56 21 => MOV R2,BYTE [R1] | |
*/ | |
case 0x56 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data)) | |
{ | |
*(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4] = AS->data[Regs->GPRs[byte_val & 0x0F]]; | |
Regs->GPRs[(byte_val & 0xF0)>>4] &= 0xFF; | |
} | |
else | |
goto exception; | |
//printf("MOVX R%d, BYTE [R%d]\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
CMP : Compare 2 registers (word) | |
70 12 : CMP R1,R2 | |
*/ | |
case 0x70 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data)) | |
{ | |
word_val = Regs->GPRs[(byte_val & 0xF0)>>4]; | |
word_val2 = Regs->GPRs[byte_val & 0x0F]; | |
if(word_val2 == word_val) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(word_val2 > word_val) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("CMP R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
CMPL : Compare 2 registers (lower byte) | |
71 12 : CMPL R1,R2 | |
*/ | |
case 0x71 : | |
byte_val = AS->data[Regs->IP++]; | |
if((byte_val & 0xF0) <= 0x30 && (byte_val & 0x0F) <= 3 && Regs->GPRs[(byte_val & 0x0F)] < sizeof(AS->data)) | |
{ | |
byte_val2 = *(BYTE*)&Regs->GPRs[(byte_val & 0xF0)>>4]; | |
byte_val3 = *(BYTE*)&Regs->GPRs[byte_val & 0x0F]; | |
if(byte_val3 == byte_val2) | |
Regs->ZF = 1; | |
else | |
Regs->ZF = 0; | |
if(byte_val3 > byte_val2) | |
Regs->CF = 1; | |
else | |
Regs->CF = 0; | |
} | |
else | |
goto exception; | |
//printf("CMP R%d,R%d\n",(byte_val & 0xF0)>>4,byte_val & 0x0F); | |
break; | |
/* | |
Push register | |
example : AF 01 => PUSH R1 | |
*/ | |
case 0xAF : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
/*Decrement the stack pointer to store the new value*/ | |
Regs->SP--; | |
/*Check for stack overflow*/ | |
if(Regs->SP == 0xFFFF) | |
goto exception; | |
/*Push value */ | |
AS->stack[Regs->SP] = Regs->GPRs[byte_val]; | |
//printf("PUSH R%d\n",byte_val); | |
break; | |
/* | |
Pop a register | |
AE 01 => POP R1 | |
*/ | |
case 0xAE : | |
byte_val = AS->data[Regs->IP++]; | |
if(byte_val > 3) | |
goto exception; | |
/* | |
Check for stack underflow | |
*/ | |
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)]) | |
goto exception; | |
/*Move the value into the register*/ | |
Regs->GPRs[byte_val] = AS->stack[Regs->SP]; | |
/*Value popped , increment SP*/ | |
Regs->SP++; | |
//printf("POP R%d\n",byte_val); | |
break; | |
/*========================================================*/ | |
/*User interaction operations (print and receive input)*/ | |
/* | |
Print Word to user as integer, the value must be at the top of the stack and it is popped | |
C0 => print integer | |
*/ | |
case 0xC0 : | |
/*read value then pop it*/ | |
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)]) | |
goto exception; | |
word_val = AS->stack[Regs->SP++]; | |
//printf("Print integer\n"); | |
printf("%u\n",word_val); | |
break; | |
/* | |
Print string to user, the pointer must be at the top of the stack and it is popped | |
C2 => print string | |
*/ | |
case 0xC2 : | |
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)]) | |
goto exception; | |
/*read it and pop it*/ | |
word_val = AS->stack[Regs->SP++]; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
//printf("Print string\n"); | |
printf("%s",&AS->data[word_val]); | |
break; | |
/* | |
Scan string from user, the pointer where to store the integer must be on top of the stack | |
89 | |
*/ | |
case 0x89 : | |
if(&AS->stack[Regs->SP] == &AS->stack[sizeof(AS->stack)/sizeof(WORD)]) | |
goto exception; | |
/*read it and pop it*/ | |
word_val = AS->stack[Regs->SP++]; | |
if(word_val > sizeof(AS->data)) | |
goto exception; | |
//printf("Scan string\n"); | |
//printf(" [+] Input : "); | |
gets((char*)&AS->data[word_val]); | |
break; | |
/*=======================================================*/ | |
/*0xDB Debugging Only*/ | |
/* | |
case 0xDB : | |
printf("\n===Debug Information Start===\n"); | |
printf("+ Registers :\n"); | |
for(i=0;i<=3;i++) | |
printf(" R%d : 0x%.4X\n",i,Regs->GPRs[i]); | |
printf(" IP : 0x%.4X\n",Regs->IP); | |
printf(" SP : 0x%.4X\n",Regs->SP*sizeof(WORD)); | |
printf("+ Current Stack : (Top 4 values)\n"); | |
if(Regs->SP == sizeof(AS->stack)/sizeof(WORD)) | |
{ | |
printf(" The stack is empty.\n"); | |
goto loc; | |
} | |
for(i=0;i<4;i++) | |
{ | |
if(Regs->SP + i < sizeof(AS->stack)/sizeof(WORD)) | |
printf(" SP+%d => 0x%.4X : %.4X\n",i*2,(Regs->SP + i)*2,AS->stack[Regs->SP+i]); | |
} | |
loc: | |
printf("+Flags Information :\n"); | |
printf(" Flags = 0x%.2X\n",Regs->Flags); | |
printf(" ZF = %d\n",Regs->ZF); | |
printf(" CF = %d\n",Regs->CF); | |
printf("===Debug Information End ===\n\n"); | |
break; | |
*/ | |
/*======================================================*/ | |
case 0xED : | |
//printf("Exit\n"); | |
exit = TRUE; | |
break; | |
default : | |
exception: | |
//printf("\n==Exception : ...Exiting==\n"); | |
exit = TRUE; | |
} | |
} | |
} | |
int main() | |
{ | |
PADDRESS_SPACE AS; | |
PREGS Regs; | |
int size; | |
FILE* File; | |
//printf("DEBUG INFO :"); | |
//printf("Allocating Address Space\n"); | |
AS = (PADDRESS_SPACE) malloc(sizeof(ADDRESS_SPACE)); | |
//printf("Allocating Registers\n"); | |
Regs = (PREGS) malloc(sizeof(REGS)); | |
//printf("Initializing Registers\n"); | |
Regs->IP = 0; | |
Regs->SP = sizeof(AS->stack) / sizeof(WORD); | |
Regs->Flags = 0; | |
/*Open code and data file and read it into */ | |
File = fopen("vm_file","rb"); | |
if(!File) | |
{ | |
printf("Found trouble opening the file"); | |
return 0; | |
} | |
/*Check the file size*/ | |
fseek(File,0,SEEK_END); | |
size = ftell(File); | |
if( size > sizeof(AS->data)) | |
{ | |
printf("File size is larger than the storage available for data and code"); | |
return 0; | |
} | |
rewind(File); | |
/*Copy the file to our VM address space*/ | |
fread(AS->data,1,size,File); | |
fclose(File); | |
//printf("Starting Execution\n"); | |
VmLoop(AS,Regs); | |
_getch(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment