#include "jmp.h" #include "codes.h" #include #include #include using namespace std::string_literals; namespace { struct Jump { std::string name; OP_T jmp8; ///< if empty, not available OP_T jmp32; ///< if empty, not available }; std::vector jumpOps { // Call Procedure {"call", OP_T{}, OP_T{ 0xE8 } }, // no addr8 version // Unconditional Jump {"jmp", OP_T{ 0xEB }, OP_T{ 0xE9 } }, // Conditional Jumps {"ja", OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }}, {"jae", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, {"jb", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, {"jbe", OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }}, {"jc", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, {"jecxz", OP_T{ 0xE3 }, OP_T{} }, // no addr32 version {"jrcxz", OP_T{ 0xE3 }, OP_T{} }, // no addr32 version {"je", OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }}, {"jg", OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }}, {"jge", OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }}, {"jl", OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }}, {"jle", OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }}, {"jna", OP_T{ 0x76 }, OP_T{ 0x0F, 0x86 }}, {"jnae", OP_T{ 0x72 }, OP_T{ 0x0F, 0x82 }}, {"jnb", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, {"jnbe", OP_T{ 0x77 }, OP_T{ 0x0F, 0x87 }}, {"jnc", OP_T{ 0x73 }, OP_T{ 0x0F, 0x83 }}, {"jne", OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }}, {"jng", OP_T{ 0x7E }, OP_T{ 0x0F, 0x8E }}, {"jnge", OP_T{ 0x7C }, OP_T{ 0x0F, 0x8C }}, {"jnl", OP_T{ 0x7D }, OP_T{ 0x0F, 0x8D }}, {"jnle", OP_T{ 0x7F }, OP_T{ 0x0F, 0x8F }}, {"jno", OP_T{ 0x71 }, OP_T{ 0x0F, 0x81 }}, {"jnp", OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }}, {"jns", OP_T{ 0x79 }, OP_T{ 0x0F, 0x89 }}, {"jnz", OP_T{ 0x75 }, OP_T{ 0x0F, 0x85 }}, {"jo", OP_T{ 0x70 }, OP_T{ 0x0F, 0x80 }}, {"jp", OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }}, {"jpe", OP_T{ 0x7A }, OP_T{ 0x0F, 0x8A }}, {"jpo", OP_T{ 0x7B }, OP_T{ 0x0F, 0x8B }}, {"js", OP_T{ 0x78 }, OP_T{ 0x0F, 0x88 }}, {"jz", OP_T{ 0x74 }, OP_T{ 0x0F, 0x84 }}, }; bool registerOps() { bool result{true}; for (const auto& jumpOp: jumpOps) { result &= registerOp(mangleName(jumpOp.name), [&](const Asm::Args& args) -> std::shared_ptr{ return std::make_shared(jumpOp.name, args, jumpOp.jmp8, jumpOp.jmp32); }); } return result; } bool registered { registerOps() }; } Op_jmp::Op_jmp(const std::string& name, const Asm::Args& args, const OP_T& jmp8, const OP_T& jmp32) { label = std::any_cast(args[0]).name(); if (!jmp32.empty()) { // set machine_code machine_code = jmp32 + OP_T(size_t(4), uint8_t(0)); addr_size = 4; addr_offs = jmp32.size(); if (!jmp8.empty()) { // also provide alternative alternative_code = jmp8 + OP_T(size_t(1), uint8_t(0)); alternative_size = 1; alternative_offs = jmp8.size(); } } if (machine_code.empty() && !jmp8.empty()) { machine_code = jmp8 + OP_T(size_t(1), uint8_t(0)); addr_size = 1; addr_offs = jmp8.size(); } if (machine_code.empty()) { throw std::runtime_error("Unimplemented: "s + name); } // actual address not set, yet! }