diff --git a/src/interpreter/computer.rs b/src/interpreter/computer.rs index 42e1af8..6d42b8d 100644 --- a/src/interpreter/computer.rs +++ b/src/interpreter/computer.rs @@ -1,9 +1,7 @@ -use clap::Parser; use core::fmt; -use crate::{ - Args, - operands::{Byte, ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word}, +use crate::operands::{ + Byte, ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word, }; use super::{ @@ -31,7 +29,7 @@ pub struct Computer { } impl Computer { - pub fn new(data: Vec) -> Self { + pub fn new(data: Option>, argv: Vec) -> Self { let mut computer = Self { regs: Register::new(), sregs: SegmentRegister::new(), @@ -39,28 +37,21 @@ impl Computer { memory: Memory::new(), }; log::info!("Initializing stack..."); - computer.init_stack().unwrap(); + computer.init_stack(argv).unwrap(); // Copy static data to 0x0000; log::info!("Initializing static data..."); - for (addr, b) in data.iter().enumerate() { - let val = ImmediateOperand::Byte(*b); - computer.write(val, (addr as Word).into()).unwrap(); + if let Some(inner) = data { + for (addr, b) in inner.iter().enumerate() { + let val = ImmediateOperand::Byte(*b); + computer.write(val, (addr as Word).into()).unwrap(); + } } computer } - fn init_stack(&mut self) -> Result<(), InterpreterError> { - let mut args = Args::parse(); - // cant panic, as we would not be here without a valid binary path... - let path = &args.path.unwrap(); - - // set executable name as argv[0] - let mut argv = Vec::from([path.clone()]); - // add the rest of the arguements argv[1], ... - argv.append(&mut args.argv); - + fn init_stack(&mut self, argv: Vec) -> Result<(), InterpreterError> { // set default env let envs = Vec::from(["PATH=/usr:/usr/bin".to_string()]); @@ -276,7 +267,6 @@ impl Computer { lhs - rhs }; let flag_set: fn(&mut Flags, ArithmeticResult, Lhs, Rhs) = |flags, result, lhs, rhs| { - // log::info!("{:?} {:?} {}", lhs, rhs, lhs < rhs); flags.cf = lhs < rhs; flags.of = lhs.msb() != rhs.msb() && lhs.msb() != result.msb(); flags.zf = result.zero(); @@ -364,10 +354,10 @@ impl Computer { self.op(op, flag_set, true, dest, src_with_carry) } - /// Applies a binary operator [`O`] to the value of two [`Operand`]s, saves - /// it to `dest`, if `write` is set, and sets flags, according to [`F`]. - /// A result can never be saved to an immediate Operand, so `dest` can only - /// be a [`ModRmTarget`]. + /// Applies a binary operator `O` to the value of two + /// [`ArithmeticOperand`]s, saves it to `dest`, if `write` is set, and sets + /// flags, according to `F`. A result can never be saved to an immediate + /// Operand, so `dest` can only be a [`ModRmTarget`]. fn op( &mut self, op: O, @@ -463,7 +453,7 @@ impl Computer { Ok(imm) } - /// Shift bits of data, pointed to by a [`ModRMTarget`]. + /// Shift bits of data, pointed to by a [`ModRmTarget`]. /// SHL: Direction::Left, false /// SHR: Direction::Right, false /// SAR: Direction::Right, true @@ -583,9 +573,11 @@ mod tests { #[test] fn test_push() { - let mut c = Computer::new(Vec::from([0])); + let mut c = Computer::new(None, vec!["foobar".to_string()]); + let val = ImmediateOperand::Word(0x1234); - println!("{}", c.regs); - assert_eq!(val, c.pop_stack().unwrap().into()) + c.push_stack(val).unwrap(); + let popped = c.pop_stack().unwrap(); + assert_eq!(val, popped.into()) } } diff --git a/src/interpreter/interpreter.rs b/src/interpreter/interpreter.rs index f9bbfbc..9648796 100644 --- a/src/interpreter/interpreter.rs +++ b/src/interpreter/interpreter.rs @@ -55,18 +55,25 @@ pub struct Interpreter { impl Interpreter { pub fn new(args: &Args) -> Self { let aout = Aout::new_from_args(args); + + // set executable name as argv[0] + // note: cant panic, as we would not be here without a valid binary path... + let mut argv = vec![args.path.clone().unwrap()]; + // add the rest of the arguements argv[1], ... + argv.append(&mut args.argv.clone()); + Self { - computer: Computer::new(aout.data), + computer: Computer::new(Some(aout.data), argv), disassembler: Disassembler::new(args), } } - /// Sets instruction pointer in compliance with [`Register::CS`]. + /// Sets instruction pointer in compliance with CS Segment Register. pub fn set_ip(&mut self, ip: 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 CS Segment Register. pub fn get_ip(&self) -> usize { self.computer.regs.ip + (self.computer.sregs.cs * 16) as usize } diff --git a/src/interpreter/memory.rs b/src/interpreter/memory.rs index c6906ee..ced6d78 100644 --- a/src/interpreter/memory.rs +++ b/src/interpreter/memory.rs @@ -5,15 +5,16 @@ use super::interpreter::InterpreterError; /// 2*20 = 1MiB const MEMORY_SIZE: usize = 1048576; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] pub struct Memory { - pub raw: [Byte; MEMORY_SIZE as usize], + pub raw: Vec, } impl Memory { pub fn new() -> Self { Self { - raw: [0; MEMORY_SIZE as usize], + // allocating is better for such bigger objects + raw: vec![0u8; MEMORY_SIZE], } } diff --git a/src/operands.rs b/src/operands.rs index eac4c5d..04dbffe 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -639,7 +639,8 @@ impl fmt::Display for MemoryIndex { /// 16-bit pointer for access, usually with a [`SegmentRegister`] as segment /// and [`Pointer16`] as offset. /// Generally, this type only gets constructed in rare scenarios, when the -/// [`Displacement`] of a parsed [`ModRmTarget`] is used as a raw pointer. +/// displacement ([`MemoryIndex`]) of a parsed [`ModRmTarget`] is used as a +/// raw pointer. pub struct Pointer16 { pub word: Word, }