diff options
Diffstat (limited to 'emulate/emulator.hpp')
| -rw-r--r-- | emulate/emulator.hpp | 97 |
1 files changed, 94 insertions, 3 deletions
diff --git a/emulate/emulator.hpp b/emulate/emulator.hpp index 9bb5735..69c2f46 100644 --- a/emulate/emulator.hpp +++ b/emulate/emulator.hpp @@ -11,6 +11,25 @@ #include <fstream> #include <iomanip> +#include <limits> + +template <typename T> + struct SignedCounterpart {}; + + template <> + struct SignedCounterpart<uint32_t> { + typedef int32_t type; + }; + + template <> + struct SignedCounterpart<uint16_t> { + typedef int16_t type; + }; + + template <> + struct SignedCounterpart<uint8_t> { + typedef int8_t type; +}; class Emulator { public: @@ -70,7 +89,18 @@ public: }; template <typename Ret> - struct binary_op : public boost::static_visitor<Ret> { + struct op : public boost::static_visitor<Ret> { + CpuState& cpu; + + op(CpuState& cpu) + : cpu(cpu) + {} + }; + + template <typename Ret> + struct binary_op : public op<Ret> { + using op<Ret>::op; + template <typename T, typename U> Ret operator()(T&, U const&) const { throw IncompatibleArguments(); @@ -79,6 +109,7 @@ public: struct and_ : public binary_op<void> { using binary_op::operator(); + using binary_op<void>::binary_op; template<typename T> void operator()(T& lh, T const& rh) const { @@ -88,6 +119,7 @@ public: struct mov : public binary_op<void> { using binary_op::operator(); + using binary_op<void>::binary_op; template<typename T> void operator()(T& lh, T const& rh) const { @@ -95,12 +127,57 @@ public: } }; - struct sub : public binary_op<void> { + struct sub : public binary_op<void> { using binary_op::operator(); + using binary_op<void>::binary_op; template<typename T> void operator()(T& lh, T const& rh) const { + typedef typename SignedCounterpart<T>::type S; + auto& slh = reinterpret_cast<S&>(lh); + auto const& srh = reinterpret_cast<S const&>(rh); + + cpu.of() = ((srh < 0) && (slh > std::numeric_limits<S>::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits<S>::min() + srh)); + cpu.af() = !(lh & 8) && (rh & 8); + cpu.cf() = !(static_cast<T>(std::numeric_limits<S>::min()) & lh) && (static_cast<T>(std::numeric_limits<S>::min()) & rh); + lh -= rh; + + cpu.sf() = static_cast<T>(std::numeric_limits<S>::min()) & lh; + cpu.zf() = lh == 0; + cpu.pf() = ((lh & 1) + (lh >> 1 & 1) + (lh >> 2 & 1) + (lh >> 3 & 1) + (lh >> 4 & 1) + (lh >> 5 & 1) + (lh >> 6 & 1) + (lh >> 7 & 1) % 2) + 1; + } + }; + + struct shr : public binary_op<void> { + using binary_op::operator(); + using binary_op<void>::binary_op; + + template <typename T> + void operator()(T& lh, T const& rh) const { + lh >>= rh; + } + }; + + struct cmp : public binary_op<void> { + using binary_op::operator(); + using binary_op<void>::binary_op; + + template<typename T> + void operator()(T& lh, T const& rh) const { + typedef typename SignedCounterpart<T>::type S; + auto& slh = reinterpret_cast<S&>(lh); + auto const& srh = reinterpret_cast<S const&>(rh); + + cpu.of() = ((srh < 0) && (slh > std::numeric_limits<S>::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits<S>::min() + srh)); + cpu.af() = !(lh & 8) && (rh & 8); + cpu.cf() = !(static_cast<T>(std::numeric_limits<S>::min()) & lh) && (static_cast<T>(std::numeric_limits<S>::min()) & rh); + + T result = lh - rh; + + cpu.sf() = static_cast<T>(std::numeric_limits<S>::min()) & result; + cpu.zf() = result == 0; + cpu.pf() = ((result & 1) + (result >> 1 & 1) + (result >> 2 & 1) + (result >> 3 & 1) + (result >> 4 & 1) + (result >> 5 & 1) + (result >> 6 & 1) + (result >> 7 & 1) % 2) + 1; } }; @@ -171,7 +248,7 @@ public: } } - boost::apply_visitor(O(), *dest, src); + boost::apply_visitor(O(cpu), *dest, src); } void handle_I_JMP(_DInst inst) { @@ -200,6 +277,14 @@ public: handle_binary<sub>(inst); } + void handle_I_SHR(_DInst inst) { + handle_binary<shr>(inst); + } + + void handle_I_CMP(_DInst inst) { + handle_binary<cmp>(inst); + } + void handle_I_INT(_DInst inst) { _Operand int_op = inst.ops[0]; @@ -232,6 +317,8 @@ public: REGISTER_HANDLER(I_MOV); REGISTER_HANDLER(I_SUB); REGISTER_HANDLER(I_INT); + REGISTER_HANDLER(I_SHR); + REGISTER_HANDLER(I_CMP); #undef REGISTER_HANDLER @@ -243,6 +330,9 @@ public: REGISTER_GETTER(R_AX , ax ); REGISTER_GETTER(R_EAX, eax); REGISTER_GETTER(R_EBX, ebx); + REGISTER_GETTER(R_ECX, ecx); + REGISTER_GETTER(R_ESI, esi); + REGISTER_GETTER(R_EDI, edi); #undef REGISTER_GETTER @@ -307,6 +397,7 @@ void emulate(std::string file_path) { _DecodedInst inst; distorm_format64(&ci, &decinst, &inst); std::cout << "CurrentInstruction: " << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl; + std::cout << emulator.cpu << std::endl; emulator.handle_instruction(decinst); } |
