diff options
| author | Dennis Brentjes <d.brentjes@gmail.com> | 2016-10-04 22:15:25 +0200 |
|---|---|---|
| committer | Dennis Brentjes <d.brentjes@gmail.com> | 2016-10-04 22:18:53 +0200 |
| commit | 0588b1ad00078daeda76a810b9ba6c68f97206a2 (patch) | |
| tree | 9f44fd94107e73c52c0262f049c3e745d58b2360 /emulate | |
| parent | cfb414ebd63e3dc735fcf415117cf06d93385741 (diff) | |
| download | openwar-0588b1ad00078daeda76a810b9ba6c68f97206a2.tar.gz openwar-0588b1ad00078daeda76a810b9ba6c68f97206a2.tar.bz2 openwar-0588b1ad00078daeda76a810b9ba6c68f97206a2.zip | |
Adds shr and cmp (with flags), and adds flags for sub.
Diffstat (limited to 'emulate')
| -rw-r--r-- | emulate/cpustate.hpp | 34 | ||||
| -rw-r--r-- | emulate/emulator.hpp | 97 |
2 files changed, 127 insertions, 4 deletions
diff --git a/emulate/cpustate.hpp b/emulate/cpustate.hpp index fb9c377..6b80551 100644 --- a/emulate/cpustate.hpp +++ b/emulate/cpustate.hpp @@ -3,6 +3,7 @@ #include <iostream> #include <array> #include <bitset> +#include <iomanip> #define REGISTER1( NAME ) \ private: \ @@ -74,4 +75,35 @@ struct CpuState { #undef REGISTER1 #undef REGISTER2 -#undef EFLAGS
\ No newline at end of file +#undef EFLAGS + +std::ostream& operator<<(std::ostream& os, CpuState& cpu) { + os << "EIP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.eip() << std::endl + << "EAX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.eax() << std::endl + << "EBX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ebx() << std::endl + << "ECX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ecx() << std::endl + << "EDX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.edx() << std::endl + << "ESP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.esp() << std::endl + << "EBP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ebp() << std::endl + << "ESI: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.esi() << std::endl + << "EDI: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.edi() << std::endl + << "cf \tpf \taf \tzf \tsf \ttf \tintf \tdf \tof \tnt \trf \tvm \tac \tvif \tvip \tid" << std::endl + << cpu.cf() << "\t" + << cpu.pf() << "\t" + << cpu.af() << "\t" + << cpu.zf() << "\t" + << cpu.sf() << "\t" + << cpu.tf() << "\t" + << cpu.intf() << "\t" + << cpu.df() << "\t" + << cpu.of() << "\t" + << cpu.nt() << "\t" + << cpu.rf() << "\t" + << cpu.vm() << "\t" + << cpu.ac() << "\t" + << cpu.vif() << "\t" + << cpu.vip() << "\t" + << cpu.id() << "\t" + << std::endl; + return os; +} 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); } |
