fix(interpreter): allocate stack on heap
This commit is contained in:
@@ -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<Byte>) -> Self {
|
||||
pub fn new(data: Option<Vec<Byte>>, argv: Vec<String>) -> 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<String>) -> 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<O, F>(
|
||||
&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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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<Byte>,
|
||||
}
|
||||
|
||||
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],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user