diff --git a/src/arch/x86_64/asm.rs b/src/arch/x86_64/asm.rs index ea78a21..1b43598 100644 --- a/src/arch/x86_64/asm.rs +++ b/src/arch/x86_64/asm.rs @@ -10,6 +10,8 @@ pub struct Asm { #[derive(Clone, Copy)] pub enum Instr { Mov { dst: RegMode, src: RegImmMem }, + // TODO: horrible + MemMov { reg: RegMode, offset: u64, val: u64 }, Int(u8), Call(Symbol), CallMem(Symbol), @@ -45,6 +47,18 @@ impl From for RegImmMem { } } +impl From for RegImmMem { + fn from(value: i64) -> Self { + Self::Imm(value as u64) + } +} + +impl From for RegImmMem { + fn from(value: i32) -> Self { + Self::Imm(value as u32 as u64) + } +} + mod fns { use super::*; pub fn mov(dst: RegMode, src: impl Into) -> Instr { diff --git a/src/arch/x86_64/encode.rs b/src/arch/x86_64/encode.rs index cd94a6d..264ff36 100644 --- a/src/arch/x86_64/encode.rs +++ b/src/arch/x86_64/encode.rs @@ -110,6 +110,18 @@ impl Encoder<'_> { Ok(()) } + pub fn mem_mov(&mut self, reg: RegMode, offset: u64, val: u64) { + assert!(offset <= u8::MAX as u64); + assert!(val <= u32::MAX as u64); + self.data + .extend([0x48 | ((reg.gt8() as u8) << 2), 0xc7, 0x40 | reg.base()]); + if reg.reg == rsp.reg { + self.data.push(0x24) + } + self.data.push(offset as u8); + self.data.extend((val as u32).to_le_bytes()); + } + pub fn lea(&mut self, dst: RegMode, sym: Symbol) { self.data.extend([ 0x48 | ((dst.gt8() as u8) << 2), @@ -184,6 +196,7 @@ impl Encoder<'_> { pub fn asm(&mut self, instr: Instr) -> Result<(), CompilerMsg> { match instr { Instr::Mov { dst, src } => self.mov(dst, src)?, + Instr::MemMov { reg, offset, val } => self.mem_mov(reg, offset, val), Instr::Int(code) => self.int(code), Instr::Syscall => self.syscall(), Instr::Lea { dst, sym } => self.lea(dst, sym), diff --git a/src/arch/x86_64/reg.rs b/src/arch/x86_64/reg.rs index e161f60..ea3a1e4 100644 --- a/src/arch/x86_64/reg.rs +++ b/src/arch/x86_64/reg.rs @@ -1,4 +1,4 @@ -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub struct Reg(u8); #[derive(Clone, Copy)] diff --git a/src/arch/x86_64/test/bin.rs b/src/arch/x86_64/test/bin.rs index 82af65b..1544270 100644 --- a/src/arch/x86_64/test/bin.rs +++ b/src/arch/x86_64/test/bin.rs @@ -79,10 +79,33 @@ fn windows() { let mut program = Program::::default(); let [get_std_handle, write_file, exit_process] = program.external("KERNEL32.dll", ["GetStdHandle", "WriteFile", "ExitProcess"]); + let text = b"Hello world!\n"; + let text_sym = program.ro_data("hello_en", text); + let written = program.ro_data("written", [0; 4]); let entry = program.func( "main", [BInstr::Asm(Asm { - instrs: vec![Instr::Sub, mov(ecx, 40), Instr::CallMem(exit_process)], + instrs: vec![ + Instr::Sub, + // stdout + mov(ecx, -11), + Instr::CallMem(get_std_handle), + // write + mov(rcx, rax), + lea(rdx, text_sym), + mov(r8d, text.len() as u64), + lea(r9, written), + Instr::MemMov { + reg: rsp, + offset: 0x20, + val: 0, + }, + // mov qword [rsp+32], 0 + Instr::CallMem(write_file), + // exit + mov(ecx, 39), + Instr::CallMem(exit_process), + ], })], ); program.entry = Some(entry); diff --git a/src/arch/x86_64/test/reg.rs b/src/arch/x86_64/test/reg.rs index 5fb6059..28e15f0 100644 --- a/src/arch/x86_64/test/reg.rs +++ b/src/arch/x86_64/test/reg.rs @@ -40,15 +40,15 @@ fn reg_reg() { fn reg_imm() { eq( [0x49, 0xbf, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(r15, 0x123456789abcdef0), + mov(r15, 0x123456789abcdef0u64), ); eq( [0x49, 0xb8, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(r8, 0x123456789abcdef0), + mov(r8, 0x123456789abcdef0u64), ); eq( [0x49, 0xb9, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(r9, 0x123456789abcdef0), + mov(r9, 0x123456789abcdef0u64), ); eq([0x41, 0xb9, 0x78, 0x56, 0x34, 0x12], mov(r9d, 0x12345678)); eq([0x66, 0x41, 0xb9, 0x34, 0x12], mov(r9w, 0x1234)); @@ -58,15 +58,15 @@ fn reg_imm() { eq( [0x48, 0xb8, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(rax, 0x123456789abcdef0), + mov(rax, 0x123456789abcdef0u64), ); eq( [0x48, 0xbb, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(rbx, 0x123456789abcdef0), + mov(rbx, 0x123456789abcdef0u64), ); eq( [0x48, 0xbf, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12], - mov(rdi, 0x123456789abcdef0), + mov(rdi, 0x123456789abcdef0u64), ); eq([0xbb, 0x78, 0x56, 0x34, 0x12], mov(ebx, 0x12345678)); eq([0x66, 0xbb, 0x34, 0x12], mov(bx, 0x1234)); diff --git a/x86_64_test.exe b/x86_64_test.exe index 14caa1d..6580c3d 100755 Binary files a/x86_64_test.exe and b/x86_64_test.exe differ