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