ft: initial disasm of example data
This only contains two instructions of which I know the correct output.
This commit is contained in:
103
src/disasm.rs
Normal file
103
src/disasm.rs
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user