Skip to content
This repository has been archived by the owner on Aug 30, 2024. It is now read-only.

Commit

Permalink
feat: write syscall
Browse files Browse the repository at this point in the history
  • Loading branch information
julio4 committed Jun 18, 2024
1 parent c7b61a2 commit e170080
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 28 deletions.
1 change: 1 addition & 0 deletions src/disassembler/disassembled_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub struct DisassembledProgram {
pub instructions: Vec<Instruction>,
}

#[allow(unused_variables)]
impl DisassembledProgram {
pub fn new(instructions: Vec<Instruction>, data: Vec<u8>) -> Self {
DisassembledProgram { instructions }
Expand Down
1 change: 1 addition & 0 deletions src/disassembler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ mod parser;

pub use self::decoder::{decode, Disassemblable};
pub use self::disassembled_program::DisassembledProgram;
pub use self::error::DisassemblerError;
pub use self::parser::parse_instruction;
1 change: 1 addition & 0 deletions src/interpreter/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub struct Memory {
pub data: Vec<u8>,
}

#[allow(dead_code)]
impl Memory {
pub fn new(size: usize) -> Self {
Memory {
Expand Down
11 changes: 10 additions & 1 deletion src/interpreter/register_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,17 @@ impl RegisterSet {

pub fn set(&mut self, reg: Register, value: i16) {
if let Some(val) = self.registers.get_mut(&reg) {
trace!("Set {:?}: {} (previous: {})", reg, value, *val);
trace!("Set {:?}: {:x} (previous: {:x})", reg, value, *val);
*val = value;
}
}
}

impl std::fmt::Display for RegisterSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for reg in Register::iter() {
write!(f, "{:?}: {:x}\n", reg, self.get(reg))?;
}
Ok(())
}
}
73 changes: 49 additions & 24 deletions src/interpreter/vm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::memory::Memory;
use super::register_set::RegisterSet;
use crate::utils::{min, HexdumpFormatter};
use crate::x86::{Address, Displacement};
use crate::x86::{Address, Displacement, Register};
use crate::{minix::Program, x86::IR};

use log::trace;
Expand Down Expand Up @@ -40,7 +40,7 @@ impl From<Program> for VM {

pub trait VmIrExecutable: OpcodeExecutable {
// Fetch the next chunk from text memory from ip
fn fetch(&self) -> &[u8];
fn fetch(&self) -> Option<&[u8]>;
// Decode the fetched chunk to an IR
fn decode(&self, chunk: &[u8]) -> (IR, usize);
// Execute the decoded instruction
Expand All @@ -52,26 +52,27 @@ pub trait VmIrExecutable: OpcodeExecutable {

const MAX_INSTRUCTION_SIZE: usize = 15;
impl VmIrExecutable for VM {
fn fetch(&self) -> &[u8] {
fn fetch(&self) -> Option<&[u8]> {
let ip = self.ip;
self.text
.read_bytes(ip, min(MAX_INSTRUCTION_SIZE, self.text.len() - ip as usize))
if self.text.len() <= ip as usize {
return None;
}
Some(
self.text
.read_bytes(ip, min(MAX_INSTRUCTION_SIZE, self.text.len() - ip as usize)),
)
}

fn decode(&self, chunk: &[u8]) -> (IR, usize) {
let (ins, ir_len) = match crate::disassembler::parse_instruction(chunk, self.ip.into()) {
Ok((instruction, bytes_consumed)) => (instruction, bytes_consumed),
// Err(DisassemblerError::UnexpectedEOF) => {
// (Instruction::new(IR::Undefined, text.to_vec()), text.len())
// }
// Err(DisassemblerError::UnexpectedEOF) => {}
Err(e) => panic!("Error decoding instruction: {:?}", e),
};
trace!("[DECODE] IR:\n{:?}\t{}", HexdumpFormatter(&ins.raw), ins.ir);
(ins.ir, ir_len)
}

fn execute(&mut self, ir: IR) {
trace!("[EXECUTE] {:?}", ir);
match ir {
IR::Mov { dest, src, byte } => {
self.mov(dest, src, byte);
Expand All @@ -88,15 +89,49 @@ impl VmIrExecutable for VM {
}

fn run(&mut self) {
loop {
trace!("\nVM STATE: {}", self);
let ir = self.fetch();
trace!(" AX BX CX DX SP BP SI DI FLAGS IP");
while let Some(ir) = self.fetch() {
let (decoded_ir, ir_len) = self.decode(ir);

// Trace with format:
// AX BX CX DX SP BP SI DI FLAGS IP
// 0000 0000 0000 0000 0000 0000 0000 0000 ---- 0000:bb0000 mov bx, 000
trace!(
"{} \t{}",
{
let mut regs = String::new();
for reg in vec![
Register::AX,
Register::BX,
Register::CX,
Register::DX,
Register::SP,
Register::BP,
Register::SI,
Register::DI,
] {
regs.push_str(&format!("{:04x} ", self.regs.get(reg)));
}
format!(
"{} {:04x} {:04x}:{}",
regs,
self.flags,
self.ip,
&ir[..ir_len]
.iter()
.map(|b| format!("{:02x}", b))
.collect::<String>(),
)
},
decoded_ir
);

self.execute(decoded_ir);

// Increment the instruction pointer (ip) appropriately
self.ip += ir_len as u16;
}
trace!("Execution finished:\n{}", self);
}
}

Expand Down Expand Up @@ -132,16 +167,6 @@ impl VM {
}
}

// Display for VM
// IP:
// FLAGS:
// TEXT: HEXDUMP
// DATA: HEXDUMP
//
// REG
// AX:
// BX:
// ...
impl std::fmt::Display for VM {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "IP: {:04x}", self.ip)?;
Expand All @@ -151,7 +176,7 @@ impl std::fmt::Display for VM {
writeln!(f, "DATA:")?;
writeln!(f, "{:?}", HexdumpFormatter(&self.data.data))?;
writeln!(f, "REGS:")?;
writeln!(f, "{:?}", self.regs)?;
writeln!(f, "{}", self.regs)?;
Ok(())
}
}
Expand Down
32 changes: 30 additions & 2 deletions src/interpreter/vm/opcodes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::VM;
use crate::x86::Operand;
use crate::x86::{Operand, Register};
use log::trace;

pub trait OpcodeExecutable {
Expand All @@ -25,7 +25,35 @@ impl OpcodeExecutable for VM {
match int_type {
// Syscalls
0x20 => {
trace!("SYSCALL");
// struct message {
// uint16_t m_source;
// uint16_t m_type;
// union m_u;
// };
let message_struct_ea = self.regs.get(Register::BX) as u16;
let message_source = self.data.read_word(message_struct_ea);
let message_type = self.data.read_word(message_struct_ea + 2);

match message_type {
1 => {
trace!("<exit({})>", message_source);
}
4 => {
// _sendrec
let content_len = self.data.read_word(message_struct_ea + 6);
let content_ea = self.data.read_word(message_struct_ea + 10);
trace!(
"<write({}, {:#04x}, {})>",
message_source,
content_ea,
content_len
);

let content = self.data.read_bytes(content_ea, content_len as usize);
print!("{}", String::from_utf8_lossy(content));
}
_ => unimplemented!(),
}
}
_ => unimplemented!(),
}
Expand Down
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use minix2_rs::minix::Program;

fn main() {
env_logger::builder()
.filter_level(log::LevelFilter::Trace)
.format_timestamp(None)
.format_module_path(false)
.format_target(false)
// .filter_level(log::LevelFilter::Trace)
.filter_level(log::LevelFilter::Info)
.init();

let args: Vec<String> = std::env::args().collect();
Expand Down

0 comments on commit e170080

Please sign in to comment.