-
Notifications
You must be signed in to change notification settings - Fork 16
/
example.cpp
120 lines (105 loc) · 4.68 KB
/
example.cpp
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <cassert>
#include <iostream>
#include "nyxstone.h"
using namespace nyxstone;
int main(int /*argc*/, char** /*argv*/)
{
// Create the nyxstone instance:
auto nyxstone { NyxstoneBuilder("x86_64").build().value() };
// Assemble to bytes
std::vector<uint8_t> bytes {
nyxstone->assemble(/*assembly=*/"mov rax, rbx", /*address=*/0x1000, /* labels= */ {}).value()
};
{
const std::vector<uint8_t> expected { 0x48, 0x89, 0xd8 };
assert(bytes == expected);
}
// Assemble with additional information
std::vector<Nyxstone::Instruction> instrs { nyxstone
->assemble_to_instructions(
/*assembly=*/"mov rax, rbx", /*address=*/0x1000,
/*labels=*/ {})
.value() };
{
const std::vector<Nyxstone::Instruction> expected { Nyxstone::Instruction { /*address=*/0x1000,
/*assembly=*/"mov rax, rbx",
/*bytes=*/ { 0x48, 0x89, 0xd8 } } };
assert(instrs == expected);
}
// Assemble with inline label
instrs = nyxstone->assemble_to_instructions("je .label; nop; .label:", 0x1000, {}).value();
{
const std::vector<Nyxstone::Instruction> expected {
Nyxstone::Instruction { /*address=*/0x1000, /*assembly=*/"je .label", /*bytes=*/ { 0x74, 0x01 } },
Nyxstone::Instruction { /*address=*/0x1002, /*assembly=*/"nop", /*bytes=*/ { 0x90 } },
};
assert(instrs == expected);
}
// Assemble with external label
bytes = nyxstone->assemble("jmp .label", 0x1000, { Nyxstone::LabelDefinition { ".label", 0x100 } }).value();
{
const std::vector<uint8_t> expected { 0xe9, 0xfb, 0xf0, 0xff, 0xff };
assert(bytes == expected);
}
// Disassemble some bytes
const std::vector<uint8_t> two_instruction_bytes
= { 0x48, 0x31, 0xc0, 0x66, 0x83, 0xc4, 0x08 }; // xor rax, rax; add sp, 8
std::string disassembly = nyxstone
->disassemble(
/*bytes=*/two_instruction_bytes,
/*address=*/0x1000,
/*count=*/0 // Disassemble all instructions
)
.value();
assert(disassembly
== "xor rax, rax\n"
"add sp, 8\n");
// Disassemble only one instruction of the bytes
disassembly = nyxstone
->disassemble(
/*bytes=*/two_instruction_bytes,
/*address=*/0x1000,
/*count=*/1 // Disassemble only one instruction
)
.value();
assert(disassembly == "xor rax, rax\n");
// Disassemble with additional information
instrs = nyxstone
->disassemble_to_instructions(
/*bytes=*/ { 0x48, 0x31, 0xc0, 0x66, 0x83, 0xc4, 0x08 },
/*address=*/0x1000,
/*count=*/0 // Disassemble all instructions
)
.value();
{
const std::vector<Nyxstone::Instruction> expected {
Nyxstone::Instruction { /*address=*/0x1000, /*assembly=*/"xor rax, rax", /*bytes=*/ { 0x48, 0x31, 0xc0 } },
Nyxstone::Instruction {
/*address=*/0x1003, /*assembly=*/"add sp, 8", /*bytes=*/ { 0x66, 0x83, 0xc4, 0x08 } },
};
assert(instrs == expected);
}
// Configure nyxstone to your liking:
nyxstone = std::move(
NyxstoneBuilder("thumbv8")
.with_cpu("cortex-m7")
.with_immediate_style(NyxstoneBuilder::IntegerBase::HexPrefix) // Change the printing style of immediates
.with_features("+mve.fp,+fp16") // Enable additional cpu features, here floating point instructions
.build()
.value());
// This fp instruction can be assembled via the new nyxstone instance
bytes = nyxstone->assemble("vadd.f16 s0, s1", 0x1000, {}).value();
{
const std::vector<uint8_t> expected { 0x30, 0xee, 0x20, 0x09 };
assert(bytes == expected);
}
// And the disassembly immediates are printed in hexadecimal style with a 0x-prefix
instrs = nyxstone->assemble_to_instructions("mov r0, #16", 0x1000, {}).value();
{
const std::vector<Nyxstone::Instruction> expected { Nyxstone::Instruction { /*address=*/0x1000,
/*assembly=*/"mov.w r0, #0x10",
/*bytes=*/ { 0x4f, 0xf0, 0x10, 0x00 } } };
assert(instrs == expected);
}
return 0;
}