ft: initial disasm of example data

This only contains two instructions of which I know
the correct output.
This commit is contained in:
2025-05-07 15:48:44 +09:00
commit 2af4578c8b
8 changed files with 804 additions and 0 deletions

103
src/disasm.rs Normal file
View File

@@ -0,0 +1,103 @@
use core::fmt;
use std::{fs::File, io::Read, process::exit};
use crate::aout::Aout;
use crate::{
Args,
instructions::{ImmediateByte, ImmediateWord, Instruction, MetaInstruction, Register},
};
#[derive(Debug)]
pub enum DisasmError {
NoFile(Option<String>),
IoError(std::io::Error),
}
impl From<std::io::Error> for DisasmError {
fn from(error: std::io::Error) -> Self {
DisasmError::IoError(error)
}
}
impl fmt::Display for DisasmError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DisasmError::NoFile(msg) => write!(f, "No file error: {:?}", msg),
DisasmError::IoError(msg) => write!(f, "{}", msg),
}
}
}
/// Disassemble the binary in `path` into a vector of instructions
/// This function just calls all other
pub fn disasm(args: &Args) -> Result<Vec<MetaInstruction>, DisasmError> {
let contents = path_to_buf(args)?;
let aout = Aout::new(contents);
// XXX: 00 is just 0, maybe this could be a problem?
log::debug!("{:?}", aout);
let instructions = decode_instructions(&aout)?;
Ok(instructions)
}
/// Read a filepath into a buffer
fn path_to_buf(args: &Args) -> Result<Vec<u8>, DisasmError> {
let path = args
.path
.clone()
.ok_or(DisasmError::NoFile(args.path.clone()))?;
let mut file = File::open(path)?;
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
Ok(buf)
}
/// Decode instructions from the text section of the provided binary
fn decode_instructions(aout: &Aout) -> Result<Vec<MetaInstruction>, DisasmError> {
// naive approach:
// 1. read byte
// 2. pattern match to see which instruction it is
// 3. read as many bytes as this instruction needs (registers, immidiates, ...)
// repeat until no bytes left
let instructions = Vec::new();
let mut offset = 0;
let text = &aout.text;
while offset < aout.text.len() {
let mut instr = MetaInstruction::new();
instr.start = offset;
let opcode = text[offset];
match opcode {
// 0x00 => {} // ADD
// INT
0xCD => {
instr.take_n_bytes(2, &mut offset, text);
instr.instruction = Instruction::INT(ImmediateByte(instr.raw[1]));
}
// MOV
0xBB => {
instr.take_n_bytes(3, &mut offset, text);
instr.instruction = Instruction::MOV_RI(
Register::BX,
ImmediateWord(u16::from_le_bytes([instr.raw[1], instr.raw[2]])),
);
}
_ => {
eprintln!("Encountered unknown instruction '0x{:x}'", opcode);
eprintln!("Offset might be misaligned and data is being interpreted.");
eprintln!("Existing to avoid further misinterpretation...");
exit(1);
}
};
println!("{}", instr);
// dbg!(&instr);
}
Ok(instructions)
}