diff --git a/src/disasm.rs b/src/disasm.rs index 7e9e375..c10d745 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -87,6 +87,7 @@ pub struct Disassembler { pub aout: Aout, // the aout binary pub instruction: Instruction, // the instruction, which is currently being parsed instructions: Vec, // all parsed instructions + dump: bool, // Dump dissambly progress, if an error occurs } impl Disassembler { @@ -98,13 +99,15 @@ impl Disassembler { aout, instruction: Instruction::new(), instructions: Vec::new(), + dump: args.dump, } } /// Start the disassmble and allow for some error handling wrapped around - /// the actual decoding function. - pub fn disassemble(&mut self, dump: bool) -> Result, DisasmError> { - let is_ok = self.decode_instructions(); + /// the actual [`Self::decode_all_instructions()`] function. + /// Also removes NULL padding from the end of the disassembly. + pub fn disassemble(&mut self) -> Result<(), DisasmError> { + let is_ok = self.decode_all_instructions(); // a.out pads the text section to byte align, so the fasely interpreted // instructions have to be removed. @@ -114,19 +117,28 @@ impl Disassembler { // to allow some error's to act as warnings (see below) let instructions = self.instructions.clone(); + let dump = + |instructions: Vec| instructions.iter().for_each(|i| println!("{i}")); + // allow for warning-type errors to pass through, as they are not fatal match is_ok { - Ok(_) => Ok(instructions), + Ok(_) => { + dump(instructions); + Ok(()) + } Err(e) => match e { + // not an error per-se DisasmError::EndOfTextSection => { log::debug!("Solo padded 0-byte at end of file was found. Ignoring."); - Ok(instructions) + dump(instructions); + Ok(()) } + // actual errors _ => { - if dump { - self.instructions.iter().for_each(|i| println!("{i}")); + if self.dump { + dump(instructions); println!( - "Encountered error during disassembly, but this is the process so far...\n{e}\nRun with RUST_LOG=debug for furhter information." + "Encountered error during disassembly, but this is the process so far...\n{e}\nRun with RUST_LOG=debug for further information." ); } else { println!( @@ -483,9 +495,11 @@ impl Disassembler { self.instructions.truncate(until); } - fn decode_instructions(&mut self) -> Result<(), DisasmError> { + /// Decode all available instruction, starting from `self.offset`. + fn decode_all_instructions(&mut self) -> Result<(), DisasmError> { while self.offset < self.aout.text.len() { - self.decode_instruction()?; + let instruction = self.decode_instruction()?; + self.instructions.push(instruction); // Advance offset to hover the next potential opcode self.offset += 1; @@ -494,11 +508,11 @@ impl Disassembler { Ok(()) } - /// Decode an instruction by matching byte signature to their mnemonics and - /// depending on the instruction, parsing some operands afterwards. - /// All parsing is done in capsulated functions, here everything just - /// gets consolodated. - pub fn decode_instruction(&mut self) -> Result<(), DisasmError> { + /// Decode the instruction at `self.offset` by matching byte signature to + /// their mnemonics and depending on the instruction, parsing some operands + /// afterwards. All parsing is done in capsulated functions, here everything + /// just gets consolodated. + pub fn decode_instruction(&mut self) -> Result { // reset mutable current instruction self.instruction = Instruction::new(); self.instruction.addr = self.offset; @@ -899,11 +913,8 @@ impl Disassembler { } }; - // Save parsed instruction log::debug!("Parsed {}", self.instruction); - self.instructions.push(self.instruction.clone()); - - Ok(()) + Ok(self.instruction.clone()) } } diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index b39a815..595dc5d 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -48,10 +48,8 @@ impl fmt::Display for InterpreterError { #[derive(Debug, Clone)] pub struct Interpreter { - computer: Computer, - text: Vec, - ip: usize, - disassembler: Disassembler, + computer: Computer, // current cpu state + disassembler: Disassembler, // fetcher, currently holds all instruction data } impl Interpreter { @@ -59,34 +57,32 @@ impl Interpreter { let aout = Aout::new_from_args(args); Self { computer: Computer::new(aout.data), - text: aout.text, - ip: 0, disassembler: Disassembler::new(args), } } /// Sets instruction pointer in compliance with [`Register::CS`]. pub fn set_ip(&mut self, ip: usize) { - self.ip = ip + (self.computer.sregs.cs * 16) as usize + self.computer.regs.ip = ip + (self.computer.sregs.cs * 16) as usize } /// Gets instruction pointer in compliance with [`Register::CS`]. pub fn get_ip(&self) -> usize { - self.ip + (self.computer.sregs.cs * 16) as usize + self.computer.regs.ip + (self.computer.sregs.cs * 16) as usize } pub fn interpret(&mut self) -> Result<(), InterpreterError> { - while self.ip < self.text.len() { + while self.computer.regs.ip < self.disassembler.aout.text.len() { log::debug!("=============== Fetching next instruction... ==============="); - self.disassembler.offset = self.ip; - self.disassembler + self.disassembler.offset = self.computer.regs.ip; + let current_instruction = self + .disassembler .decode_instruction() .map_err(|e| InterpreterError::FetchError(e.to_string()))?; - let current_instruction = self.disassembler.instruction.clone(); log::info!( "({:04x}) {:<32} {}", - current_instruction.addr, + self.computer.regs.ip, current_instruction.mnemonic.to_string(), self.computer, ); @@ -845,7 +841,7 @@ impl Interpreter { } // Go to next instruction - self.ip += current_instruction.raw.len(); + self.computer.regs.ip += current_instruction.raw.len(); } Ok(()) diff --git a/src/interpreter/register.rs b/src/interpreter/register.rs index 2315dc9..a39c77c 100644 --- a/src/interpreter/register.rs +++ b/src/interpreter/register.rs @@ -11,6 +11,7 @@ pub struct Register { pub bp: Word, pub si: Word, pub di: Word, + pub ip: usize, } impl Register { @@ -24,6 +25,7 @@ impl Register { bp: 0, si: 0, di: 0, + ip: 0, } } diff --git a/src/main.rs b/src/main.rs index 7697dce..9768d54 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,12 +55,8 @@ fn main() { match args.command { Command::Disassemble => { - let mut disasm = Disassembler::new(&args); - let instructions = disasm.disassemble(args.dump); - match instructions { - Ok(instrs) => instrs.iter().for_each(|i| println!("{i}")), - _ => {} - } + let mut disassembler = Disassembler::new(&args); + disassembler.disassemble().unwrap(); } Command::Interpret => { let mut interpreter = Interpreter::new(&args);