ft(interpreter): expose data to memory
This commit is contained in:
@@ -3,7 +3,7 @@ use core::fmt;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Args,
|
Args,
|
||||||
operands::{ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word},
|
operands::{Byte, ImmediateOperand, ImmediateOperandSigned, MemoryIndex, ModRmTarget, Word},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -31,21 +31,20 @@ pub struct Computer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Computer {
|
impl Computer {
|
||||||
pub fn new() -> Self {
|
pub fn new(data: Vec<Byte>) -> Self {
|
||||||
let mut computer = Self {
|
let mut computer = Self {
|
||||||
regs: Register::new(),
|
regs: Register::new(),
|
||||||
sregs: SegmentRegister::new(),
|
sregs: SegmentRegister::new(),
|
||||||
flags: Flags::new(),
|
flags: Flags::new(),
|
||||||
memory: Memory::new(),
|
memory: Memory::new(),
|
||||||
};
|
};
|
||||||
// Initialization cannot fail
|
|
||||||
computer.init_stack().unwrap();
|
computer.init_stack().unwrap();
|
||||||
|
|
||||||
// for (idx, val) in computer.memory.raw.iter().enumerate() {
|
// Copy static data to 0x0000;
|
||||||
// if idx > 0xfff9 && idx <= 0xffff {
|
for (addr, b) in data.iter().enumerate() {
|
||||||
// log::debug!("MEMORY {idx}: {val}");
|
let val = ImmediateOperand::Byte(*b);
|
||||||
// }
|
computer.write(val, (addr as Word).into()).unwrap();
|
||||||
// }
|
}
|
||||||
|
|
||||||
computer
|
computer
|
||||||
}
|
}
|
||||||
@@ -328,6 +327,7 @@ impl Computer {
|
|||||||
ArithmeticOperand::ModRmTarget(target) => self.read_modrm(target)?,
|
ArithmeticOperand::ModRmTarget(target) => self.read_modrm(target)?,
|
||||||
};
|
};
|
||||||
let result = op(lhs, rhs);
|
let result = op(lhs, rhs);
|
||||||
|
log::debug!("{:04x} <op> {:04x} = {:04x}", lhs, rhs, result);
|
||||||
if write {
|
if write {
|
||||||
self.write_modrm(dest, result)?;
|
self.write_modrm(dest, result)?;
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push() {
|
fn test_push() {
|
||||||
let mut c = Computer::new();
|
let mut c = Computer::new(Vec::from([0]));
|
||||||
let val = ImmediateOperand::Word(0x1234);
|
let val = ImmediateOperand::Word(0x1234);
|
||||||
println!("{}", c.regs);
|
println!("{}", c.regs);
|
||||||
assert_eq!(val, c.pop_stack().unwrap().into())
|
assert_eq!(val, c.pop_stack().unwrap().into())
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ type InstructionPointer<'a> = std::slice::Iter<'a, Instruction>;
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum InterpreterError {
|
pub enum InterpreterError {
|
||||||
EndOfData,
|
|
||||||
InvalidSyscall(Byte),
|
InvalidSyscall(Byte),
|
||||||
InstructionNotFound(Word),
|
InstructionNotFound(Word),
|
||||||
MemoryOutOfBound(Word),
|
MemoryOutOfBound(Word),
|
||||||
@@ -29,7 +28,6 @@ pub enum InterpreterError {
|
|||||||
impl fmt::Display for InterpreterError {
|
impl fmt::Display for InterpreterError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
InterpreterError::EndOfData => write!(f, "Read beyond the available data section"),
|
|
||||||
InterpreterError::InvalidSyscall(id) => {
|
InterpreterError::InvalidSyscall(id) => {
|
||||||
write!(f, "The syscall with ID {} is unknown", id)
|
write!(f, "The syscall with ID {} is unknown", id)
|
||||||
}
|
}
|
||||||
@@ -50,15 +48,13 @@ impl fmt::Display for InterpreterError {
|
|||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
computer: Computer,
|
computer: Computer,
|
||||||
instructions: Vec<Instruction>,
|
instructions: Vec<Instruction>,
|
||||||
data: Vec<Byte>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
pub fn new(instructions: Vec<Instruction>, data: Vec<Byte>) -> Self {
|
pub fn new(instructions: Vec<Instruction>, data: Vec<Byte>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
computer: Computer::new(),
|
computer: Computer::new(data),
|
||||||
instructions,
|
instructions,
|
||||||
data,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,14 +777,13 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn interpret_interrupt(&self, id: u8) -> Result<(), InterpreterError> {
|
fn interpret_interrupt(&self, id: u8) -> Result<(), InterpreterError> {
|
||||||
let bx = self.computer.regs.bx.read() as usize;
|
let bx = self.computer.regs.bx.read();
|
||||||
// a message is always 8 words aligned
|
let w1 = self.computer.read(bx.into())?;
|
||||||
let len = 2 * 8;
|
let w2 = self.computer.read((bx + 2).into())?;
|
||||||
let data = self
|
|
||||||
.data
|
let mut data = Vec::new();
|
||||||
.get(bx..bx + len)
|
data.extend_from_slice(&w1.to_le_bytes());
|
||||||
.ok_or(InterpreterError::EndOfData)?
|
data.extend_from_slice(&w2.to_le_bytes());
|
||||||
.to_owned();
|
|
||||||
|
|
||||||
let msg = InterruptMessage::new(&data);
|
let msg = InterruptMessage::new(&data);
|
||||||
|
|
||||||
@@ -812,7 +807,7 @@ impl Interpreter {
|
|||||||
let len = data.i2;
|
let len = data.i2;
|
||||||
let location = data.p1;
|
let location = data.p1;
|
||||||
log::info!("executing write({}, {}, {})", fd, location, len);
|
log::info!("executing write({}, {}, {})", fd, location, len);
|
||||||
for byte in &self.data[location as usize..] {
|
for byte in &self.computer.memory.raw[location as usize..] {
|
||||||
if *byte == 0x00 {
|
if *byte == 0x00 {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::operands::{Byte, ImmediateOperand, Word};
|
use crate::operands::{Byte, ImmediateOperand, Word};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use super::interpreter::InterpreterError;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
pub ax: AX,
|
pub ax: AX,
|
||||||
|
|||||||
@@ -539,6 +539,16 @@ pub struct MemoryIndex {
|
|||||||
pub displacement: Option<ImmediateOperand>,
|
pub displacement: Option<ImmediateOperand>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<MemoryIndex> for u16 {
|
||||||
|
fn into(self) -> MemoryIndex {
|
||||||
|
MemoryIndex {
|
||||||
|
base: None,
|
||||||
|
index: None,
|
||||||
|
displacement: Some(self.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for MemoryIndex {
|
impl fmt::Display for MemoryIndex {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match &self.base {
|
match &self.base {
|
||||||
|
|||||||
Reference in New Issue
Block a user