srctree

Robin Linden parent e312894f 2179c640
azm: Implement JMP rel32

inlinesplit
azm/amd64/assembler.h added: 57, removed: 4, total 53
@@ -38,11 +38,18 @@ constexpr std::optional<std::uint8_t> register_index(Reg32 reg) {
return std::nullopt;
}
 
struct Label {
std::size_t offset{};
};
 
// https://www.felixcloutier.com/x86/
class Assembler {
public:
[[nodiscard]] std::vector<std::uint8_t> take_assembled() { return std::exchange(assembled_, {}); }
 
Label label() const { return Label{assembled_.size()}; }
 
// Instructions
void add(Reg32 dst, Imm32 imm32) {
if (dst != Reg32::Eax) {
std::cerr << "add: Unhandled dst " << static_cast<int>(dst) << '\n';
@@ -54,6 +61,13 @@ public:
emit(imm32);
}
 
void jmp(Label label) {
// JMP rel32
emit(0xe9);
static constexpr int kInstructionSize = 4;
emit(Imm32{static_cast<std::uint32_t>(label.offset - assembled_.size() - kInstructionSize)});
}
 
void mov(Reg32 dst, Imm32 imm32) {
emit(0xb8 + register_index(dst).value());
emit(imm32);
 
azm/amd64/assembler_test.cpp added: 57, removed: 4, total 53
@@ -41,6 +41,38 @@ int main() {
a.expect_eq(unsupported_add_code, assembler.take_assembled());
});
 
s.add_test("JMP, backwards", [](etest::IActions &a) {
Assembler assembler;
 
auto slot1 = assembler.label();
assembler.jmp(slot1);
assembler.ud2();
assembler.jmp(slot1);
auto slot2 = assembler.label();
assembler.jmp(slot2);
 
a.expect_eq(assembler.take_assembled(),
CodeVec{
0xe9, // jmp rel32
0xfb, // -5
0xff,
0xff,
0xff,
0x0f, // ud2
0x0b,
0xe9, // jmp rel32
0xf4, // -12
0xff,
0xff,
0xff,
0xe9, // jmp rel32
0xfb, // -5
0xff,
0xff,
0xff,
});
});
 
s.add_test("MOV r32, imm32", [](etest::IActions &a) {
Assembler assembler;
 
 
azm/azm_example.cpp added: 57, removed: 4, total 53
@@ -14,10 +14,17 @@ int main() {
assembler.mov(Reg32::Eax, Imm32{3});
assembler.add(Reg32::Eax, Imm32{39});
assembler.mov(Reg32::Ecx, Imm32{0x4321});
 
auto end = assembler.label();
assembler.ret();
 
// TODO(robinlinden): jump here.
assembler.mov(Reg32::Edx, Imm32{0x12345678});
assembler.mov(Reg32::Ebx, Imm32{0x1234});
assembler.ret();
assembler.jmp(end);
 
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>`.