srctree

Robin Linden parent 86f124d8 b738622d
azm: Support ADD eax,imm32 and UD2

inlinesplit
azm/assembler.h added: 47, removed: 4, total 43
@@ -6,6 +6,7 @@
#define AZM_ASSEMBLER_H_
 
#include <cstdint>
#include <iostream>
#include <optional>
#include <utility>
#include <vector>
@@ -42,6 +43,17 @@ class Amd64Assembler {
public:
[[nodiscard]] std::vector<std::uint8_t> take_assembled() { return std::exchange(assembled_, {}); }
 
void add(Reg32 dst, Imm32 imm32) {
if (dst != Reg32::Eax) {
std::cerr << "add: Unhandled dst " << static_cast<int>(dst) << '\n';
ud2();
return;
}
 
emit(0x05);
emit(imm32);
}
 
void mov(Reg32 dst, Imm32 imm32) {
emit(0xb8 + register_index(dst).value());
emit(imm32);
@@ -49,6 +61,11 @@ public:
 
void ret() { emit(0xc3); }
 
void ud2() {
emit(0x0f);
emit(0x0b);
}
 
private:
void emit(std::uint8_t byte) { assembled_.push_back(byte); }
void emit(Imm32 imm32) {
 
azm/assembler_test.cpp added: 47, removed: 4, total 43
@@ -24,6 +24,23 @@ int main() {
a.expect_eq(register_index(static_cast<Reg32>(std::underlying_type_t<Reg32>{30})), std::nullopt);
});
 
s.add_test("ADD EAX, imm32", [](etest::IActions &a) {
Amd64Assembler assembler;
 
assembler.add(Reg32::Eax, Imm32{0x42});
a.expect_eq(assembler.take_assembled(), CodeVec{0x05, 0x42, 0, 0, 0});
});
 
s.add_test("ADD w/ unsupported dst is ud2", [](etest::IActions &a) {
Amd64Assembler assembler;
 
assembler.add(Reg32::Edx, Imm32{0x42});
auto unsupported_add_code = assembler.take_assembled();
 
assembler.ud2();
a.expect_eq(unsupported_add_code, assembler.take_assembled());
});
 
s.add_test("MOV r32, imm32", [](etest::IActions &a) {
Amd64Assembler assembler;
 
@@ -41,5 +58,12 @@ int main() {
a.expect_eq(assembler.take_assembled(), CodeVec{0xc3});
});
 
s.add_test("UD2", [](etest::IActions &a) {
Amd64Assembler assembler;
 
assembler.ud2();
a.expect_eq(assembler.take_assembled(), CodeVec{0x0f, 0x0b});
});
 
return s.run();
}
 
azm/azm_example.cpp added: 47, removed: 4, total 43
@@ -11,11 +11,13 @@
int main() {
using namespace azm;
Amd64Assembler assembler;
assembler.mov(Reg32::Eax, Imm32{0xdeadbeef});
assembler.mov(Reg32::Eax, Imm32{3});
assembler.add(Reg32::Eax, Imm32{39});
assembler.mov(Reg32::Ecx, Imm32{0x4321});
assembler.mov(Reg32::Edx, Imm32{0x12345678});
assembler.mov(Reg32::Ebx, Imm32{0x1234});
assembler.ret();
assembler.ud2();
auto code = assembler.take_assembled();
// Print the machine code in a format usable for something like
// `objdump -D -b binary -mi386:x86-64 -Mintel <file>`.