ft(interpreter): impl simple stack init
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
use clap::Parser;
|
||||
use core::fmt;
|
||||
|
||||
use crate::operands::{ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word};
|
||||
use crate::{
|
||||
Args,
|
||||
operands::{ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word},
|
||||
};
|
||||
|
||||
use super::{
|
||||
flags::Flags, interpreter::InterpreterError, memory::Memory, register::Register,
|
||||
@@ -28,17 +32,80 @@ pub struct Computer {
|
||||
|
||||
impl Computer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
let mut computer = Self {
|
||||
regs: Register::new(),
|
||||
sregs: SegmentRegister::new(),
|
||||
flags: Flags::new(),
|
||||
memory: Memory::new(),
|
||||
};
|
||||
// Initialization cannot fail
|
||||
computer.init_stack().unwrap();
|
||||
|
||||
// for (idx, val) in computer.memory.raw.iter().enumerate() {
|
||||
// if idx > 0xfff9 && idx <= 0xffff {
|
||||
// log::debug!("MEMORY {idx}: {val}");
|
||||
// }
|
||||
// }
|
||||
|
||||
computer
|
||||
}
|
||||
|
||||
fn init_stack(&mut self) -> Result<(), InterpreterError> {
|
||||
let args = Args::parse();
|
||||
let argv = args.argv;
|
||||
let argc = argv.len() + 1;
|
||||
let mut argv_ptrs = Vec::new();
|
||||
|
||||
let envs = Vec::from(["PATH=/usr:/usr/bin".to_string()]);
|
||||
let mut env_ptrs = Vec::new();
|
||||
|
||||
// Padding
|
||||
let total_len_argv: usize = argv.iter().map(|i| i.len()).sum();
|
||||
let total_len_env: usize = envs.iter().map(|i| i.len()).sum();
|
||||
|
||||
if total_len_argv + total_len_env % 2 != 0 {
|
||||
self.push_stack(ImmediateOperand::Byte(0))?;
|
||||
}
|
||||
|
||||
// Write env
|
||||
for env in envs.iter() {
|
||||
for b in env.chars().rev() {
|
||||
self.push_stack(ImmediateOperand::Byte(b as u8))?;
|
||||
}
|
||||
env_ptrs.push(self.regs.sp);
|
||||
}
|
||||
|
||||
// Write argv
|
||||
for arg in argv.iter() {
|
||||
// self.push_stack(ImmediateOperand::Byte(0))?;
|
||||
for b in arg.chars().rev() {
|
||||
self.push_stack(ImmediateOperand::Byte(b as u8))?;
|
||||
}
|
||||
argv_ptrs.push(self.regs.sp);
|
||||
}
|
||||
|
||||
// add env ptrs
|
||||
for addr in env_ptrs {
|
||||
self.push_stack(addr.into())?;
|
||||
}
|
||||
|
||||
// delimiter
|
||||
self.push_stack(ImmediateOperand::Word(0))?;
|
||||
|
||||
// add argv ptrs
|
||||
for addr in argv_ptrs {
|
||||
self.push_stack(addr.into())?;
|
||||
}
|
||||
|
||||
// add argc
|
||||
self.push_stack(ImmediateOperand::Word(argc as Word))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Decrement stack pointer and write `val` onto the stack.
|
||||
pub fn push_stack(&mut self, val: ImmediateOperand) -> Result<(), InterpreterError> {
|
||||
self.regs.push_sp()?;
|
||||
self.regs.push_sp();
|
||||
self.memory.write_raw(
|
||||
self.mem_addr(
|
||||
ImmediateOperand::from(self.regs.sp).into(),
|
||||
@@ -54,7 +121,7 @@ impl Computer {
|
||||
ImmediateOperand::from(self.regs.sp).into(),
|
||||
&crate::register::SegmentRegister::SS,
|
||||
))?;
|
||||
self.regs.pop_sp()?;
|
||||
self.regs.pop_sp();
|
||||
Ok(word)
|
||||
}
|
||||
|
||||
@@ -395,7 +462,7 @@ mod tests {
|
||||
fn test_push() {
|
||||
let mut c = Computer::new();
|
||||
let val = ImmediateOperand::Word(0x1234);
|
||||
c.push_stack(val).unwrap();
|
||||
println!("{}", c.regs);
|
||||
assert_eq!(val, c.pop_stack().unwrap().into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ pub enum InterpreterError {
|
||||
InvalidSyscall(Byte),
|
||||
InstructionNotFound(Word),
|
||||
MemoryOutOfBound(Word),
|
||||
InvalidRegisterState(crate::interpreter::register::Register),
|
||||
}
|
||||
|
||||
impl fmt::Display for InterpreterError {
|
||||
@@ -43,9 +42,6 @@ impl fmt::Display for InterpreterError {
|
||||
"Attempted memory write out of physical bounds: ({addr:#04x})"
|
||||
)
|
||||
}
|
||||
InterpreterError::InvalidRegisterState(reg) => {
|
||||
write!(f, "Invalid Register State: {reg:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ const MEMORY_SIZE: usize = 1048576;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Memory {
|
||||
memory: [Byte; MEMORY_SIZE as usize],
|
||||
pub raw: [Byte; MEMORY_SIZE as usize],
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
memory: [0; MEMORY_SIZE as usize],
|
||||
raw: [0; MEMORY_SIZE as usize],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ impl Memory {
|
||||
} else {
|
||||
match val {
|
||||
ImmediateOperand::Byte(b) => {
|
||||
self.memory[addr as usize] = b;
|
||||
self.raw[addr as usize] = b;
|
||||
}
|
||||
ImmediateOperand::Word(w) => {
|
||||
let [low, high] = w.to_le_bytes();
|
||||
self.memory[addr as usize] = low;
|
||||
self.memory[(addr + 1) as usize] = high;
|
||||
self.raw[addr as usize] = low;
|
||||
self.raw[(addr + 1) as usize] = high;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,12 +41,12 @@ impl Memory {
|
||||
/// Warning: Does access at `addr`, not `DS:addr`!
|
||||
pub fn read_raw(&self, addr: Word) -> Result<Word, InterpreterError> {
|
||||
let b1 = self
|
||||
.memory
|
||||
.raw
|
||||
.get(addr as usize)
|
||||
.ok_or(InterpreterError::MemoryOutOfBound(addr))?
|
||||
.to_owned();
|
||||
let b2 = self
|
||||
.memory
|
||||
.raw
|
||||
.get((addr + 1) as usize)
|
||||
.ok_or(InterpreterError::MemoryOutOfBound(addr))?
|
||||
.to_owned();
|
||||
|
||||
@@ -22,7 +22,7 @@ impl Register {
|
||||
bx: BX::new(),
|
||||
cx: CX::new(),
|
||||
dx: DX::new(),
|
||||
sp: 0xffda,
|
||||
sp: 0,
|
||||
bp: 0,
|
||||
si: 0,
|
||||
di: 0,
|
||||
@@ -30,23 +30,17 @@ impl Register {
|
||||
}
|
||||
|
||||
/// Decrement stack pointer
|
||||
pub fn push_sp(&mut self) -> Result<(), InterpreterError> {
|
||||
if self.sp < 2 {
|
||||
return Err(InterpreterError::InvalidRegisterState(*self));
|
||||
} else {
|
||||
self.sp -= 2;
|
||||
Ok(())
|
||||
}
|
||||
pub fn push_sp(&mut self) {
|
||||
log::debug!("SP before push: {:04x}", self.sp);
|
||||
self.sp = self.sp.wrapping_sub(2);
|
||||
log::debug!("SP after push: {:04x}", self.sp);
|
||||
}
|
||||
|
||||
/// Increment stack pointer
|
||||
pub fn pop_sp(&mut self) -> Result<(), InterpreterError> {
|
||||
if self.sp > 0xffff - 2 {
|
||||
return Err(InterpreterError::InvalidRegisterState(*self));
|
||||
} else {
|
||||
self.sp += 2;
|
||||
Ok(())
|
||||
}
|
||||
pub fn pop_sp(&mut self) {
|
||||
log::debug!("SP before pop: {:04x}", self.sp);
|
||||
self.sp = self.sp.wrapping_add(2);
|
||||
log::debug!("SP after pop: {:04x}", self.sp);
|
||||
}
|
||||
|
||||
/// Read value from a [`crate::register::Register`].
|
||||
|
||||
14
src/main.rs
14
src/main.rs
@@ -36,11 +36,23 @@ struct Args {
|
||||
/// Dump progress of disassembly, in case of encountering an error.
|
||||
#[arg(short, long, global = true, action)]
|
||||
dump: bool,
|
||||
|
||||
/// argv passed to the program, which will be interpreted
|
||||
#[arg(trailing_var_arg = true, global = true)]
|
||||
argv: Vec<String>,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Builder::new()
|
||||
.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args()))
|
||||
.format(|buf, record| {
|
||||
writeln!(
|
||||
buf,
|
||||
"{} {}: {}",
|
||||
record.target(),
|
||||
record.level(),
|
||||
record.args()
|
||||
)
|
||||
})
|
||||
.parse_default_env()
|
||||
.init();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user