fix(interpreter): impl fetch and decode

I parsed all instructions before executing, but this is not how
intel works.
We need to decode the instructions, pointed to by IP, on the fly.
This commit is contained in:
2025-07-01 12:04:20 +09:00
parent f3fd655908
commit a5cffa4852
5 changed files with 511 additions and 539 deletions

View File

@@ -1,9 +1,13 @@
//! Internal a.out File abstraction. //! Internal a.out File abstraction.
use core::fmt; use core::fmt;
use std::ffi::{c_uchar, c_ushort}; use std::{
ffi::{c_uchar, c_ushort},
fs::File,
io::Read,
};
use crate::operands::Byte; use crate::{Args, disasm::DisasmError, operands::Byte};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type c_long = i32; // we use a a.out with 32 byte pub type c_long = i32; // we use a a.out with 32 byte
@@ -25,6 +29,20 @@ impl fmt::Display for Aout {
} }
impl Aout { impl Aout {
pub fn new_from_args(args: &Args) -> Self {
let path = args
.path
.clone()
.ok_or(DisasmError::NoFile(args.path.clone()))
.unwrap();
let mut file = File::open(path).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
let aout = Aout::new(buf);
log::debug!("{:?}", aout);
aout
}
pub fn new(buf: Vec<u8>) -> Self { pub fn new(buf: Vec<u8>) -> Self {
let hdr = Header { let hdr = Header {
magic: [buf[0], buf[1]], magic: [buf[0], buf[1]],

View File

@@ -12,7 +12,6 @@ use crate::{
}; };
use crate::{modrm_8b_register, modrm_16b_register, modrm_sregister}; use crate::{modrm_8b_register, modrm_16b_register, modrm_sregister};
use core::fmt; use core::fmt;
use std::{fs::File, io::Read};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
/// Select, wheter 8, or 16-bit Registers should be selected. /// Select, wheter 8, or 16-bit Registers should be selected.
@@ -84,24 +83,15 @@ impl fmt::Display for DisasmError {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Disassembler { pub struct Disassembler {
offset: usize, // the current offset in the disasm process pub offset: usize, // the current offset in the disasm process
pub aout: Aout, // the aout binary pub aout: Aout, // the aout binary
instruction: Instruction, // the instruction, which is currently being parsed pub instruction: Instruction, // the instruction, which is currently being parsed
instructions: Vec<Instruction>, // all parsed instructions instructions: Vec<Instruction>, // all parsed instructions
} }
impl Disassembler { impl Disassembler {
pub fn new(args: &Args) -> Self { pub fn new(args: &Args) -> Self {
let path = args let aout = Aout::new_from_args(args);
.path
.clone()
.ok_or(DisasmError::NoFile(args.path.clone()))
.unwrap();
let mut file = File::open(path).unwrap();
let mut buf = Vec::new();
file.read_to_end(&mut buf).unwrap();
let aout = Aout::new(buf);
log::debug!("{:?}", aout);
Disassembler { Disassembler {
offset: 0, offset: 0,
@@ -472,7 +462,7 @@ impl Disassembler {
fn remove_trailing_padding(&mut self) { fn remove_trailing_padding(&mut self) {
let mut until = self.instructions.len(); let mut until = self.instructions.len();
for i in self.instructions.iter().rev() { for i in self.instructions.iter().rev() {
match i.opcode { match i.mnemonic {
// 0x00 0x00 in binary // 0x00 0x00 in binary
Mnemonic::ADD_FromReg( Mnemonic::ADD_FromReg(
ModRmTarget::Memory(MemoryIndex { ModRmTarget::Memory(MemoryIndex {
@@ -493,416 +483,9 @@ impl Disassembler {
self.instructions.truncate(until); self.instructions.truncate(until);
} }
/// Decode instructions by matching byte signature to their mnemonics and
/// depending on the instruction, parsing some operands afterwards.
/// All parsing is done in capsulated functions, here everything just
/// gets consolodated.
fn decode_instructions(&mut self) -> Result<(), DisasmError> { fn decode_instructions(&mut self) -> Result<(), DisasmError> {
log::debug!("Starting to decode text of length {}", self.aout.text.len());
while self.offset < self.aout.text.len() { while self.offset < self.aout.text.len() {
// reset mutable current instruction self.decode_instruction()?;
self.instruction = Instruction::new();
self.instruction.addr = self.offset;
// fetch next opcode
let opcode = self.aout.text[self.offset];
// additional raw bytes will be pushed by parse functions
self.instruction.raw.push(opcode);
log::debug!("Parsing next opcode with opcode: {opcode:#04x}");
self.instruction.opcode = match opcode {
0x00 => modrm_8b_register!(self, ADD_FromReg),
0x01 => modrm_16b_register!(self, ADD_FromReg),
0x02 => modrm_8b_register!(self, ADD_ToReg),
0x03 => modrm_16b_register!(self, ADD_ToReg),
0x04 => Mnemonic::ADD_ALIb(self.parse_byte()?),
0x05 => Mnemonic::ADD_AXIv(self.parse_word()?),
0x06 => Mnemonic::PUSH_S(SegmentRegister::ES),
0x07 => Mnemonic::POP_S(SegmentRegister::ES),
0x08 => modrm_8b_register!(self, OR_FromReg),
0x09 => modrm_16b_register!(self, OR_FromReg),
0x0A => modrm_8b_register!(self, OR_ToReg),
0x0B => modrm_16b_register!(self, OR_ToReg),
0x0C => Mnemonic::OR_ALIb(self.parse_byte()?),
0x0D => Mnemonic::OR_AXIv(self.parse_word()?),
0x0E => Mnemonic::PUSH_S(SegmentRegister::CS),
0x0F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x10 => modrm_8b_register!(self, ADC_FromReg),
0x11 => modrm_16b_register!(self, ADC_FromReg),
0x12 => modrm_8b_register!(self, ADC_ToReg),
0x13 => modrm_16b_register!(self, ADC_ToReg),
0x14 => Mnemonic::ADC_ALIb(self.parse_byte()?),
0x15 => Mnemonic::ADC_AXIv(self.parse_word()?),
0x16 => Mnemonic::PUSH_S(SegmentRegister::SS),
0x17 => Mnemonic::POP_S(SegmentRegister::SS),
0x18 => modrm_8b_register!(self, SBB_FromReg),
0x19 => modrm_16b_register!(self, SBB_FromReg),
0x1A => modrm_8b_register!(self, SBB_ToReg),
0x1B => modrm_16b_register!(self, SBB_ToReg),
0x1C => Mnemonic::SBB_ALIb(self.parse_byte()?),
0x1D => Mnemonic::SBB_AXIv(self.parse_word()?),
0x1E => Mnemonic::PUSH_S(SegmentRegister::DS),
0x1F => Mnemonic::POP_S(SegmentRegister::DS),
0x20 => modrm_8b_register!(self, AND_FromReg),
0x21 => modrm_16b_register!(self, AND_FromReg),
0x22 => modrm_8b_register!(self, AND_ToReg),
0x23 => modrm_16b_register!(self, AND_ToReg),
0x24 => Mnemonic::AND_ALIb(self.parse_byte()?),
0x25 => Mnemonic::AND_AXIv(self.parse_word()?),
0x26 => Mnemonic::OVERRIDE(SegmentRegister::ES),
0x27 => Mnemonic::DAA,
0x28 => modrm_8b_register!(self, SUB_FromReg),
0x29 => modrm_16b_register!(self, SUB_FromReg),
0x2A => modrm_8b_register!(self, SUB_ToReg),
0x2B => modrm_16b_register!(self, SUB_ToReg),
0x2C => Mnemonic::SUB_ALIb(self.parse_byte()?),
0x2D => Mnemonic::SUB_AXIv(self.parse_word()?),
0x2E => Mnemonic::OVERRIDE(SegmentRegister::CS),
0x2F => Mnemonic::DAS,
0x30 => modrm_8b_register!(self, XOR_FromReg),
0x31 => modrm_16b_register!(self, XOR_FromReg),
0x32 => modrm_8b_register!(self, XOR_ToReg),
0x33 => modrm_16b_register!(self, XOR_ToReg),
0x34 => Mnemonic::XOR_ALIb(self.parse_byte()?),
0x35 => Mnemonic::XOR_AXIv(self.parse_word()?),
0x36 => Mnemonic::OVERRIDE(SegmentRegister::SS),
0x37 => Mnemonic::AAA,
0x38 => modrm_8b_register!(self, CMP_FromReg),
0x39 => modrm_16b_register!(self, CMP_FromReg),
0x3A => modrm_8b_register!(self, CMP_ToReg),
0x3B => modrm_16b_register!(self, CMP_ToReg),
0x3C => Mnemonic::CMP_ALIb(self.parse_byte()?),
0x3D => Mnemonic::CMP_AXIv(self.parse_word()?),
0x3E => Mnemonic::OVERRIDE(SegmentRegister::DS),
0x3F => Mnemonic::AAS,
0x40 => Mnemonic::INC_Reg(Register::AX),
0x41 => Mnemonic::INC_Reg(Register::CX),
0x42 => Mnemonic::INC_Reg(Register::DX),
0x43 => Mnemonic::INC_Reg(Register::BX),
0x44 => Mnemonic::INC_Reg(Register::SP),
0x45 => Mnemonic::INC_Reg(Register::BP),
0x46 => Mnemonic::INC_Reg(Register::SI),
0x47 => Mnemonic::INC_Reg(Register::DI),
0x48 => Mnemonic::DEC_Reg(Register::AX),
0x49 => Mnemonic::DEC_Reg(Register::CX),
0x4A => Mnemonic::DEC_Reg(Register::DX),
0x4B => Mnemonic::DEC_Reg(Register::BX),
0x4C => Mnemonic::DEC_Reg(Register::SP),
0x4D => Mnemonic::DEC_Reg(Register::BP),
0x4E => Mnemonic::DEC_Reg(Register::SI),
0x4F => Mnemonic::DEC_Reg(Register::DI),
0x50 => Mnemonic::PUSH_R(Register::AX),
0x51 => Mnemonic::PUSH_R(Register::CX),
0x52 => Mnemonic::PUSH_R(Register::DX),
0x53 => Mnemonic::PUSH_R(Register::BX),
0x54 => Mnemonic::PUSH_R(Register::SP),
0x55 => Mnemonic::PUSH_R(Register::BP),
0x56 => Mnemonic::PUSH_R(Register::SI),
0x57 => Mnemonic::PUSH_R(Register::DI),
0x58 => Mnemonic::POP_R(Register::AX),
0x59 => Mnemonic::POP_R(Register::CX),
0x5A => Mnemonic::POP_R(Register::DX),
0x5B => Mnemonic::POP_R(Register::BX),
0x5C => Mnemonic::POP_R(Register::SP),
0x5D => Mnemonic::POP_R(Register::BP),
0x5E => Mnemonic::POP_R(Register::SI),
0x5F => Mnemonic::POP_R(Register::DI),
0x60..=0x6F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x70 => Mnemonic::JO(self.parse_j_byte()?),
0x71 => Mnemonic::JNO(self.parse_j_byte()?),
0x72 => Mnemonic::JB(self.parse_j_byte()?),
0x73 => Mnemonic::JNB(self.parse_j_byte()?),
0x74 => Mnemonic::JZ(self.parse_j_byte()?),
0x75 => Mnemonic::JNZ(self.parse_j_byte()?),
0x76 => Mnemonic::JBE(self.parse_j_byte()?),
0x77 => Mnemonic::JA(self.parse_j_byte()?),
0x78 => Mnemonic::JS(self.parse_j_byte()?),
0x79 => Mnemonic::JNS(self.parse_j_byte()?),
0x7A => Mnemonic::JPE(self.parse_j_byte()?),
0x7B => Mnemonic::JPO(self.parse_j_byte()?),
0x7C => Mnemonic::JL(self.parse_j_byte()?),
0x7D => Mnemonic::JGE(self.parse_j_byte()?),
0x7E => Mnemonic::JLE(self.parse_j_byte()?),
0x7F => Mnemonic::JG(self.parse_j_byte()?),
// Group 1
0x80 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x81 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_word()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))?
}
0x82 => {
// same as 0x80
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x83 => {
// byte extended version
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x84 => modrm_8b_register!(self, TEST),
0x85 => modrm_16b_register!(self, TEST),
0x86 => modrm_8b_register!(self, XCHG),
0x87 => modrm_16b_register!(self, XCHG),
0x88 => modrm_8b_register!(self, MOV_FromReg),
0x89 => modrm_16b_register!(self, MOV_FromReg),
0x8A => modrm_8b_register!(self, MOV_ToReg),
0x8B => modrm_16b_register!(self, MOV_ToReg),
0x8C => modrm_sregister!(self, MOV_FromSReg),
0x8E => modrm_sregister!(self, MOV_ToSReg),
0x8D => modrm_16b_register!(self, LEA),
0x8F => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let mem = match target {
ModRmTarget::Memory(idx) => idx,
_ => {
return Err(DisasmError::IllegalOperand(
"POP (memory) instruction given a register to pop into".into(),
));
}
};
Mnemonic::POP_M(mem)
}
0x90 => Mnemonic::NOP(),
0x91 => Mnemonic::XCHG_AX(Register::CX),
0x92 => Mnemonic::XCHG_AX(Register::DX),
0x93 => Mnemonic::XCHG_AX(Register::BX),
0x94 => Mnemonic::XCHG_AX(Register::SP),
0x95 => Mnemonic::XCHG_AX(Register::BP),
0x96 => Mnemonic::XCHG_AX(Register::SI),
0x97 => Mnemonic::XCHG_AX(Register::DI),
0x98 => Mnemonic::CBW,
0x99 => Mnemonic::CWD,
0x9A => Mnemonic::CALL_p(self.parse_ptr()?),
0x9B => Mnemonic::WAIT,
0x9C => Mnemonic::PUSHF,
0x9D => Mnemonic::POPF,
0x9E => Mnemonic::SAHF,
0x9F => Mnemonic::LAHF,
0xA0 => Mnemonic::MOV_AL0b(self.parse_byte()?),
0xA1 => Mnemonic::MOV_AX0v(self.parse_word()?),
0xA2 => Mnemonic::MOV_0bAL(self.parse_byte()?),
0xA3 => Mnemonic::MOV_0vAX(self.parse_word()?),
0xA4 => Mnemonic::MOVSB,
0xA5 => Mnemonic::MOVSW,
0xA6 => Mnemonic::CMPSB,
0xA7 => Mnemonic::CMPSW,
0xA8 => Mnemonic::TEST_ALIb(self.parse_byte()?),
0xA9 => Mnemonic::TEST_AXIv(self.parse_word()?),
0xAA => Mnemonic::STOSB,
0xAB => Mnemonic::STOSW,
0xAC => Mnemonic::LODSB,
0xAD => Mnemonic::LODSW,
0xAE => Mnemonic::SCASB,
0xAF => Mnemonic::SCASW,
0xB0 => Mnemonic::MOV_ALIb(self.parse_byte()?),
0xB1 => Mnemonic::MOV_CLIb(self.parse_byte()?),
0xB2 => Mnemonic::MOV_DLIb(self.parse_byte()?),
0xB3 => Mnemonic::MOV_BLIb(self.parse_byte()?),
0xB4 => Mnemonic::MOV_AHIb(self.parse_byte()?),
0xB5 => Mnemonic::MOV_CHIb(self.parse_byte()?),
0xB6 => Mnemonic::MOV_DHIb(self.parse_byte()?),
0xB7 => Mnemonic::MOV_BHIb(self.parse_byte()?),
0xB8 => Mnemonic::MOV_AXIv(self.parse_word()?),
0xB9 => Mnemonic::MOV_CXIv(self.parse_word()?),
0xBA => Mnemonic::MOV_DXIv(self.parse_word()?),
0xBB => Mnemonic::MOV_BXIv(self.parse_word()?),
0xBC => Mnemonic::MOV_SPIv(self.parse_word()?),
0xBD => Mnemonic::MOV_BPIv(self.parse_word()?),
0xBE => Mnemonic::MOV_SIIv(self.parse_word()?),
0xBF => Mnemonic::MOV_DIIv(self.parse_word()?),
0xC0..=0xC1 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xC2 => Mnemonic::RET_Iw(self.parse_word()?),
0xC3 => Mnemonic::RET,
0xC4 => {
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
let ptr = Pointer16::try_from(target)?;
Mnemonic::LES(reg, ptr)
}
0xC5 => {
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
let ptr = Pointer16::try_from(target)?;
Mnemonic::LDS(reg, ptr)
}
0xC6 => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Mnemonic::MOV_Ib(target, self.parse_byte()?)
}
0xC7 => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Mnemonic::MOV_Iv(target, self.parse_word()?)
}
0xC8..=0xC9 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xCA => Mnemonic::RETF_Iw(self.parse_word()?),
0xCB => Mnemonic::RETF,
0xCC => Mnemonic::INT(3),
0xCD => Mnemonic::INT(self.parse_byte()?),
0xCE => Mnemonic::INTO,
0xCF => Mnemonic::IRET,
// Group 2
0xD0 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Self::modrm_reg_to_grp2_1(reg, target)?
}
0xD1 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Self::modrm_reg_to_grp2_1(reg, target)?
}
0xD2 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Self::modrm_reg_to_grp2_cl(reg, target)?
}
0xD3 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Self::modrm_reg_to_grp2_cl(reg, target)?
}
0xD4 => Mnemonic::AAM(self.parse_byte()?),
0xD5 => Mnemonic::AAD(self.parse_byte()?),
0xD6 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xD7 => Mnemonic::XLAT,
0xD8..=0xDF => return Err(DisasmError::OpcodeUndefined(opcode)),
0xE0 => Mnemonic::LOOPNZ(self.parse_j_byte()?),
0xE1 => Mnemonic::LOOPZ(self.parse_j_byte()?),
0xE2 => Mnemonic::LOOP(self.parse_j_byte()?),
0xE3 => Mnemonic::JCXZ(self.parse_j_byte()?),
0xE4 => Mnemonic::IN_AL(self.parse_byte()?),
0xE5 => Mnemonic::IN_AX(self.parse_byte()?),
0xE6 => Mnemonic::OUT_AL(self.parse_byte()?),
0xE7 => Mnemonic::OUT_AX(self.parse_byte()?),
0xE8 => Mnemonic::CALL_v(self.parse_j_word()?),
0xE9 => Mnemonic::JMP_v(self.parse_j_word()?),
0xEA => Mnemonic::JMP_p(self.parse_ptr()?),
0xEB => Mnemonic::JMP_b(self.parse_j_byte()?),
0xEC => Mnemonic::IN_ALDX,
0xED => Mnemonic::IN_AXDX,
0xEE => Mnemonic::OUT_ALDX,
0xEF => Mnemonic::OUT_AXDX,
0xF0 => Mnemonic::LOCK,
0xF1 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xF2 => Mnemonic::REPNZ,
0xF3 => Mnemonic::REPZ,
0xF4 => Mnemonic::HLT,
0xF5 => Mnemonic::CMC,
// Group 3a
0xF6 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Byte)?
}
// Group 3b
0xF7 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Word)?
}
0xF8 => Mnemonic::CLC,
0xF9 => Mnemonic::STC,
0xFA => Mnemonic::CLI,
0xFB => Mnemonic::STI,
0xFC => Mnemonic::CLD,
0xFD => Mnemonic::STD,
// Group 4
0xFE => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
match reg {
0b0 => Mnemonic::INC_Mod(target),
0b1 => Mnemonic::DEC_Mod(target),
_ => return Err(DisasmError::IllegalGroupMnemonic(4, reg)),
}
}
// Group 5
0xFF => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
match reg {
0b000 => Mnemonic::INC_Mod(target),
0b001 => Mnemonic::DEC_Mod(target),
0b010 => Mnemonic::CALL_Mod(target),
0b011 => Mnemonic::CALL_Mp(Pointer16::try_from(target)?),
0b100 => Mnemonic::JMP_Mod(target),
0b101 => Mnemonic::JMP_Mp(Pointer16::try_from(target)?),
0b110 => Mnemonic::PUSH_Mod(target),
// 0b111 => unused
_ => return Err(DisasmError::IllegalGroupMnemonic(5, reg)),
}
}
};
// Save parsed instruction
log::debug!("{}", self.instruction);
self.instructions.push(self.instruction.clone());
// Advance offset to hover the next potential opcode // Advance offset to hover the next potential opcode
self.offset += 1; self.offset += 1;
@@ -910,6 +493,418 @@ impl Disassembler {
Ok(()) Ok(())
} }
/// Decode an instruction by matching byte signature to their mnemonics and
/// depending on the instruction, parsing some operands afterwards.
/// All parsing is done in capsulated functions, here everything just
/// gets consolodated.
pub fn decode_instruction(&mut self) -> Result<(), DisasmError> {
// reset mutable current instruction
self.instruction = Instruction::new();
self.instruction.addr = self.offset;
// fetch next opcode
let opcode = self.aout.text[self.offset];
log::debug!("Parsing next opcode with opcode: {opcode:#04x}");
// additional raw bytes will be pushed by parse functions
self.instruction.raw.push(opcode);
self.instruction.mnemonic = match opcode {
0x00 => modrm_8b_register!(self, ADD_FromReg),
0x01 => modrm_16b_register!(self, ADD_FromReg),
0x02 => modrm_8b_register!(self, ADD_ToReg),
0x03 => modrm_16b_register!(self, ADD_ToReg),
0x04 => Mnemonic::ADD_ALIb(self.parse_byte()?),
0x05 => Mnemonic::ADD_AXIv(self.parse_word()?),
0x06 => Mnemonic::PUSH_S(SegmentRegister::ES),
0x07 => Mnemonic::POP_S(SegmentRegister::ES),
0x08 => modrm_8b_register!(self, OR_FromReg),
0x09 => modrm_16b_register!(self, OR_FromReg),
0x0A => modrm_8b_register!(self, OR_ToReg),
0x0B => modrm_16b_register!(self, OR_ToReg),
0x0C => Mnemonic::OR_ALIb(self.parse_byte()?),
0x0D => Mnemonic::OR_AXIv(self.parse_word()?),
0x0E => Mnemonic::PUSH_S(SegmentRegister::CS),
0x0F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x10 => modrm_8b_register!(self, ADC_FromReg),
0x11 => modrm_16b_register!(self, ADC_FromReg),
0x12 => modrm_8b_register!(self, ADC_ToReg),
0x13 => modrm_16b_register!(self, ADC_ToReg),
0x14 => Mnemonic::ADC_ALIb(self.parse_byte()?),
0x15 => Mnemonic::ADC_AXIv(self.parse_word()?),
0x16 => Mnemonic::PUSH_S(SegmentRegister::SS),
0x17 => Mnemonic::POP_S(SegmentRegister::SS),
0x18 => modrm_8b_register!(self, SBB_FromReg),
0x19 => modrm_16b_register!(self, SBB_FromReg),
0x1A => modrm_8b_register!(self, SBB_ToReg),
0x1B => modrm_16b_register!(self, SBB_ToReg),
0x1C => Mnemonic::SBB_ALIb(self.parse_byte()?),
0x1D => Mnemonic::SBB_AXIv(self.parse_word()?),
0x1E => Mnemonic::PUSH_S(SegmentRegister::DS),
0x1F => Mnemonic::POP_S(SegmentRegister::DS),
0x20 => modrm_8b_register!(self, AND_FromReg),
0x21 => modrm_16b_register!(self, AND_FromReg),
0x22 => modrm_8b_register!(self, AND_ToReg),
0x23 => modrm_16b_register!(self, AND_ToReg),
0x24 => Mnemonic::AND_ALIb(self.parse_byte()?),
0x25 => Mnemonic::AND_AXIv(self.parse_word()?),
0x26 => Mnemonic::OVERRIDE(SegmentRegister::ES),
0x27 => Mnemonic::DAA,
0x28 => modrm_8b_register!(self, SUB_FromReg),
0x29 => modrm_16b_register!(self, SUB_FromReg),
0x2A => modrm_8b_register!(self, SUB_ToReg),
0x2B => modrm_16b_register!(self, SUB_ToReg),
0x2C => Mnemonic::SUB_ALIb(self.parse_byte()?),
0x2D => Mnemonic::SUB_AXIv(self.parse_word()?),
0x2E => Mnemonic::OVERRIDE(SegmentRegister::CS),
0x2F => Mnemonic::DAS,
0x30 => modrm_8b_register!(self, XOR_FromReg),
0x31 => modrm_16b_register!(self, XOR_FromReg),
0x32 => modrm_8b_register!(self, XOR_ToReg),
0x33 => modrm_16b_register!(self, XOR_ToReg),
0x34 => Mnemonic::XOR_ALIb(self.parse_byte()?),
0x35 => Mnemonic::XOR_AXIv(self.parse_word()?),
0x36 => Mnemonic::OVERRIDE(SegmentRegister::SS),
0x37 => Mnemonic::AAA,
0x38 => modrm_8b_register!(self, CMP_FromReg),
0x39 => modrm_16b_register!(self, CMP_FromReg),
0x3A => modrm_8b_register!(self, CMP_ToReg),
0x3B => modrm_16b_register!(self, CMP_ToReg),
0x3C => Mnemonic::CMP_ALIb(self.parse_byte()?),
0x3D => Mnemonic::CMP_AXIv(self.parse_word()?),
0x3E => Mnemonic::OVERRIDE(SegmentRegister::DS),
0x3F => Mnemonic::AAS,
0x40 => Mnemonic::INC_Reg(Register::AX),
0x41 => Mnemonic::INC_Reg(Register::CX),
0x42 => Mnemonic::INC_Reg(Register::DX),
0x43 => Mnemonic::INC_Reg(Register::BX),
0x44 => Mnemonic::INC_Reg(Register::SP),
0x45 => Mnemonic::INC_Reg(Register::BP),
0x46 => Mnemonic::INC_Reg(Register::SI),
0x47 => Mnemonic::INC_Reg(Register::DI),
0x48 => Mnemonic::DEC_Reg(Register::AX),
0x49 => Mnemonic::DEC_Reg(Register::CX),
0x4A => Mnemonic::DEC_Reg(Register::DX),
0x4B => Mnemonic::DEC_Reg(Register::BX),
0x4C => Mnemonic::DEC_Reg(Register::SP),
0x4D => Mnemonic::DEC_Reg(Register::BP),
0x4E => Mnemonic::DEC_Reg(Register::SI),
0x4F => Mnemonic::DEC_Reg(Register::DI),
0x50 => Mnemonic::PUSH_R(Register::AX),
0x51 => Mnemonic::PUSH_R(Register::CX),
0x52 => Mnemonic::PUSH_R(Register::DX),
0x53 => Mnemonic::PUSH_R(Register::BX),
0x54 => Mnemonic::PUSH_R(Register::SP),
0x55 => Mnemonic::PUSH_R(Register::BP),
0x56 => Mnemonic::PUSH_R(Register::SI),
0x57 => Mnemonic::PUSH_R(Register::DI),
0x58 => Mnemonic::POP_R(Register::AX),
0x59 => Mnemonic::POP_R(Register::CX),
0x5A => Mnemonic::POP_R(Register::DX),
0x5B => Mnemonic::POP_R(Register::BX),
0x5C => Mnemonic::POP_R(Register::SP),
0x5D => Mnemonic::POP_R(Register::BP),
0x5E => Mnemonic::POP_R(Register::SI),
0x5F => Mnemonic::POP_R(Register::DI),
0x60..=0x6F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x70 => Mnemonic::JO(self.parse_j_byte()?),
0x71 => Mnemonic::JNO(self.parse_j_byte()?),
0x72 => Mnemonic::JB(self.parse_j_byte()?),
0x73 => Mnemonic::JNB(self.parse_j_byte()?),
0x74 => Mnemonic::JZ(self.parse_j_byte()?),
0x75 => Mnemonic::JNZ(self.parse_j_byte()?),
0x76 => Mnemonic::JBE(self.parse_j_byte()?),
0x77 => Mnemonic::JA(self.parse_j_byte()?),
0x78 => Mnemonic::JS(self.parse_j_byte()?),
0x79 => Mnemonic::JNS(self.parse_j_byte()?),
0x7A => Mnemonic::JPE(self.parse_j_byte()?),
0x7B => Mnemonic::JPO(self.parse_j_byte()?),
0x7C => Mnemonic::JL(self.parse_j_byte()?),
0x7D => Mnemonic::JGE(self.parse_j_byte()?),
0x7E => Mnemonic::JLE(self.parse_j_byte()?),
0x7F => Mnemonic::JG(self.parse_j_byte()?),
// Group 1
0x80 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x81 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_word()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))?
}
0x82 => {
// same as 0x80
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x83 => {
// byte extended version
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
}
0x84 => modrm_8b_register!(self, TEST),
0x85 => modrm_16b_register!(self, TEST),
0x86 => modrm_8b_register!(self, XCHG),
0x87 => modrm_16b_register!(self, XCHG),
0x88 => modrm_8b_register!(self, MOV_FromReg),
0x89 => modrm_16b_register!(self, MOV_FromReg),
0x8A => modrm_8b_register!(self, MOV_ToReg),
0x8B => modrm_16b_register!(self, MOV_ToReg),
0x8C => modrm_sregister!(self, MOV_FromSReg),
0x8E => modrm_sregister!(self, MOV_ToSReg),
0x8D => modrm_16b_register!(self, LEA),
0x8F => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let mem = match target {
ModRmTarget::Memory(idx) => idx,
_ => {
return Err(DisasmError::IllegalOperand(
"POP (memory) instruction given a register to pop into".into(),
));
}
};
Mnemonic::POP_M(mem)
}
0x90 => Mnemonic::NOP(),
0x91 => Mnemonic::XCHG_AX(Register::CX),
0x92 => Mnemonic::XCHG_AX(Register::DX),
0x93 => Mnemonic::XCHG_AX(Register::BX),
0x94 => Mnemonic::XCHG_AX(Register::SP),
0x95 => Mnemonic::XCHG_AX(Register::BP),
0x96 => Mnemonic::XCHG_AX(Register::SI),
0x97 => Mnemonic::XCHG_AX(Register::DI),
0x98 => Mnemonic::CBW,
0x99 => Mnemonic::CWD,
0x9A => Mnemonic::CALL_p(self.parse_ptr()?),
0x9B => Mnemonic::WAIT,
0x9C => Mnemonic::PUSHF,
0x9D => Mnemonic::POPF,
0x9E => Mnemonic::SAHF,
0x9F => Mnemonic::LAHF,
0xA0 => Mnemonic::MOV_AL0b(self.parse_byte()?),
0xA1 => Mnemonic::MOV_AX0v(self.parse_word()?),
0xA2 => Mnemonic::MOV_0bAL(self.parse_byte()?),
0xA3 => Mnemonic::MOV_0vAX(self.parse_word()?),
0xA4 => Mnemonic::MOVSB,
0xA5 => Mnemonic::MOVSW,
0xA6 => Mnemonic::CMPSB,
0xA7 => Mnemonic::CMPSW,
0xA8 => Mnemonic::TEST_ALIb(self.parse_byte()?),
0xA9 => Mnemonic::TEST_AXIv(self.parse_word()?),
0xAA => Mnemonic::STOSB,
0xAB => Mnemonic::STOSW,
0xAC => Mnemonic::LODSB,
0xAD => Mnemonic::LODSW,
0xAE => Mnemonic::SCASB,
0xAF => Mnemonic::SCASW,
0xB0 => Mnemonic::MOV_ALIb(self.parse_byte()?),
0xB1 => Mnemonic::MOV_CLIb(self.parse_byte()?),
0xB2 => Mnemonic::MOV_DLIb(self.parse_byte()?),
0xB3 => Mnemonic::MOV_BLIb(self.parse_byte()?),
0xB4 => Mnemonic::MOV_AHIb(self.parse_byte()?),
0xB5 => Mnemonic::MOV_CHIb(self.parse_byte()?),
0xB6 => Mnemonic::MOV_DHIb(self.parse_byte()?),
0xB7 => Mnemonic::MOV_BHIb(self.parse_byte()?),
0xB8 => Mnemonic::MOV_AXIv(self.parse_word()?),
0xB9 => Mnemonic::MOV_CXIv(self.parse_word()?),
0xBA => Mnemonic::MOV_DXIv(self.parse_word()?),
0xBB => Mnemonic::MOV_BXIv(self.parse_word()?),
0xBC => Mnemonic::MOV_SPIv(self.parse_word()?),
0xBD => Mnemonic::MOV_BPIv(self.parse_word()?),
0xBE => Mnemonic::MOV_SIIv(self.parse_word()?),
0xBF => Mnemonic::MOV_DIIv(self.parse_word()?),
0xC0..=0xC1 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xC2 => Mnemonic::RET_Iw(self.parse_word()?),
0xC3 => Mnemonic::RET,
0xC4 => {
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
let ptr = Pointer16::try_from(target)?;
Mnemonic::LES(reg, ptr)
}
0xC5 => {
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
let ptr = Pointer16::try_from(target)?;
Mnemonic::LDS(reg, ptr)
}
0xC6 => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Mnemonic::MOV_Ib(target, self.parse_byte()?)
}
0xC7 => {
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Mnemonic::MOV_Iv(target, self.parse_word()?)
}
0xC8..=0xC9 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xCA => Mnemonic::RETF_Iw(self.parse_word()?),
0xCB => Mnemonic::RETF,
0xCC => Mnemonic::INT(3),
0xCD => Mnemonic::INT(self.parse_byte()?),
0xCE => Mnemonic::INTO,
0xCF => Mnemonic::IRET,
// Group 2
0xD0 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Self::modrm_reg_to_grp2_1(reg, target)?
}
0xD1 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Self::modrm_reg_to_grp2_1(reg, target)?
}
0xD2 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
Self::modrm_reg_to_grp2_cl(reg, target)?
}
0xD3 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
Self::modrm_reg_to_grp2_cl(reg, target)?
}
0xD4 => Mnemonic::AAM(self.parse_byte()?),
0xD5 => Mnemonic::AAD(self.parse_byte()?),
0xD6 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xD7 => Mnemonic::XLAT,
0xD8..=0xDF => return Err(DisasmError::OpcodeUndefined(opcode)),
0xE0 => Mnemonic::LOOPNZ(self.parse_j_byte()?),
0xE1 => Mnemonic::LOOPZ(self.parse_j_byte()?),
0xE2 => Mnemonic::LOOP(self.parse_j_byte()?),
0xE3 => Mnemonic::JCXZ(self.parse_j_byte()?),
0xE4 => Mnemonic::IN_AL(self.parse_byte()?),
0xE5 => Mnemonic::IN_AX(self.parse_byte()?),
0xE6 => Mnemonic::OUT_AL(self.parse_byte()?),
0xE7 => Mnemonic::OUT_AX(self.parse_byte()?),
0xE8 => Mnemonic::CALL_v(self.parse_j_word()?),
0xE9 => Mnemonic::JMP_v(self.parse_j_word()?),
0xEA => Mnemonic::JMP_p(self.parse_ptr()?),
0xEB => Mnemonic::JMP_b(self.parse_j_byte()?),
0xEC => Mnemonic::IN_ALDX,
0xED => Mnemonic::IN_AXDX,
0xEE => Mnemonic::OUT_ALDX,
0xEF => Mnemonic::OUT_AXDX,
0xF0 => Mnemonic::LOCK,
0xF1 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xF2 => Mnemonic::REPNZ,
0xF3 => Mnemonic::REPZ,
0xF4 => Mnemonic::HLT,
0xF5 => Mnemonic::CMC,
// Group 3a
0xF6 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Byte)?
}
// Group 3b
0xF7 => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Word)?
}
0xF8 => Mnemonic::CLC,
0xF9 => Mnemonic::STC,
0xFA => Mnemonic::CLI,
0xFB => Mnemonic::STI,
0xFC => Mnemonic::CLD,
0xFD => Mnemonic::STD,
// Group 4
0xFE => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
match reg {
0b0 => Mnemonic::INC_Mod(target),
0b1 => Mnemonic::DEC_Mod(target),
_ => return Err(DisasmError::IllegalGroupMnemonic(4, reg)),
}
}
// Group 5
0xFF => {
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
match reg {
0b000 => Mnemonic::INC_Mod(target),
0b001 => Mnemonic::DEC_Mod(target),
0b010 => Mnemonic::CALL_Mod(target),
0b011 => Mnemonic::CALL_Mp(Pointer16::try_from(target)?),
0b100 => Mnemonic::JMP_Mod(target),
0b101 => Mnemonic::JMP_Mp(Pointer16::try_from(target)?),
0b110 => Mnemonic::PUSH_Mod(target),
// 0b111 => unused
_ => return Err(DisasmError::IllegalGroupMnemonic(5, reg)),
}
}
};
// Save parsed instruction
log::debug!("Parsed {}", self.instruction);
self.instructions.push(self.instruction.clone());
Ok(())
}
} }
// #[cfg(test)] // #[cfg(test)]

