1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#include "jmp.h"
#include "codes.h"
#include <asm/assembler.h>
#include <asm/operators.h>
#include <asm/intel64/codes.h>
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<Jump> 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<AsmArgs::Label>(jumpOp.name), [&](AsmArgs& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_jmp>(jumpOp.name, args, jumpOp.jmp8, jumpOp.jmp32);
});
}
return result;
}
bool registered {
registerOps()
};
}
Op_jmp::Op_jmp(const std::string& name, AsmArgs& args, const OP_T& jmp8, const OP_T& jmp32)
{
label = std::any_cast<AsmArgs::Label>(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!
}
|