use crate::{ arch::x86_64::*, backend::{Instr as BInstr, Program}, }; use std::{fs::OpenOptions, io::Write, os::unix::fs::OpenOptionsExt, process::Command}; pub fn run() { windows(); // linux(); } fn linux() { let mut program = Program::::default(); let text = b"Hello world!\n"; let text_sym = program.ro_data("hello_en", text); let text2 = "世界、こんにちは!\n"; let text_sym2 = program.ro_data("hello_jp", text2); let hello2 = program.func( "hello2", [BInstr::Asm(Asm { instrs: vec![ mov(ax, 1), mov(di, 1), lea(rsi, text_sym2), mov(dx, text2.len() as u64), Instr::Syscall, Instr::Ret, ], })], ); let entry = program.func( "main", [BInstr::Asm(Asm { instrs: vec![ mov(di, 39), push(rdi), mov(ax, 1), mov(di, 1), lea(rsi, text_sym), mov(dx, text.len() as u64), Instr::Syscall, Instr::Call(hello2), mov(ax, 0x3c), pop(rdi), Instr::Syscall, ], })], ); program.entry = Some(entry); let linked = program.compile().expect("failed to compile"); let binary = linked.to_elf(); let path = "./x86_64_test"; write(path, &binary); println!("running..."); let gdb = false; let mut proc = if gdb { let mut cmd = Command::new("gdb"); #[rustfmt::skip] cmd.args([ "-q", "-ex", "starti", "-ex", "layout asm", "-ex", "focus next", "x86_64_test", ]); cmd } else { Command::new(path) } .spawn() .expect("failed to run"); let status = proc.wait().expect("failed to wait"); if let Some(code) = status.code() { std::process::exit(code); } } fn windows() { let mut program = Program::::default(); let [get_std_handle, write_file, exit_process] = program.external("KERNEL32.dll", ["GetStdHandle", "WriteFile", "ExitProcess"]); let entry = program.func( "main", [BInstr::Asm(Asm { instrs: vec![Instr::Sub, mov(ecx, 40), Instr::CallMem(exit_process)], })], ); program.entry = Some(entry); let linked = program.compile().expect("failed to compile"); let binary = linked.to_pe(); let path = "./x86_64_test.exe"; write(path, &binary); let mut cmd = Command::new("wine"); cmd.arg("x86_64_test"); let mut proc = cmd.spawn().expect("failed to run"); let status = proc.wait().expect("failed to wait"); if let Some(code) = status.code() { std::process::exit(code); } } fn write(path: &str, binary: &[u8]) { let mut file = OpenOptions::new() .create(true) .write(true) .truncate(true) .mode(0o750) .open(path) .expect("Failed to create file"); file.write_all(binary).expect("Failed to write to file"); file.sync_all().expect("Failed to sync file"); }