public string Disassemble(Instruction Instruction) { switch (Instruction.Type) { case InstructionType.Empty: return String.Format("{0}", Instruction.Opcode); case InstructionType.Register: return String.Format("{0} {1}", Instruction.Opcode, (ERegister)Instruction.Register1); case InstructionType.Value: return String.Format("{0} {1}", Instruction.Opcode, (int)Instruction.Value); case InstructionType.Indirect: return String.Format("{0} [0x{1:X}]", Instruction.Opcode, Instruction.Value); case InstructionType.RegisterRegister: return String.Format("{0} {1}, {2}", Instruction.Opcode, (ERegister)Instruction.Register1, (ERegister)Instruction.Register2); case InstructionType.RegisterValue: return String.Format("{0} {1}, {2}", Instruction.Opcode, (ERegister)Instruction.Register1, Instruction.Value); case InstructionType.RegisterOffsetRegister: return String.Format("{0} [{1}+{2}], {3}", Instruction.Opcode, (ERegister)Instruction.Register1, (int)Instruction.Value, (ERegister)Instruction.Register2); case InstructionType.RegisterRegisterOffset: return String.Format("{0} {1}, [{2}+{3}]", Instruction.Opcode, (ERegister)Instruction.Register1, (ERegister)Instruction.Register2, (int)Instruction.Value); default: throw(new Exception("Not implemented " + Instruction.Type)); } }
private bool EmitInstruction(uint PC, uint nPC, Instruction Instruction, ILGenerator ILGenerator) { switch (Instruction.Opcode) { case Opcode.PUSH: { LoadThreadContext(); LoadRegisterValue(Instruction.Register1); CallFunction((Action<ThreadContext, uint>)Operations.PUSH_DWORD); } break; case Opcode.MOV: //Console.WriteLine(" {0}", Instruction.Type); switch (Instruction.Type) { case InstructionType.RegisterValue: LoadRegisterAddress(Instruction.Register1); LoadValue(Instruction.Value); CallFunction((REF_DWORD_DELEGATE)Operations.MOV_DWORD); break; case InstructionType.RegisterRegister: LoadRegisterAddress(Instruction.Register1); LoadRegisterValue(Instruction.Register2); CallFunction((REF_DWORD_DELEGATE)Operations.MOV_DWORD); break; case InstructionType.RegisterOffsetRegister: LoadThreadContext(); LoadRegisterValue(Instruction.Register1); LoadValue(Instruction.Value); ILGenerator.Emit(OpCodes.Add); LoadRegisterValue(Instruction.Register2); CallFunction((Action<ThreadContext, uint, uint>)Operations.STORE_DWORD); break; case InstructionType.RegisterRegisterOffset: LoadThreadContext(); LoadRegisterAddress(Instruction.Register1); LoadRegisterValue(Instruction.Register2); LoadValue(Instruction.Value); ILGenerator.Emit(OpCodes.Add); CallFunction((TCTX_REF_DWORD_DELEGATE)Operations.LOAD_DWORD); break; default: throw(new NotImplementedException()); } break; case Opcode.LEA: switch (Instruction.Type) { // LEA REG, [REG + OFF] case InstructionType.RegisterRegisterOffset: LoadRegisterAddress(Instruction.Register1); LoadRegisterValue(Instruction.Register2); LoadValue(Instruction.Value); ILGenerator.Emit(OpCodes.Add); CallFunction((REF_DWORD_DELEGATE)Operations.MOV_DWORD); break; default: throw (new NotImplementedException()); } break; case Opcode.SUB: { switch (Instruction.Type) { case InstructionType.RegisterValue: LoadRegisterAddress(Instruction.Register1); LoadValue(Instruction.Value); CallFunction((REF_DWORD_DELEGATE)Operations.SUB_DWORD); break; default: throw (new NotImplementedException()); } } break; case Opcode.ADD: { switch (Instruction.Type) { case InstructionType.RegisterValue: LoadRegisterAddress(Instruction.Register1); LoadValue(Instruction.Value); CallFunction((REF_DWORD_DELEGATE)Operations.ADD_DWORD); break; case InstructionType.RegisterRegister: LoadRegisterAddress(Instruction.Register1); LoadRegisterValue(Instruction.Register2); CallFunction((REF_DWORD_DELEGATE)Operations.ADD_DWORD); break; default: throw (new NotImplementedException()); } } break; case Opcode.SHL: { switch (Instruction.Type) { case InstructionType.RegisterValue: LoadRegisterAddress(Instruction.Register1); LoadValue(Instruction.Value); CallFunction((REF_DWORD_DELEGATE)Operations.SHL_DWORD); break; case InstructionType.RegisterRegister: LoadRegisterAddress(Instruction.Register1); LoadRegisterValue(Instruction.Register2); CallFunction((REF_DWORD_DELEGATE)Operations.SHL_DWORD); break; default: throw(new NotImplementedException()); } } break; case Opcode.TEST: { switch (Instruction.Type) { case InstructionType.RegisterRegister: LoadThreadContext(); LoadRegisterValue(Instruction.Register1); LoadRegisterValue(Instruction.Register2); CallFunction((Action<ThreadContext, int, int>)Operations.TEST_DWORD); break; default: throw (new NotImplementedException()); } } break; case Opcode.CMP: { switch (Instruction.Type) { case InstructionType.RegisterValue: LoadThreadContext(); LoadRegisterValue(Instruction.Register1); LoadValue(Instruction.Value); CallFunction((Action<ThreadContext, int, int>)Operations.CMP_DWORD); break; default: throw (new NotImplementedException()); } } break; case Opcode.XCHG: if (Instruction.Register1 != Instruction.Register2) { LoadRegisterAddress(Instruction.Register1); LoadRegisterAddress(Instruction.Register2); CallFunction((REF_REF_DELEGATE)Operations.XCHG_DWORD); } break; case Opcode.RETN: { LoadThreadContext(); CallFunction((Action<ThreadContext>)Operations.RETURN); return false; } case Opcode.JZ: case Opcode.JNZ: case Opcode.JGE: { switch (Instruction.Type) { case InstructionType.Value: LoadThreadContext(); LoadValue((uint)(nPC)); LoadValue((uint)(nPC + Instruction.Value)); switch (Instruction.Opcode) { case Opcode.JZ: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_ZERO); break; case Opcode.JNZ: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_NOT_ZERO); break; case Opcode.JGE: CallFunction((Action<ThreadContext, uint, uint>)Operations.JUMP_GREATER_EQUAL); break; default: throw (new NotImplementedException()); } break; default: throw (new NotImplementedException()); } return false; } // idiv — Integer Division // The idiv instruction divides the contents of the 64 bit integer EDX:EAX // (constructed by viewing EDX as the most significant four bytes and EAX as // the least significant four bytes) by the specified operand value. The quotient // result of the division is stored into EAX, while the remainder is placed in EDX. case Opcode.IDIV: { LoadThreadContext(); CallFunction((Action<ThreadContext>)Operations.IDIV); } break; case Opcode.CDQ: { LoadThreadContext(); CallFunction((Action<ThreadContext>)Operations.CONVERT_DWORD_TO_QWORD); } break; case Opcode.JMP: { switch (Instruction.Type) { case InstructionType.Indirect: LoadThreadContext(); LoadValue((uint)Instruction.Value); CallFunction((Action<ThreadContext, uint>)Operations.JUMP_INDIRECT); break; case InstructionType.Value: LoadThreadContext(); LoadValue((uint)(nPC + Instruction.Value)); CallFunction((Action<ThreadContext, uint>)Operations.JUMP); break; default: throw(new NotImplementedException()); } return false; } case Opcode.INT: { LoadThreadContext(); LoadValue(nPC); LoadValue(Instruction.Value); CallFunction((Action<ThreadContext, uint, uint>)Operations.INTERRUPT); return false; } case Opcode.LEAVE: { LoadThreadContext(); CallFunction((Action<ThreadContext>)Operations.LEAVE); //throw(new NotImplementedException()); } break; case Opcode.CALL: { uint ReturnPC = nPC; uint CallPC = ReturnPC + Instruction.Value; LoadThreadContext(); LoadValue((uint)ReturnPC); LoadValue((uint)CallPC); CallFunction((Action<ThreadContext, uint, uint>)Operations.CALL); return false; /* int AllocatedIndex = 0; Console.WriteLine("CALL: {0:X}, {1:X}, {2:X}", CallPC, PC, Instruction.Value); Action<uint, int, Instruction> Context = (ContextCallPC, ContextAllocatedIndex, ContextInstruction) => { CpuContext.MethodCache[ContextAllocatedIndex] = (ThreadState) => { Console.WriteLine("Generating method : {0} : {1:X}", ContextInstruction, ContextCallPC); var Method = CpuContext.GenerateMethod(ContextCallPC); CpuContext.MethodCache[ContextAllocatedIndex] = Method; Method(ThreadState); }; }; Context(CallPC, AllocatedIndex, Instruction); LoadThreadContext(); LoadValue((uint)AllocatedIndex); //CallTailFunction((Action<ThreadContext, int>)Operations.CALL_INDEX); CallFunction((Action<ThreadContext, int>)Operations.CALL_INDEX); ILGenerator.Emit(OpCodes.Ret); */ /* LoadThreadContext(); LoadThreadContext(); ILGenerator.Emit(OpCodes.Ldfld, typeof(ThreadContext).GetField("TestMethod")); //ILGenerator.Emit(OpCodes.Callvirt, typeof(Action<ThreadContext>).GetMethod("Invoke")); CallFunction((Action<ThreadContext, Action<ThreadContext>>)Operations.CALLVIRT); */ } default: throw (new NotImplementedException("Unimplemented opcode " + Instruction.Opcode)); } return true; }