diff --git a/examples/VM.c b/examples/VM.c deleted file mode 100644 index 699ecc1..0000000 --- a/examples/VM.c +++ /dev/null @@ -1,724 +0,0 @@ -/* -VM by Souhail Hammou : custom instruction set -data space and stack space are customizable. -Important : In calculations the VM is using unsigned values. -*/ -#include -#include -#include -#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; -}