// orbitvm.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include #include #include #include enum cmp_op { LTZ=0, LEZ=1, EQZ=2, GEZ=3, GTZ=4 }; enum instr_d { SOP=0, ADD=1, SUB=2, MUL=3, DIV=4, OUTPUT=5, PHI=6 }; enum instr_s { NOP=0, CMP=1, SQRT=2, COPY=3, INPUT=4 }; class VM { public: DWORD prg[16384]; int prglen; double mem[16384]; bool status; int time; double inp[16384]; double out[16384]; VM() : status(false), time(0), prglen(0) { for(int i=0; i<16384;i++) { inp[i] = out[i] = mem[i] = 0.0; prg[i] = 0; } } bool load_program(const char *fname) { HANDLE h = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (h==INVALID_HANDLE_VALUE) return false; DWORD sz = GetFileSize(h, NULL); prglen = sz / 12; DWORD w; for(int i=0; i < prglen; i++) { if (i & 1) { ReadFile(h, &prg[i], 4, &w, 0); ReadFile(h, &mem[i], 8, &w, 0); } else { ReadFile(h, &mem[i], 8, &w, 0); ReadFile(h, &prg[i], 4, &w, 0); } } CloseHandle(h); return true; } void run() { for(int ip=0; ip>28; const int dr1 = (prg[ip] >> 14) & 0x3FFF; const int dr2 = prg[ip] & 0x3FFF; switch(dop) { case ADD: mem[ip] = mem[dr1] + mem[dr2]; break; case SUB: mem[ip] = mem[dr1] - mem[dr2]; break; case MUL: mem[ip] = mem[dr1] * mem[dr2]; break; case DIV: mem[ip] = (mem[dr2]==0.0) ? 0.0 : mem[dr1] / mem[dr2]; break; case OUTPUT: out[dr1] = mem[dr2]; break; case PHI: mem[ip] = status ? mem[dr1] : mem[dr2]; break; case SOP: { const int sop = prg[ip] >> 24; const int imm = (prg[ip] >> 21) & 7; const int sr1 = dr2; switch(sop) { case NOP: break; case CMP: switch(imm) { case LTZ: status = mem[sr1] < 0; break; case LEZ: status = mem[sr1] <= 0; break; case EQZ: status = mem[sr1] == 0; break; case GEZ: status = mem[sr1] >= 0; break; case GTZ: status = mem[sr1] > 0; break; default: printf("bad imm=%d ip=%d\n", imm, ip); return; } break; case SQRT: mem[ip] = sqrt(mem[sr1]); break; case COPY: mem[ip] = mem[sr1]; break; case INPUT: mem[ip] = inp[sr1]; break; default: printf("bad sop=%d ip=%d\n", sop, ip); return; } } break; default: printf("bad dop=%d ip=%d\n", dop, ip); return; } //switch dop }//for ip }//run }; class Command { public: int ip, r1, r2; Command *next; VM &vm; Command(int _ip, int _r1, int _r2, Command *k, VM& _vm) : ip(_ip), r1(_r1), r2(_r2), next(k), vm(_vm) {} virtual void Execute()=0; }; class Add : public Command { public: Add(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.mem[r1] + vm.mem[r2]; next->Execute(); } }; class Sub : public Command { public: Sub(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.mem[r1] - vm.mem[r2]; next->Execute(); } }; class Mul : public Command { public: Mul(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.mem[r1] * vm.mem[r2]; next->Execute(); } }; class Div : public Command { public: Div(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.mem[r2]==0.0 ? 0.0 : vm.mem[r1] / vm.mem[r2]; next->Execute(); } }; class Out : public Command { public: Out(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.out[r1] = vm.mem[r2]; next->Execute(); } }; class Inp : public Command { public: Inp(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.inp[r1]; next->Execute(); } }; class Sqrt : public Command { public: Sqrt(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = sqrt(vm.mem[r1]); next->Execute(); } }; class Copy : public Command { public: Copy(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { vm.mem[ip] = vm.mem[r1]; next->Execute(); } }; class Phi : public Command { public: Phi(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm) {} virtual void Execute() { printf("Error: phi gets executed!\n"); } }; class CmpLTZ : public Command { int pip, pr1, pr2; public: CmpLTZ(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm), pip(k->ip), pr1(k->r1), pr2(k->r2) { next = k->next; } virtual void Execute() { vm.mem[pip] = vm.mem[r1] < 0 ? vm.mem[pr1] : vm.mem[pr2]; next->Execute(); } }; class CmpLEZ : public Command { int pip, pr1, pr2; public: CmpLEZ(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm), pip(k->ip), pr1(k->r1), pr2(k->r2) { next = k->next; } virtual void Execute() { vm.mem[pip] = vm.mem[r1] <= 0 ? vm.mem[pr1] : vm.mem[pr2]; next->Execute(); } }; class CmpEQZ : public Command { int pip, pr1, pr2; public: CmpEQZ(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm), pip(k->ip), pr1(k->r1), pr2(k->r2) { next = k->next; } virtual void Execute() { vm.mem[pip] = vm.mem[r1] == 0.0 ? vm.mem[pr1] : vm.mem[pr2]; next->Execute(); } }; class CmpGEZ : public Command { int pip, pr1, pr2; public: CmpGEZ(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm), pip(k->ip), pr1(k->r1), pr2(k->r2) { next = k->next; } virtual void Execute() { vm.mem[pip] = vm.mem[r1] >= 0 ? vm.mem[pr1] : vm.mem[pr2]; next->Execute(); } }; class CmpGTZ : public Command { int pip, pr1, pr2; public: CmpGTZ(int _ip, int _r1, int _r2, Command *k, VM& _vm) : Command(_ip, _r1, _r2, k, _vm), pip(k->ip), pr1(k->r1), pr2(k->r2) { next = k->next; } virtual void Execute() { vm.mem[pip] = vm.mem[r1] > 0 ? vm.mem[pr1] : vm.mem[pr2]; next->Execute(); } }; class End : public Command { public: End(VM& _vm) : Command(0,0,0, NULL,_vm) {} virtual void Execute() { vm.time++; } }; Command* comp_instr(int ip, DWORD ins, Command *nxt, VM& vm) { const int dop = ins>>28; const int dr1 = (ins >> 14) & 0x3FFF; const int dr2 = ins & 0x3FFF; switch(dop) { case ADD: return new Add(ip, dr1, dr2, nxt, vm); break; case SUB: return new Sub(ip, dr1, dr2, nxt, vm); break; case MUL: return new Mul(ip, dr1, dr2, nxt, vm); break; case DIV: return new Div(ip, dr1, dr2, nxt, vm); break; case OUTPUT: return new Out(ip, dr1, dr2, nxt, vm); break; case PHI: return new Phi(ip, dr1, dr2, nxt, vm); break; case SOP: { const int sop = ins >> 24; const int imm = (ins >> 21) & 7; const int sr1 = dr2; switch(sop) { case NOP: return nxt; break; case CMP: switch(imm) { case LTZ: return new CmpLTZ(ip, sr1, dr2, nxt, vm); break; case LEZ: return new CmpLEZ(ip, sr1, dr2, nxt, vm); break; case EQZ: return new CmpEQZ(ip, sr1, dr2, nxt, vm); break; case GEZ: return new CmpGEZ(ip, sr1, dr2, nxt, vm); break; case GTZ: return new CmpGTZ(ip, sr1, dr2, nxt, vm); break; default: printf("bad imm=%d ip=%d\n", imm, ip); return NULL; } break; case SQRT: return new Sqrt(ip, sr1, dr2, nxt, vm); break; case COPY: return new Copy(ip, sr1, dr2, nxt, vm); break; case INPUT: return new Inp(ip, sr1, dr2, nxt, vm); break; default: printf("bad sop=%d ip=%d\n", sop, ip); return NULL; } } break; default: printf("bad dop=%d ip=%d\n", dop, ip); return NULL; } //switch dop return NULL; } Command* comp_prg(DWORD *prg, int prglen, VM& vm) { Command *cmd = new End(vm); for(int i=prglen-1; i>=0; i--) cmd = comp_instr(i, prg[i], cmd, vm); return cmd; } int main(int argc, char* argv[]) { VM vm; if (!vm.load_program("bin1.obf")) { printf("load failed"); return 0; } vm.inp[16000] = 1001.0; Command* compiled = comp_prg(vm.prg, vm.prglen, vm); LARGE_INTEGER t0, t1, fr; QueryPerformanceCounter(&t0); for(int i=0; i<1000000; i++) //vm.run(); compiled->Execute(); QueryPerformanceCounter(&t1); QueryPerformanceFrequency(&fr); double t = (double)(t1.QuadPart - t0.QuadPart) / (double)fr.QuadPart; printf("fuel=%lf x=%lf y=%lf time=%lf\n", vm.out[1], vm.out[2], vm.out[3], t); return 0; }