Skip to content

Commit

Permalink
azm: Support ADD eax,imm32 and UD2
Browse files Browse the repository at this point in the history
  • Loading branch information
robinlinden committed Oct 31, 2023
1 parent 86f124d commit b738622
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
17 changes: 17 additions & 0 deletions azm/assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define AZM_ASSEMBLER_H_

#include <cstdint>
#include <iostream>
#include <optional>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -42,13 +43,29 @@ 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);
}

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) {
Expand Down
24 changes: 24 additions & 0 deletions azm/assembler_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
}
4 changes: 3 additions & 1 deletion azm/azm_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>`.
Expand Down

0 comments on commit b738622

Please sign in to comment.