From 16d57bf64b00603698750c2b3a5f6cbabca21f20 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Sat, 13 May 2017 19:36:46 +0200 Subject: [PATCH] Initial --- .gitignore | 1 + README.md | 1 + cpp/a.out | Bin 0 -> 8552 bytes cpp/debug.h | 32 ++ cpp/emulator.cpp | 26 ++ cpp/instructions.h | 41 +++ cpp/vm.cpp | 15 + cpp/vm.h | 20 ++ examples/VM.c | 724 +++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 860 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 cpp/a.out create mode 100644 cpp/debug.h create mode 100644 cpp/emulator.cpp create mode 100644 cpp/instructions.h create mode 100644 cpp/vm.cpp create mode 100644 cpp/vm.h create mode 100644 examples/VM.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f47cb20 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.out diff --git a/README.md b/README.md new file mode 100644 index 0000000..3aa8f82 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +VM con ISA diversi e bytecode generati casualmente. \ No newline at end of file diff --git a/cpp/a.out b/cpp/a.out new file mode 100755 index 0000000000000000000000000000000000000000..2d21ebd3da6b9692e94187ae597da1cd70a92494 GIT binary patch literal 8552 zcmeHMeQZo2fVZL#?UZB!K$`XyKG5JD>6Irp98 zJijjtVv!zF6`_YXjxna9M=a?TS+B@?LP6x2O8=;D^b9gS=nf%Ae255itM@!5 zSt|Q3nQ^M0A*YIlDrlSH0ECL(S5c2uSmNIkA2;{2zs1I-h2s}0^RQ(+Io#g1Wjx+G zo=oQ_TPHi(Tie^TTt?ff`c3vpc6Z-?<%!Hte13c==2iI68ld)Xeet#8<8R)W*!I)l z%Wv!*d?k4)Rzte-VD(cM^6Rf6{d2@tR>9XVg7+(I-dImhSFq>sXAtiuarB+C z++uAs7Bh0h1qqKyI8^6wQqg1@c1L|UcGSX@VYZ(p2BDvdVv~Bvm=e`A0ZHi&QTO2n(%+1_Wkqg47GMQy`g zL9B35KmH=gK8RtIyQ1O=-ygm&TquS2hX*4kH~y&JkDWW&N_3#NaJ9Gam&m3|YOcL2>lIhVfu_53?Dmk$nwzaAb69}FAko}733 z(K(Ec=3dP4h&^M5N3mVYPF{B+x_aW7=$J0nBk-m&{4ylh9C4G0OxQ_ON zYtrXhx4gdLNmsp(aQdyGq1j9VT&l|hY`}JsKZf!FlJ)v_d7JNPT=r1IG1$3w$CtKk zxSe2_XBsQxA_TAkJo>)rqkQ< zc&+XYJX)uFJErRQctcrlN7x$(ds{laew0J`PH%(yp8f*WFQ6T3gvi*vlrRojvN2be|HZxt#R7m-( ziN`W3@>{8X!;zQY`+C(1a2wM}?yulF^Afk{pOST)+W z)$m&oci~sS*)KohZk!jt<9kYne8LYoa7wTVcYc5GMcf7R@yqx20fjFd=i_W=#$o@Y zl3zGqlmk@j*Kd`4BmA1@UHmRK4zDTsCYY@cVQs#=h1F`~LlV{eexOtru0y(VbXA%6 z+f-mH7p%7y#^rZKnZ?%*WoO}fdm3>+EL=a`h_9r1;c<}f@Q)dndr!#$2bCT1Hc$JM z{KEYhQ~11`)V_;&6U^_^8g6(BabJ}Bv4bQZaO{^Yh|@UG zwFecIdm`P5xX-peRU^LcP;st-ki*WsN`7HH{cNA^Q>dui7wL9|SNR?$(@9f{K`d+L z%>2j*Rt@8xu6`rZJ1~eBYw<)jF`CSo3A{r~8L{z9I*~((c*YnV&kRS$jkuY~=8R~5 z5@MOu#CXC?#I^SA?Sbk-#t8Z|qS=K}*&{HLjiwStJfBJ(K@}TkP-GRNiBx_( zite=7!~|a94VaPO_K9R7mUt+cOBk_C8n6BGF%!+~>JRVfF?#yC>1t4QN9y>?Y4qqU zpm+C!u{*N2GaNDY?%FlbGiVHkJ0m@$RN*~d38-5~FuK3i7v9s`g>CBcFP6)z?jc`! zH)%CnSCw=(7z(M&LB0?)diUbJVLX{O^0@>#ibu_;b(8oR?kVY7lkM`QqhSp0>5?({ z)YqeQ-|4gy&t;6UXgWTguy>UP2>Ib$PJ&HPZP~ZpUV%5yVB-UvKVp~Q9t0l&G&5gxTS2#<pQ|^$GJjH;-Pxpyb7~?q9@Q# zuwwTw`SNqzA;}v>p3Mpir&(XdU(Wl_v%ZYGC^+?}9r}_N$p0DJM3Jde|2GbO$sdaB z|6_-~%%8wBSn=Y+%e98-s_VynbaJTt;2Hf60T2)F~_?XL0lEU*dlk8|?b!e2EoX zM3JfJ38ne5>q}nM!upH(7qi!~Lbjy;l7DruqWBSc@?|fSfDsn3gIE{+wGLeL?Nrvj wUGxC^5AeX#cbt4kJo5da{Ux#6^}lzk#og~PE`CL}X%YQ5*+GLt!NJ160Q~KGF8}}l literal 0 HcmV?d00001 diff --git a/cpp/debug.h b/cpp/debug.h new file mode 100644 index 0000000..c21572b --- /dev/null +++ b/cpp/debug.h @@ -0,0 +1,32 @@ +#ifndef DBG_H +#define DBG_H + + #if DBG + #define DBG_INFO(_x_) \ + do { \ + printf("\t[*] "); \ + printf _x_; \ + } while (0) + #define DBG_WARN(_x_) \ + do { \ + printf("[!] "); \ + printf _x_; \ + } while (0) + #define DBG_ERROR(_x_) \ + do { \ + printf("[-] "); \ + printf _x_; \ + } while (0) + #define DBG_SUCC(_x_) \ + do { \ + printf("[+] "); \ + printf _x_; \ + } while (0) + #else + #define DBG_INFO(_x_) + #define DBG_WARN(_x_) + #define DBG_ERROR(_x_) + #define DBG_SUCC(_x_) + #endif + +#endif \ No newline at end of file diff --git a/cpp/emulator.cpp b/cpp/emulator.cpp new file mode 100644 index 0000000..75f045d --- /dev/null +++ b/cpp/emulator.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "instructions.h" +#include "vm.h" +#include "debug.h" + +using namespace std; + +int main() { + ifstream vmbytecode; + VM * vm; + uint8_t * data; + + + /* + if (vmbytecode != NULL) { + fread() + } else { + fprintf(stderr, "Couldn't open bytecode!\n"); + return 1; + } + */ + return 0; +} \ No newline at end of file diff --git a/cpp/instructions.h b/cpp/instructions.h new file mode 100644 index 0000000..0303886 --- /dev/null +++ b/cpp/instructions.h @@ -0,0 +1,41 @@ +#include "vm.h" +#ifndef INS_H +#define INS_H +enum regs { + R0, + R1, + R2, + R3, + S0, + S1, + S2, + S3, + IP, + BP, + SP +}; + +enum ins { + MOVI, + MOVR, + MOVM, + ADDI, + ADDR, + ADDM, + SUBI, + SUBR, + SUBM, + XORI, + XORR, + XORM, + MULI, + MULR, + MULM, + DIVI, + DIVR, + DIVM, + HALT, + NOPE +}; + +#endif \ No newline at end of file diff --git a/cpp/vm.cpp b/cpp/vm.cpp new file mode 100644 index 0000000..daf23ad --- /dev/null +++ b/cpp/vm.cpp @@ -0,0 +1,15 @@ +#include "vm.hh" +#include "debug.h" + +void VM::VM(void) { + DBG_INFO(("Creating VM without code.\n")); +} + +void VM::VM(uint8_t * code, uint32_t codesize) { + DBG_INFO(("Creating VM with code.\n")); + memcpy(&vm.as.code, code, codesize); +} + +void VM::run(uint8_t * code) { + return; +} \ No newline at end of file diff --git a/cpp/vm.h b/cpp/vm.h new file mode 100644 index 0000000..1bfdd35 --- /dev/null +++ b/cpp/vm.h @@ -0,0 +1,20 @@ +#ifndef VM_H +#define VM_H + +class VMAddrSpace { + uint8_t stack[0x100], code[0x300], data[0x500]; +}; + +class VM { + uint16_t regs[0xb]; + struct flags { + uint8_t zf:1; + uint8_t cf:1; + }; + VMAddrSpace as; + + public: + void run(uint8_t * code); +}; + +#endif \ No newline at end of file diff --git a/examples/VM.c b/examples/VM.c new file mode 100644 index 0000000..699ecc1 --- /dev/null +++ b/examples/VM.c @@ -0,0 +1,724 @@ +/* +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; +}