View File

@@ -11,9 +11,9 @@ use core::fmt;
/// contains the `Mnemonic` that will be executed, alongside its starting offset /// contains the `Mnemonic` that will be executed, alongside its starting offset
/// and the raw parsed bytes /// and the raw parsed bytes
pub struct Instruction { pub struct Instruction {
pub addr: usize, // location of the instruction start pub addr: usize, // location of the instruction start
pub raw: Vec<u8>, // raw value of instruction pub raw: Vec<u8>, // raw value of instruction
pub opcode: Mnemonic, // actual instruction pub mnemonic: Mnemonic, // actual instruction
} }
impl Instruction { impl Instruction {
@@ -21,7 +21,7 @@ impl Instruction {
Instruction { Instruction {
addr: 0, addr: 0,
raw: Vec::new(), raw: Vec::new(),
opcode: Mnemonic::NOP(), mnemonic: Mnemonic::NOP(),
} }
} }
} }
@@ -41,7 +41,7 @@ impl fmt::Display for Instruction {
) )
.unwrap(); .unwrap();
write!(f, "\t{}", self.opcode) write!(f, "\t{}", self.mnemonic)
} }
} }

View File

@@ -2,11 +2,13 @@ use core::fmt;
use std::{fmt::Debug, process::exit}; use std::{fmt::Debug, process::exit};
use crate::{ use crate::{
Args,
aout::Aout,
disasm::Disassembler,
instructions::{Instruction, Mnemonic}, instructions::{Instruction, Mnemonic},
interpreter::{ interpreter::{
computer::{CarryUsage, RotationDirection}, computer::{CarryUsage, RotationDirection},
interrupt::Mess1, interrupt::Mess1,
register::SegmentRegister,
}, },
operands::{Byte, ImmediateOperand, ModRmTarget, Word}, operands::{Byte, ImmediateOperand, ModRmTarget, Word},
}; };
@@ -16,12 +18,9 @@ use super::{
interrupt::InterruptMessage, interrupt::InterruptMessage,
}; };
type InstructionPointer<'a> = std::slice::Iter<'a, Instruction>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum InterpreterError { pub enum InterpreterError {
InvalidSyscall(Byte), InvalidSyscall(Byte),
InstructionNotFound(Word),
MemoryOutOfBound(Word), MemoryOutOfBound(Word),
} }
@@ -31,9 +30,6 @@ impl fmt::Display for InterpreterError {
InterpreterError::InvalidSyscall(id) => { InterpreterError::InvalidSyscall(id) => {
write!(f, "The syscall with ID {} is unknown", id) write!(f, "The syscall with ID {} is unknown", id)
} }
InterpreterError::InstructionNotFound(addr) => {
write!(f, "IP({addr}) points at invalid instruction")
}
InterpreterError::MemoryOutOfBound(addr) => { InterpreterError::MemoryOutOfBound(addr) => {
write!( write!(
f, f,
@@ -47,30 +43,47 @@ impl fmt::Display for InterpreterError {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Interpreter { pub struct Interpreter {
computer: Computer, computer: Computer,
instructions: Vec<Instruction>, text: Vec<u8>,
ip: usize,
disassembler: Disassembler,
} }
impl Interpreter { impl Interpreter {
pub fn new(instructions: Vec<Instruction>, data: Vec<Byte>) -> Self { pub fn new(args: &Args) -> Self {
let aout = Aout::new_from_args(args);
Self { Self {
computer: Computer::new(data), computer: Computer::new(aout.data),
instructions, text: aout.text,
ip: 0,
disassembler: Disassembler::new(args),
} }
} }
pub fn interpret(&mut self) -> Result<(), InterpreterError> { /// Sets instruction pointer in compliance with [`Register::CS`].
let mut ip = Self::find_instruction(&self.instructions, 0, &self.computer.sregs) pub fn set_ip(&mut self, ip: usize) {
.ok_or(InterpreterError::InstructionNotFound(0))?; self.ip = ip + (self.computer.sregs.cs * 16) as usize
}
/// Gets instruction pointer in compliance with [`Register::CS`].
pub fn get_ip(&self) -> usize {
self.ip + (self.computer.sregs.cs * 16) as usize
}
pub fn interpret(&mut self) -> Result<(), InterpreterError> {
while self.ip < self.text.len() {
self.disassembler.offset = self.ip;
// XXX remove unwrap
self.disassembler.decode_instruction().unwrap();
let current_instruction = self.disassembler.instruction.clone();
while let Some(cur_instr) = ip.next() {
log::info!( log::info!(
"{} IP({:04x})\t {:<32}", "{} IP({:04x})\t {:<32}",
self.computer, self.computer,
cur_instr.addr, current_instruction.addr,
cur_instr.opcode.to_string(), current_instruction.mnemonic.to_string(),
); );
match cur_instr.opcode { match current_instruction.mnemonic {
/* /*
* ADD * ADD
*/ */
@@ -381,7 +394,7 @@ impl Interpreter {
| Mnemonic::JMP_b(offset) | Mnemonic::JMP_b(offset)
| Mnemonic::JMP_v(offset) => { | Mnemonic::JMP_v(offset) => {
let flags = self.computer.flags.clone(); let flags = self.computer.flags.clone();
let flag = match cur_instr.opcode { let flag = match current_instruction.mnemonic {
Mnemonic::JO(_) => flags.of, Mnemonic::JO(_) => flags.of,
Mnemonic::JNO(_) => !flags.of, Mnemonic::JNO(_) => !flags.of,
Mnemonic::JB(_) => flags.cf, Mnemonic::JB(_) => flags.cf,
@@ -402,7 +415,8 @@ impl Interpreter {
_ => panic!("unreachable"), _ => panic!("unreachable"),
}; };
if flag { if flag {
Self::ip_jump(&self.instructions, &mut ip, &self.computer.sregs, offset); self.set_ip(offset);
continue;
} }
} }
@@ -411,66 +425,35 @@ impl Interpreter {
*/ */
Mnemonic::JMP_p(ptr) => { Mnemonic::JMP_p(ptr) => {
self.computer.sregs.cs = ptr.segment; self.computer.sregs.cs = ptr.segment;
Self::ip_jump( self.set_ip(ptr.offset.into());
&self.instructions, continue;
&mut ip,
&self.computer.sregs,
ptr.offset.into(),
);
} }
Mnemonic::JMP_Mp(ptr) => { Mnemonic::JMP_Mp(ptr) => {
Self::ip_jump( self.set_ip(ptr.word.into());
&self.instructions, continue;
&mut ip,
&self.computer.sregs,
ptr.word.into(),
);
} }
Mnemonic::JMP_Mod(target) => Self::ip_jump( Mnemonic::JMP_Mod(target) => self.set_ip(self.computer.read_modrm(target)?.into()),
&self.instructions,
&mut ip,
&self.computer.sregs,
self.computer.read_modrm(target)?.into(),
),
Mnemonic::CALL_p(ptr) => { Mnemonic::CALL_p(ptr) => {
if let Some(next_instr) = ip.next() { self.save_next_instruction_into_stack(&current_instruction)?;
self.computer.push_stack(next_instr.addr.into())?;
}
self.computer.sregs.cs = ptr.segment; self.computer.sregs.cs = ptr.segment;
Self::ip_jump( self.set_ip(ptr.offset.into());
&self.instructions, continue;
&mut ip,
&self.computer.sregs,
ptr.offset.into(),
);
} }
Mnemonic::CALL_v(offset) => { Mnemonic::CALL_v(offset) => {
if let Some(next_instr) = ip.next() { self.save_next_instruction_into_stack(&current_instruction)?;
self.computer.push_stack(next_instr.addr.into())?; self.set_ip(offset);
} continue;
Self::ip_jump(&self.instructions, &mut ip, &self.computer.sregs, offset);
} }
Mnemonic::CALL_Mod(target) => { Mnemonic::CALL_Mod(target) => {
if let Some(next_instr) = ip.next() { self.save_next_instruction_into_stack(&current_instruction)?;
self.computer.push_stack(next_instr.addr.into())?; self.set_ip(self.computer.read_modrm(target)?.into());
} continue;
Self::ip_jump(
&self.instructions,
&mut ip,
&self.computer.sregs,
self.computer.read_modrm(target)?.into(),
);
} }
Mnemonic::CALL_Mp(ptr) => { Mnemonic::CALL_Mp(ptr) => {
if let Some(next_instr) = ip.next() { self.save_next_instruction_into_stack(&current_instruction)?;
self.computer.push_stack(next_instr.addr.into())?; self.set_ip(ptr.word.into());
} continue;
Self::ip_jump(
&self.instructions,
&mut ip,
&self.computer.sregs,
ptr.word.into(),
);
} }
/* /*
@@ -601,13 +584,9 @@ impl Interpreter {
* RET * RET
*/ */
Mnemonic::RET => { Mnemonic::RET => {
let offset = self.computer.pop_stack()?; let return_addr = self.computer.pop_stack()?;
Self::ip_jump( self.set_ip(return_addr as usize);
&self.instructions, continue;
&mut ip,
&self.computer.sregs,
offset as usize,
);
} }
/* /*
@@ -771,6 +750,9 @@ impl Interpreter {
} }
_ => log::info!("no action done"), _ => log::info!("no action done"),
} }
// Go to next instruction
self.ip += current_instruction.raw.len();
} }
Ok(()) Ok(())
@@ -824,31 +806,15 @@ impl Interpreter {
Ok(()) Ok(())
} }
/// Find the starting addr of an instruction in the list of all parsed /// Used for CALL and JUMP instructions.
/// instructions and return the iterator to that matching instruction, to fn save_next_instruction_into_stack(
/// allow for further traversal from that point on. &mut self,
/// I bet, that this is not really fast, but I could'nt come up with a current_instruction: &Instruction,
/// better idea so far. ) -> Result<(), InterpreterError> {
fn find_instruction<'a>( let instruction_size_in_bytes = current_instruction.raw.len();
items: &'a Vec<Instruction>, self.computer
ip_addr: usize, .push_stack((self.get_ip() + instruction_size_in_bytes).into())?;
sregs: &SegmentRegister,
) -> Option<InstructionPointer<'a>> {
items
.iter()
.position(|instruction| instruction.addr == ip_addr + (sregs.cs * 16) as usize)
.map(|index| items[index..].iter())
}
/// Jump [`InstructionPointer`] `ip` to an `offset`. Ok(())
fn ip_jump<'a>(
instructions: &'a Vec<Instruction>,
ip: &mut InstructionPointer<'a>,
sregs: &SegmentRegister,
offset: usize,
) {
if let Some(next_instr) = Self::find_instruction(&instructions, offset, sregs) {
*ip = next_instr;
}
} }
} }

View File

@@ -69,15 +69,8 @@ fn main() {
} }
} }
Command::Interpret => { Command::Interpret => {
let mut disasm = Disassembler::new(&args); let mut interpreter = Interpreter::new(&args);
let instructions = disasm.disassemble(args.dump); interpreter.interpret().unwrap();
match instructions {
Ok(instrs) => {
let mut interpreter = Interpreter::new(instrs, disasm.aout.data);
interpreter.interpret().unwrap();
}
_ => {}
}
} }
} }
} }