Files
lang/src/arch/x86_64/test/bin.rs
T
2026-06-09 01:02:40 -04:00

138 lines
3.9 KiB
Rust

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::<X86_64>::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::<X86_64>::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,
// 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);
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");
}