chore: replace all panic's with proper error propagation

This commit is contained in:
2025-05-25 15:45:09 +09:00
parent 73b1a99cbd
commit 74e936ab76
4 changed files with 278 additions and 243 deletions

View File

@@ -2,7 +2,7 @@
use crate::aout::Aout; use crate::aout::Aout;
use crate::operands::{ use crate::operands::{
DWord, Displacement, IByte, IWord, MemoryIndex, ModRmTarget, Operand, Pointer, Byte, Displacement, IByte, IWord, MemoryIndex, ModRmTarget, Operand, Pointer, Word,
}; };
use crate::register::{Register, RegisterId, SegmentRegister}; use crate::register::{Register, RegisterId, SegmentRegister};
use crate::{ use crate::{
@@ -19,7 +19,11 @@ pub enum DisasmError {
NoFile(Option<String>), NoFile(Option<String>),
IoError(std::io::Error), IoError(std::io::Error),
OpcodeUndefined(u8), OpcodeUndefined(u8),
IndexOutOfBounds(usize), IllegalGroupMnemonic(u8, u8),
IllegalModRMByteMode(u8),
IllegalModRMByteIndex(u8),
ReadBeyondTextSection(Disassembler),
UnknownRegister(usize),
} }
impl From<std::io::Error> for DisasmError { impl From<std::io::Error> for DisasmError {
@@ -35,10 +39,33 @@ impl fmt::Display for DisasmError {
DisasmError::IoError(msg) => write!(f, "{}", msg), DisasmError::IoError(msg) => write!(f, "{}", msg),
DisasmError::OpcodeUndefined(opcode) => write!( DisasmError::OpcodeUndefined(opcode) => write!(
f, f,
"Instruction '{:#x} is considered undefined by the Spec", "Error (Undefined Opcode). '{:#x} is considered undefined by the Spec",
opcode opcode
), ),
DisasmError::IndexOutOfBounds(msg) => write!(f, "Out of bounds read at {}", msg), DisasmError::IllegalGroupMnemonic(group, mnemonic) => write!(
f,
"Error (Illegal group mnemonic). While parsing the ModRM reg field for groups, the following bit-combination for GRP{group} is unknown: {}",
mnemonic
),
DisasmError::IllegalModRMByteMode(modrm) => write!(
f,
"Error (Illegal modrm byte). While deconstructing a ModRM byte, the following mode is unknown: {}",
modrm
),
DisasmError::IllegalModRMByteIndex(modrm) => write!(
f,
"Error (Illegal modrm byte). While deconstructing a ModRM byte, the following index is unknown: {}",
modrm
),
DisasmError::ReadBeyondTextSection(disasm) => write!(
f,
"Error (Out of bounds access). Disassembler state: {:?}",
disasm
),
DisasmError::UnknownRegister(id) => write!(
f,
"Error (Unknown register). The register with ID {id} is unknown",
),
} }
} }
} }
@@ -68,7 +95,7 @@ fn path_to_buf(args: &Args) -> Result<Vec<u8>, DisasmError> {
Ok(buf) Ok(buf)
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Disassembler { pub struct Disassembler {
pub offset: usize, // the current offset in the disasm process pub offset: usize, // the current offset in the disasm process
pub text: Vec<u8>, // the aout binary pub text: Vec<u8>, // the aout binary
@@ -86,47 +113,48 @@ impl Disassembler {
/// Parse a single byte of binary, return it and advance the offset. /// Parse a single byte of binary, return it and advance the offset.
/// Returns the read byte. /// Returns the read byte.
pub fn parse_byte(&mut self) -> u8 { pub fn parse_byte(&mut self) -> Result<Byte, DisasmError> {
log::debug!("Attempting to parse byte at {} ...", self.offset);
// advance to operand // advance to operand
self.offset += 1; self.offset += 1;
let byte = self.text[self.offset]; let byte = self
self.instruction.raw.push(byte); .text
byte .get(self.offset)
.ok_or(DisasmError::ReadBeyondTextSection(self.clone()))?;
self.instruction.raw.push(*byte);
Ok(*byte)
} }
/// Parse a single word of binary, return it and advance the offset. /// Parse a single word of binary.
/// Just a wrapper for parsing a byte twice.
/// Returns the read word. /// Returns the read word.
pub fn parse_word(&mut self) -> u16 { pub fn parse_word(&mut self) -> Result<Word, DisasmError> {
// advance to operand log::debug!("Attempting to parse word at {} ...", self.offset);
self.offset += 1; let byte1 = self.parse_byte()?;
// XXX: wrap in Result<> let byte2 = self.parse_byte()?;
let byte1 = self.text[self.offset];
let byte2 = self.text[self.offset + 1];
// jump onto last operand
self.offset += 1;
self.instruction.raw.push(byte1); self.instruction.raw.push(byte1);
self.instruction.raw.push(byte2); self.instruction.raw.push(byte2);
u16::from_le_bytes([byte1, byte2]) Ok(u16::from_le_bytes([byte1, byte2]))
} }
/// Parse a single byte of binary and advance the offset. /// Parse a single byte of binary and interpret as as signed.
/// The returned IByte contains a relative offset to be added to the address /// The isize contains a relative offset to be added to the address
/// of the subsequent instruction. /// of the subsequent instruction.
pub fn parse_j_byte(&mut self) -> isize { pub fn parse_j_byte(&mut self) -> Result<isize, DisasmError> {
// first interpret as 2-complement, then cast for addition // first interpret as 2-complement, then cast for addition
let byte = self.parse_byte() as IByte as isize; let byte = self.parse_byte()? as IByte as isize;
let next_addr = (self.offset + 1) as isize; let next_addr = (self.offset + 1) as isize;
byte + next_addr Ok(byte + next_addr)
} }
/// Parse a single byte of binary and advance the offset. /// Parse a single byte of binary and interpret as signed.
/// The returned IByte contains a relative offset to be added to the address /// The isize contains a relative offset to be added to the address
/// of the subsequent instruction. /// of the subsequent instruction.
pub fn parse_j_word(&mut self) -> isize { pub fn parse_j_word(&mut self) -> Result<isize, DisasmError> {
// first interpret as 2-complement, then cast for addition // first interpret as 2-complement, then cast for addition
let word = self.parse_word() as IWord as isize; let word = self.parse_word()? as IWord as isize;
let next_addr = (self.offset + 1) as isize; let next_addr = (self.offset + 1) as isize;
word + next_addr Ok(word + next_addr)
} }
/// Takes in a modrm byte and returns mod, reg and r/m. /// Takes in a modrm byte and returns mod, reg and r/m.
@@ -140,7 +168,10 @@ impl Disassembler {
/// Parse a single modrm byte, return the resulting MemoryIndex and advance the offset. /// Parse a single modrm byte, return the resulting MemoryIndex and advance the offset.
/// Returns the parsed modrm target and the source register /// Returns the parsed modrm target and the source register
pub fn parse_modrm_byte(&mut self, width: Operand) -> (ModRmTarget, RegisterId) { pub fn parse_modrm_byte(
&mut self,
register_width: Operand,
) -> Result<(ModRmTarget, RegisterId), DisasmError> {
// advance to operand // advance to operand
self.offset += 1; self.offset += 1;
let modrm = self.text[self.offset]; let modrm = self.text[self.offset];
@@ -161,39 +192,39 @@ impl Disassembler {
0b00 => { 0b00 => {
if rm == 0b110 { if rm == 0b110 {
log::debug!("Additional word during ModRM parsing was read with mod 0."); log::debug!("Additional word during ModRM parsing was read with mod 0.");
displacement = Some(Displacement::IWord(self.parse_word() as IWord)); displacement = Some(Displacement::IWord(self.parse_word()? as IWord));
return ( return Ok((
ModRmTarget::Memory(MemoryIndex { ModRmTarget::Memory(MemoryIndex {
base: None, base: None,
index: None, index: None,
displacement, displacement,
}), }),
reg, reg,
); ));
} else { } else {
displacement = None; displacement = None;
} }
} }
0b01 => { 0b01 => {
log::debug!("Additional byte during ModRM parsing was read."); log::debug!("Additional byte during ModRM parsing was read.");
displacement = Some(Displacement::IByte(self.parse_byte() as IByte)) displacement = Some(Displacement::IByte(self.parse_byte()? as IByte))
} }
0b10 => { 0b10 => {
log::debug!("Additional word during ModRM parsing was read."); log::debug!("Additional word during ModRM parsing was read.");
displacement = Some(Displacement::IWord(self.parse_word() as IWord)); displacement = Some(Displacement::IWord(self.parse_word()? as IWord));
} }
0b11 => { 0b11 => {
log::debug!("ModRM ({:#b}) to/from Register ({:#b})", rm, reg); log::debug!("ModRM ({:#b}) to/from Register ({:#b})", rm, reg);
// XXX: find a nicer way instead of using Byte(0) and Word(0) // XXX: find a nicer way instead of using Byte(0) and Word(0)
let target = match width { let target = match register_width {
Operand::Byte(_) => ModRmTarget::Register(Register::by_id(Operand::Byte(rm))), Operand::Byte(_) => ModRmTarget::Register(Register::by_id(Operand::Byte(rm))?),
Operand::Word(_) => { Operand::Word(_) => {
ModRmTarget::Register(Register::by_id(Operand::Word(rm.into()))) ModRmTarget::Register(Register::by_id(Operand::Word(rm.into()))?)
} }
}; };
return (target, reg); return Ok((target, reg));
} }
_ => panic!("Invalid ModRM byte encountered"), _ => return Err(DisasmError::IllegalModRMByteMode(mode)),
}; };
let index = match rm { let index = match rm {
@@ -237,39 +268,43 @@ impl Disassembler {
index: None, index: None,
displacement, displacement,
}, },
_ => panic!("Invalid ModRM byte encountered"), _ => return Err(DisasmError::IllegalModRMByteIndex(rm)),
}; };
(ModRmTarget::Memory(index), reg) Ok((ModRmTarget::Memory(index), reg))
} }
/// Match the modrm reg bits to the GPR1 mnemonics. /// Match the modrm reg bits to the GPR1 mnemonics.
/// Group 1 always have an ModRM target (all modrm bits, without reg) as /// Group 1 always have an ModRM target (all modrm bits, without reg) as
/// first and an imm value as second operand (which has to be parsed before /// first and an imm value as second operand (which has to be parsed before
/// call to this function), but is available in both Byte and Word length. /// call to this function), but is available in both Byte and Word length.
pub fn modrm_reg_to_grp1(reg: u8, target: ModRmTarget, imm: Operand) -> Mnemonic { pub fn modrm_reg_to_grp1(
reg: u8,
target: ModRmTarget,
imm: Operand,
) -> Result<Mnemonic, DisasmError> {
match imm { match imm {
Operand::Byte(b) => match reg { Operand::Byte(b) => match reg {
0b000 => Mnemonic::ADD_Ib(target, b), 0b000 => Ok(Mnemonic::ADD_Ib(target, b)),
0b001 => Mnemonic::OR_Ib(target, b), 0b001 => Ok(Mnemonic::OR_Ib(target, b)),
0b010 => Mnemonic::ADC_Ib(target, b), 0b010 => Ok(Mnemonic::ADC_Ib(target, b)),
0b011 => Mnemonic::SBB_Ib(target, b), 0b011 => Ok(Mnemonic::SBB_Ib(target, b)),
0b100 => Mnemonic::AND_Ib(target, b), 0b100 => Ok(Mnemonic::AND_Ib(target, b)),
0b101 => Mnemonic::SUB_Ib(target, b), 0b101 => Ok(Mnemonic::SUB_Ib(target, b)),
0b110 => Mnemonic::XOR_Ib(target, b), 0b110 => Ok(Mnemonic::XOR_Ib(target, b)),
0b111 => Mnemonic::CMP_Ib(target, b), 0b111 => Ok(Mnemonic::CMP_Ib(target, b)),
_ => panic!("Illegal Group 1 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(1, reg)),
}, },
Operand::Word(w) => match reg { Operand::Word(w) => match reg {
0b000 => Mnemonic::ADD_Iv(target, w), 0b000 => Ok(Mnemonic::ADD_Iv(target, w)),
0b001 => Mnemonic::OR_Iv(target, w), 0b001 => Ok(Mnemonic::OR_Iv(target, w)),
0b010 => Mnemonic::ADC_Iv(target, w), 0b010 => Ok(Mnemonic::ADC_Iv(target, w)),
0b011 => Mnemonic::SBB_Iv(target, w), 0b011 => Ok(Mnemonic::SBB_Iv(target, w)),
0b100 => Mnemonic::AND_Iv(target, w), 0b100 => Ok(Mnemonic::AND_Iv(target, w)),
0b101 => Mnemonic::SUB_Iv(target, w), 0b101 => Ok(Mnemonic::SUB_Iv(target, w)),
0b110 => Mnemonic::XOR_Iv(target, w), 0b110 => Ok(Mnemonic::XOR_Iv(target, w)),
0b111 => Mnemonic::CMP_Iv(target, w), 0b111 => Ok(Mnemonic::CMP_Iv(target, w)),
_ => panic!("Illegal Group 1 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(1, reg)),
}, },
} }
} }
@@ -278,17 +313,17 @@ impl Disassembler {
/// Group 2 only has a single operand, the other one is either a constant /// Group 2 only has a single operand, the other one is either a constant
/// 1 (not present in the binary) or the CL register. /// 1 (not present in the binary) or the CL register.
/// This function assumes the operand to be 1 /// This function assumes the operand to be 1
pub fn modrm_reg_to_grp2_1(reg: u8, target: ModRmTarget) -> Mnemonic { pub fn modrm_reg_to_grp2_1(reg: u8, target: ModRmTarget) -> Result<Mnemonic, DisasmError> {
match reg { match reg {
0b000 => Mnemonic::ROL_b(target, 1), 0b000 => Ok(Mnemonic::ROL_b(target, 1)),
0b001 => Mnemonic::ROR_b(target, 1), 0b001 => Ok(Mnemonic::ROR_b(target, 1)),
0b010 => Mnemonic::RCL_b(target, 1), 0b010 => Ok(Mnemonic::RCL_b(target, 1)),
0b011 => Mnemonic::RCR_b(target, 1), 0b011 => Ok(Mnemonic::RCR_b(target, 1)),
0b100 => Mnemonic::SHL_b(target, 1), 0b100 => Ok(Mnemonic::SHL_b(target, 1)),
0b101 => Mnemonic::SHR_b(target, 1), 0b101 => Ok(Mnemonic::SHR_b(target, 1)),
0b110 => Mnemonic::SAR_b(target, 1), 0b110 => Ok(Mnemonic::SAR_b(target, 1)),
0b111 => Mnemonic::SAR_b(target, 1), 0b111 => Ok(Mnemonic::SAR_b(target, 1)),
_ => panic!("Illegal Group 2 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(2, reg)),
} }
} }
@@ -296,37 +331,42 @@ impl Disassembler {
/// Group 2 only has a single operand, the other one is either a constant /// Group 2 only has a single operand, the other one is either a constant
/// 1 (not present in the binary) or the CL register. /// 1 (not present in the binary) or the CL register.
/// This function assumes the operand to be CL register. /// This function assumes the operand to be CL register.
pub fn modrm_reg_to_grp2_cl(reg: u8, target: ModRmTarget) -> Mnemonic { pub fn modrm_reg_to_grp2_cl(reg: u8, target: ModRmTarget) -> Result<Mnemonic, DisasmError> {
match reg { match reg {
0b000 => Mnemonic::ROL_fromReg(target, Register::CL), 0b000 => Ok(Mnemonic::ROL_fromReg(target, Register::CL)),
0b001 => Mnemonic::ROR_fromReg(target, Register::CL), 0b001 => Ok(Mnemonic::ROR_fromReg(target, Register::CL)),
0b010 => Mnemonic::RCL_fromReg(target, Register::CL), 0b010 => Ok(Mnemonic::RCL_fromReg(target, Register::CL)),
0b011 => Mnemonic::RCR_fromReg(target, Register::CL), 0b011 => Ok(Mnemonic::RCR_fromReg(target, Register::CL)),
0b100 => Mnemonic::SHL_fromReg(target, Register::CL), 0b100 => Ok(Mnemonic::SHL_fromReg(target, Register::CL)),
0b101 => Mnemonic::SHR_fromReg(target, Register::CL), 0b101 => Ok(Mnemonic::SHR_fromReg(target, Register::CL)),
0b110 => Mnemonic::SAR_fromReg(target, Register::CL), 0b110 => Ok(Mnemonic::SAR_fromReg(target, Register::CL)),
0b111 => Mnemonic::SAR_fromReg(target, Register::CL), 0b111 => Ok(Mnemonic::SAR_fromReg(target, Register::CL)),
_ => panic!("Illegal Group 2 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(2, reg)),
} }
} }
/// Match the modrm reg bits to the GPR3a/b mnemonics. /// Match the modrm reg bits to the GPR3a/b mnemonics.
/// Group 3 only has a single operand, which is the ModRmTarget selected /// Group 3 only has a single operand, which is the ModRmTarget selected
/// by modrm bits. /// by modrm bits.
pub fn modrm_reg_to_grp3(&mut self, reg: u8, target: ModRmTarget, width: Operand) -> Mnemonic { pub fn modrm_reg_to_grp3(
&mut self,
reg: u8,
target: ModRmTarget,
width: Operand,
) -> Result<Mnemonic, DisasmError> {
match reg { match reg {
0b000 => match width { 0b000 => match width {
Operand::Byte(_) => Mnemonic::TEST_Ib(target, self.parse_byte()), Operand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
Operand::Word(_) => Mnemonic::TEST_Iv(target, self.parse_word()), Operand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
}, },
// 0b001 => // unused // 0b001 => // unused
0b010 => Mnemonic::NOT(target), 0b010 => Ok(Mnemonic::NOT(target)),
0b011 => Mnemonic::NEG(target), 0b011 => Ok(Mnemonic::NEG(target)),
0b100 => Mnemonic::MUL(target), 0b100 => Ok(Mnemonic::MUL(target)),
0b101 => Mnemonic::IMUL(target), 0b101 => Ok(Mnemonic::IMUL(target)),
0b110 => Mnemonic::DIV(target), 0b110 => Ok(Mnemonic::DIV(target)),
0b111 => Mnemonic::IDIV(target), 0b111 => Ok(Mnemonic::IDIV(target)),
_ => panic!("Illegal Group 3 mnemonic"), _ => Err(DisasmError::IllegalGroupMnemonic(3, reg)),
} }
} }
@@ -334,7 +374,7 @@ impl Disassembler {
/// An Mp is a ModRM byte with the `reg` bits ignored and an additional /// An Mp is a ModRM byte with the `reg` bits ignored and an additional
/// 2 words parsed for a `Pointer` type. /// 2 words parsed for a `Pointer` type.
pub fn modrm_mp(&mut self) -> Result<(ModRmTarget, Pointer), DisasmError> { pub fn modrm_mp(&mut self) -> Result<(ModRmTarget, Pointer), DisasmError> {
let (target, _) = self.parse_modrm_byte(Operand::Byte(0)); let (target, _) = self.parse_modrm_byte(Operand::Byte(0))?;
let ptr = Pointer::new(self)?; let ptr = Pointer::new(self)?;
Ok((target, ptr)) Ok((target, ptr))
} }
@@ -362,8 +402,8 @@ impl Disassembler {
0x01 => modrmv!(self, ADD_FromReg), 0x01 => modrmv!(self, ADD_FromReg),
0x02 => modrmb!(self, ADD_ToReg), 0x02 => modrmb!(self, ADD_ToReg),
0x03 => modrmv!(self, ADD_ToReg), 0x03 => modrmv!(self, ADD_ToReg),
0x04 => Mnemonic::ADD_ALIb(self.parse_byte()), 0x04 => Mnemonic::ADD_ALIb(self.parse_byte()?),
0x05 => Mnemonic::ADD_AXIv(self.parse_word()), 0x05 => Mnemonic::ADD_AXIv(self.parse_word()?),
0x06 => Mnemonic::PUSH_S(SegmentRegister::ES), 0x06 => Mnemonic::PUSH_S(SegmentRegister::ES),
0x07 => Mnemonic::POP_S(SegmentRegister::ES), 0x07 => Mnemonic::POP_S(SegmentRegister::ES),
@@ -372,8 +412,8 @@ impl Disassembler {
0x09 => modrmv!(self, OR_FromReg), 0x09 => modrmv!(self, OR_FromReg),
0x0A => modrmb!(self, OR_ToReg), 0x0A => modrmb!(self, OR_ToReg),
0x0B => modrmv!(self, OR_ToReg), 0x0B => modrmv!(self, OR_ToReg),
0x0C => Mnemonic::OR_ALIb(self.parse_byte()), 0x0C => Mnemonic::OR_ALIb(self.parse_byte()?),
0x0D => Mnemonic::OR_AXIv(self.parse_word()), 0x0D => Mnemonic::OR_AXIv(self.parse_word()?),
0x0E => Mnemonic::PUSH_S(SegmentRegister::CS), 0x0E => Mnemonic::PUSH_S(SegmentRegister::CS),
@@ -383,8 +423,8 @@ impl Disassembler {
0x11 => modrmv!(self, ADC_FromReg), 0x11 => modrmv!(self, ADC_FromReg),
0x12 => modrmb!(self, ADC_ToReg), 0x12 => modrmb!(self, ADC_ToReg),
0x13 => modrmv!(self, ADC_ToReg), 0x13 => modrmv!(self, ADC_ToReg),
0x14 => Mnemonic::ADC_ALIb(self.parse_byte()), 0x14 => Mnemonic::ADC_ALIb(self.parse_byte()?),
0x15 => Mnemonic::ADC_AXIv(self.parse_word()), 0x15 => Mnemonic::ADC_AXIv(self.parse_word()?),
0x16 => Mnemonic::PUSH_S(SegmentRegister::SS), 0x16 => Mnemonic::PUSH_S(SegmentRegister::SS),
0x17 => Mnemonic::POP_S(SegmentRegister::SS), 0x17 => Mnemonic::POP_S(SegmentRegister::SS),
@@ -393,8 +433,8 @@ impl Disassembler {
0x19 => modrmv!(self, SBB_FromReg), 0x19 => modrmv!(self, SBB_FromReg),
0x1A => modrmb!(self, SBB_ToReg), 0x1A => modrmb!(self, SBB_ToReg),
0x1B => modrmv!(self, SBB_ToReg), 0x1B => modrmv!(self, SBB_ToReg),
0x1C => Mnemonic::SBB_ALIb(self.parse_byte()), 0x1C => Mnemonic::SBB_ALIb(self.parse_byte()?),
0x1D => Mnemonic::SBB_AXIv(self.parse_word()), 0x1D => Mnemonic::SBB_AXIv(self.parse_word()?),
0x1E => Mnemonic::PUSH_S(SegmentRegister::DS), 0x1E => Mnemonic::PUSH_S(SegmentRegister::DS),
0x1F => Mnemonic::POP_S(SegmentRegister::DS), 0x1F => Mnemonic::POP_S(SegmentRegister::DS),
@@ -403,8 +443,8 @@ impl Disassembler {
0x21 => modrmv!(self, AND_FromReg), 0x21 => modrmv!(self, AND_FromReg),
0x22 => modrmb!(self, AND_ToReg), 0x22 => modrmb!(self, AND_ToReg),
0x23 => modrmv!(self, AND_ToReg), 0x23 => modrmv!(self, AND_ToReg),
0x24 => Mnemonic::AND_ALIb(self.parse_byte()), 0x24 => Mnemonic::AND_ALIb(self.parse_byte()?),
0x25 => Mnemonic::AND_AXIv(self.parse_word()), 0x25 => Mnemonic::AND_AXIv(self.parse_word()?),
0x26 => Mnemonic::OVERRIDE(SegmentRegister::ES), 0x26 => Mnemonic::OVERRIDE(SegmentRegister::ES),
0x27 => Mnemonic::DAA, 0x27 => Mnemonic::DAA,
@@ -413,8 +453,8 @@ impl Disassembler {
0x29 => modrmv!(self, SUB_FromReg), 0x29 => modrmv!(self, SUB_FromReg),
0x2A => modrmb!(self, SUB_ToReg), 0x2A => modrmb!(self, SUB_ToReg),
0x2B => modrmv!(self, SUB_ToReg), 0x2B => modrmv!(self, SUB_ToReg),
0x2C => Mnemonic::SUB_ALIb(self.parse_byte()), 0x2C => Mnemonic::SUB_ALIb(self.parse_byte()?),
0x2D => Mnemonic::SUB_AXIv(self.parse_word()), 0x2D => Mnemonic::SUB_AXIv(self.parse_word()?),
0x2E => Mnemonic::OVERRIDE(SegmentRegister::CS), 0x2E => Mnemonic::OVERRIDE(SegmentRegister::CS),
0x2F => Mnemonic::DAS, 0x2F => Mnemonic::DAS,
@@ -423,8 +463,8 @@ impl Disassembler {
0x31 => modrmv!(self, XOR_FromReg), 0x31 => modrmv!(self, XOR_FromReg),
0x32 => modrmb!(self, XOR_ToReg), 0x32 => modrmb!(self, XOR_ToReg),
0x33 => modrmv!(self, XOR_ToReg), 0x33 => modrmv!(self, XOR_ToReg),
0x34 => Mnemonic::XOR_ALIb(self.parse_byte()), 0x34 => Mnemonic::XOR_ALIb(self.parse_byte()?),
0x35 => Mnemonic::XOR_AXIv(self.parse_word()), 0x35 => Mnemonic::XOR_AXIv(self.parse_word()?),
0x36 => Mnemonic::OVERRIDE(SegmentRegister::SS), 0x36 => Mnemonic::OVERRIDE(SegmentRegister::SS),
0x37 => Mnemonic::AAA, 0x37 => Mnemonic::AAA,
@@ -433,8 +473,8 @@ impl Disassembler {
0x39 => modrmv!(self, CMP_FromReg), 0x39 => modrmv!(self, CMP_FromReg),
0x3A => modrmb!(self, CMP_ToReg), 0x3A => modrmb!(self, CMP_ToReg),
0x3B => modrmv!(self, CMP_ToReg), 0x3B => modrmv!(self, CMP_ToReg),
0x3C => Mnemonic::CMP_ALIb(self.parse_byte()), 0x3C => Mnemonic::CMP_ALIb(self.parse_byte()?),
0x3D => Mnemonic::CMP_AXIv(self.parse_word()), 0x3D => Mnemonic::CMP_AXIv(self.parse_word()?),
0x3E => Mnemonic::OVERRIDE(SegmentRegister::DS), 0x3E => Mnemonic::OVERRIDE(SegmentRegister::DS),
0x3F => Mnemonic::AAS, 0x3F => Mnemonic::AAS,
@@ -477,45 +517,45 @@ impl Disassembler {
0x60..=0x6F => return Err(DisasmError::OpcodeUndefined(opcode)), 0x60..=0x6F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x70 => Mnemonic::JO(self.parse_j_byte()), 0x70 => Mnemonic::JO(self.parse_j_byte()?),
0x71 => Mnemonic::JNO(self.parse_j_byte()), 0x71 => Mnemonic::JNO(self.parse_j_byte()?),
0x72 => Mnemonic::JB(self.parse_j_byte()), 0x72 => Mnemonic::JB(self.parse_j_byte()?),
0x73 => Mnemonic::JNB(self.parse_j_byte()), 0x73 => Mnemonic::JNB(self.parse_j_byte()?),
0x74 => Mnemonic::JZ(self.parse_j_byte()), 0x74 => Mnemonic::JZ(self.parse_j_byte()?),
0x75 => Mnemonic::JNZ(self.parse_j_byte()), 0x75 => Mnemonic::JNZ(self.parse_j_byte()?),
0x76 => Mnemonic::JBE(self.parse_j_byte()), 0x76 => Mnemonic::JBE(self.parse_j_byte()?),
0x77 => Mnemonic::JA(self.parse_j_byte()), 0x77 => Mnemonic::JA(self.parse_j_byte()?),
0x78 => Mnemonic::JS(self.parse_j_byte()), 0x78 => Mnemonic::JS(self.parse_j_byte()?),
0x79 => Mnemonic::JNS(self.parse_j_byte()), 0x79 => Mnemonic::JNS(self.parse_j_byte()?),
0x7A => Mnemonic::JPE(self.parse_j_byte()), 0x7A => Mnemonic::JPE(self.parse_j_byte()?),
0x7B => Mnemonic::JPO(self.parse_j_byte()), 0x7B => Mnemonic::JPO(self.parse_j_byte()?),
0x7C => Mnemonic::JL(self.parse_j_byte()), 0x7C => Mnemonic::JL(self.parse_j_byte()?),
0x7D => Mnemonic::JGE(self.parse_j_byte()), 0x7D => Mnemonic::JGE(self.parse_j_byte()?),
0x7E => Mnemonic::JLE(self.parse_j_byte()), 0x7E => Mnemonic::JLE(self.parse_j_byte()?),
0x7F => Mnemonic::JG(self.parse_j_byte()), 0x7F => Mnemonic::JG(self.parse_j_byte()?),
// Group 1 // Group 1
0x80 => { 0x80 => {
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
let imm = self.parse_byte(); let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm)) Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
} }
0x81 => { 0x81 => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
let imm = self.parse_word(); let imm = self.parse_word()?;
Self::modrm_reg_to_grp1(reg, target, Operand::Word(imm)) Self::modrm_reg_to_grp1(reg, target, Operand::Word(imm))?
} }
0x82 => { 0x82 => {
// same as 0x80 // same as 0x80
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
let imm = self.parse_byte(); let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm)) Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
} }
0x83 => { 0x83 => {
// byte extended version // byte extended version
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
let imm = self.parse_byte(); let imm = self.parse_byte()?;
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm)) Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))?
} }
0x84 => modrmb!(self, TEST), 0x84 => modrmb!(self, TEST),
@@ -534,7 +574,7 @@ impl Disassembler {
0x8D => modrmv!(self, LEA), 0x8D => modrmv!(self, LEA),
0x8F => { 0x8F => {
let target = self.parse_modrm_byte(Operand::Word(0)).0; let target = self.parse_modrm_byte(Operand::Word(0))?.0;
let mem = match target { let mem = match target {
ModRmTarget::Memory(idx) => idx, ModRmTarget::Memory(idx) => idx,
_ => panic!("POP_M instruction given a register to pop into"), _ => panic!("POP_M instruction given a register to pop into"),
@@ -554,16 +594,7 @@ impl Disassembler {
0x98 => Mnemonic::CBW, 0x98 => Mnemonic::CBW,
0x99 => Mnemonic::CWD, 0x99 => Mnemonic::CWD,
0x9A => Mnemonic::CALL_p(Pointer { 0x9A => Mnemonic::CALL_p(Pointer::new(self)?),
raw: DWord::from_le_bytes([
self.text[self.offset],
self.text[self.offset + 1],
self.text[self.offset + 2],
self.text[self.offset + 3],
]),
segment: self.parse_word(),
offset: self.parse_word(),
}),
0x9B => Mnemonic::WAIT, 0x9B => Mnemonic::WAIT,
@@ -572,18 +603,18 @@ impl Disassembler {
0x9E => Mnemonic::SAHF, 0x9E => Mnemonic::SAHF,
0x9F => Mnemonic::LAHF, 0x9F => Mnemonic::LAHF,
0xA0 => Mnemonic::MOV_AL0b(self.parse_byte()), 0xA0 => Mnemonic::MOV_AL0b(self.parse_byte()?),
0xA1 => Mnemonic::MOV_AX0v(self.parse_word()), 0xA1 => Mnemonic::MOV_AX0v(self.parse_word()?),
0xA2 => Mnemonic::MOV_0bAL(self.parse_byte()), 0xA2 => Mnemonic::MOV_0bAL(self.parse_byte()?),
0xA3 => Mnemonic::MOV_0vAX(self.parse_word()), 0xA3 => Mnemonic::MOV_0vAX(self.parse_word()?),
0xA4 => Mnemonic::MOVSB, 0xA4 => Mnemonic::MOVSB,
0xA5 => Mnemonic::MOVSW, 0xA5 => Mnemonic::MOVSW,
0xA6 => Mnemonic::CMPSB, 0xA6 => Mnemonic::CMPSB,
0xA7 => Mnemonic::CMPSW, 0xA7 => Mnemonic::CMPSW,
0xA8 => Mnemonic::TEST_ALIb(self.parse_byte()), 0xA8 => Mnemonic::TEST_ALIb(self.parse_byte()?),
0xA9 => Mnemonic::TEST_AXIv(self.parse_word()), 0xA9 => Mnemonic::TEST_AXIv(self.parse_word()?),
0xAA => Mnemonic::STOSB, 0xAA => Mnemonic::STOSB,
0xAB => Mnemonic::STOSW, 0xAB => Mnemonic::STOSW,
@@ -592,26 +623,26 @@ impl Disassembler {
0xAE => Mnemonic::SCASB, 0xAE => Mnemonic::SCASB,
0xAF => Mnemonic::SCASW, 0xAF => Mnemonic::SCASW,
0xB0 => Mnemonic::MOV_ALIb(self.parse_byte()), 0xB0 => Mnemonic::MOV_ALIb(self.parse_byte()?),
0xB1 => Mnemonic::MOV_CLIb(self.parse_byte()), 0xB1 => Mnemonic::MOV_CLIb(self.parse_byte()?),
0xB2 => Mnemonic::MOV_DLIb(self.parse_byte()), 0xB2 => Mnemonic::MOV_DLIb(self.parse_byte()?),
0xB3 => Mnemonic::MOV_BLIb(self.parse_byte()), 0xB3 => Mnemonic::MOV_BLIb(self.parse_byte()?),
0xB4 => Mnemonic::MOV_AHIb(self.parse_byte()), 0xB4 => Mnemonic::MOV_AHIb(self.parse_byte()?),
0xB5 => Mnemonic::MOV_CHIb(self.parse_byte()), 0xB5 => Mnemonic::MOV_CHIb(self.parse_byte()?),
0xB6 => Mnemonic::MOV_DHIb(self.parse_byte()), 0xB6 => Mnemonic::MOV_DHIb(self.parse_byte()?),
0xB7 => Mnemonic::MOV_BHIb(self.parse_byte()), 0xB7 => Mnemonic::MOV_BHIb(self.parse_byte()?),
0xB8 => Mnemonic::MOV_AXIv(self.parse_word()), 0xB8 => Mnemonic::MOV_AXIv(self.parse_word()?),
0xB9 => Mnemonic::MOV_CXIv(self.parse_word()), 0xB9 => Mnemonic::MOV_CXIv(self.parse_word()?),
0xBA => Mnemonic::MOV_DXIv(self.parse_word()), 0xBA => Mnemonic::MOV_DXIv(self.parse_word()?),
0xBB => Mnemonic::MOV_BXIv(self.parse_word()), 0xBB => Mnemonic::MOV_BXIv(self.parse_word()?),
0xBC => Mnemonic::MOV_SPIv(self.parse_word()), 0xBC => Mnemonic::MOV_SPIv(self.parse_word()?),
0xBD => Mnemonic::MOV_BPIv(self.parse_word()), 0xBD => Mnemonic::MOV_BPIv(self.parse_word()?),
0xBE => Mnemonic::MOV_SIIv(self.parse_word()), 0xBE => Mnemonic::MOV_SIIv(self.parse_word()?),
0xBF => Mnemonic::MOV_DIIv(self.parse_word()), 0xBF => Mnemonic::MOV_DIIv(self.parse_word()?),
0xC0..=0xC1 => return Err(DisasmError::OpcodeUndefined(opcode)), 0xC0..=0xC1 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xC2 => Mnemonic::RET_Iw(self.parse_word()), 0xC2 => Mnemonic::RET_Iw(self.parse_word()?),
0xC3 => Mnemonic::RET, 0xC3 => Mnemonic::RET,
0xC4 => { 0xC4 => {
@@ -624,45 +655,45 @@ impl Disassembler {
} }
0xC6 => { 0xC6 => {
let (target, _) = self.parse_modrm_byte(Operand::Byte(0)); let (target, _) = self.parse_modrm_byte(Operand::Byte(0))?;
Mnemonic::MOV_Ib(target, self.parse_byte()) Mnemonic::MOV_Ib(target, self.parse_byte()?)
} }
0xC7 => { 0xC7 => {
let (target, _) = self.parse_modrm_byte(Operand::Word(0)); let (target, _) = self.parse_modrm_byte(Operand::Word(0))?;
Mnemonic::MOV_Iv(target, self.parse_word()) Mnemonic::MOV_Iv(target, self.parse_word()?)
} }
0xC8..=0xC9 => return Err(DisasmError::OpcodeUndefined(opcode)), 0xC8..=0xC9 => return Err(DisasmError::OpcodeUndefined(opcode)),
0xCA => Mnemonic::RETF_Iw(self.parse_word()), 0xCA => Mnemonic::RETF_Iw(self.parse_word()?),
0xCB => Mnemonic::RETF, 0xCB => Mnemonic::RETF,
0xCC => Mnemonic::INT(3), 0xCC => Mnemonic::INT(3),
0xCD => Mnemonic::INT(self.parse_byte()), 0xCD => Mnemonic::INT(self.parse_byte()?),
0xCE => Mnemonic::INTO, 0xCE => Mnemonic::INTO,
0xCF => Mnemonic::IRET, 0xCF => Mnemonic::IRET,
// Group 2 // Group 2
0xD0 => { 0xD0 => {
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
Self::modrm_reg_to_grp2_1(reg, target) Self::modrm_reg_to_grp2_1(reg, target)?
} }
0xD1 => { 0xD1 => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
Self::modrm_reg_to_grp2_1(reg, target) Self::modrm_reg_to_grp2_1(reg, target)?
} }
0xD2 => { 0xD2 => {
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
Self::modrm_reg_to_grp2_cl(reg, target) Self::modrm_reg_to_grp2_cl(reg, target)?
} }
0xD3 => { 0xD3 => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
Self::modrm_reg_to_grp2_cl(reg, target) Self::modrm_reg_to_grp2_cl(reg, target)?
} }
0xD4 => Mnemonic::AAM(self.parse_byte()), 0xD4 => Mnemonic::AAM(self.parse_byte()?),
0xD5 => Mnemonic::AAD(self.parse_byte()), 0xD5 => Mnemonic::AAD(self.parse_byte()?),
0xD6 => return Err(DisasmError::OpcodeUndefined(opcode)), 0xD6 => return Err(DisasmError::OpcodeUndefined(opcode)),
@@ -670,21 +701,21 @@ impl Disassembler {
0xD8..=0xDF => return Err(DisasmError::OpcodeUndefined(opcode)), 0xD8..=0xDF => return Err(DisasmError::OpcodeUndefined(opcode)),
0xE0 => Mnemonic::LOOPNZ(self.parse_j_byte()), 0xE0 => Mnemonic::LOOPNZ(self.parse_j_byte()?),
0xE1 => Mnemonic::LOOPZ(self.parse_j_byte()), 0xE1 => Mnemonic::LOOPZ(self.parse_j_byte()?),
0xE2 => Mnemonic::LOOP(self.parse_j_byte()), 0xE2 => Mnemonic::LOOP(self.parse_j_byte()?),
0xE3 => Mnemonic::JCXZ(self.parse_j_byte()), 0xE3 => Mnemonic::JCXZ(self.parse_j_byte()?),
0xE4 => Mnemonic::IN_AL(self.parse_byte()), 0xE4 => Mnemonic::IN_AL(self.parse_byte()?),
0xE5 => Mnemonic::IN_AX(self.parse_byte()), 0xE5 => Mnemonic::IN_AX(self.parse_byte()?),
0xE6 => Mnemonic::OUT_AL(self.parse_byte()), 0xE6 => Mnemonic::OUT_AL(self.parse_byte()?),
0xE7 => Mnemonic::OUT_AX(self.parse_byte()), 0xE7 => Mnemonic::OUT_AX(self.parse_byte()?),
0xE8 => Mnemonic::CALL_v(self.parse_j_word()), 0xE8 => Mnemonic::CALL_v(self.parse_j_word()?),
0xE9 => Mnemonic::JMP_v(self.parse_j_word()), 0xE9 => Mnemonic::JMP_v(self.parse_j_word()?),
0xEA => Mnemonic::JMP_p(Pointer::new(self)?), 0xEA => Mnemonic::JMP_p(Pointer::new(self)?),
0xEB => Mnemonic::JMP_b(self.parse_j_byte()), 0xEB => Mnemonic::JMP_b(self.parse_j_byte()?),
0xEC => Mnemonic::IN_ALDX, 0xEC => Mnemonic::IN_ALDX,
0xED => Mnemonic::IN_AXDX, 0xED => Mnemonic::IN_AXDX,
@@ -703,12 +734,12 @@ impl Disassembler {
// Group 3 // Group 3
0xF6 => { 0xF6 => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
self.modrm_reg_to_grp3(reg, target, Operand::Byte(0)) self.modrm_reg_to_grp3(reg, target, Operand::Byte(0))?
} }
0xF7 => { 0xF7 => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
self.modrm_reg_to_grp3(reg, target, Operand::Word(0)) self.modrm_reg_to_grp3(reg, target, Operand::Word(0))?
} }
0xF8 => Mnemonic::CLC, 0xF8 => Mnemonic::CLC,
@@ -719,15 +750,15 @@ impl Disassembler {
0xFD => Mnemonic::STD, 0xFD => Mnemonic::STD,
0xFE => { 0xFE => {
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = self.parse_modrm_byte(Operand::Byte(0))?;
match reg { match reg {
0b0 => Mnemonic::INC_Mod(target), 0b0 => Mnemonic::INC_Mod(target),
0b1 => Mnemonic::DEC_Mod(target), 0b1 => Mnemonic::DEC_Mod(target),
_ => panic!("Illegal Group 4 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(4, reg)),
} }
} }
0xFF => { 0xFF => {
let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = self.parse_modrm_byte(Operand::Word(0))?;
match reg { match reg {
0b000 => Mnemonic::INC_Mod(target), 0b000 => Mnemonic::INC_Mod(target),
0b001 => Mnemonic::DEC_Mod(target), 0b001 => Mnemonic::DEC_Mod(target),
@@ -737,7 +768,7 @@ impl Disassembler {
0b101 => Mnemonic::JMP_Mp(target, Pointer::new(self)?), 0b101 => Mnemonic::JMP_Mp(target, Pointer::new(self)?),
0b110 => Mnemonic::PUSH_Mod(target), 0b110 => Mnemonic::PUSH_Mod(target),
// 0b111 => unused // 0b111 => unused
_ => panic!("Illegal Group 5 mnemonic"), _ => return Err(DisasmError::IllegalGroupMnemonic(5, reg)),
} }
} }

View File

@@ -4,8 +4,8 @@
/// Generate a Mnemonic for an 8-bit Register from a ModRM byte. /// Generate a Mnemonic for an 8-bit Register from a ModRM byte.
macro_rules! modrmb { macro_rules! modrmb {
($self:ident, $variant:ident) => {{ ($self:ident, $variant:ident) => {{
let (target, reg) = $self.parse_modrm_byte(Operand::Byte(0)); let (target, reg) = $self.parse_modrm_byte(Operand::Byte(0))?;
Mnemonic::$variant(target, Register::by_id(Operand::Byte(reg))) Mnemonic::$variant(target, Register::by_id(Operand::Byte(reg))?)
}}; }};
} }
@@ -13,8 +13,8 @@ macro_rules! modrmb {
/// Generate a Mnemonic for a 16-bit Register from a ModRM byte. /// Generate a Mnemonic for a 16-bit Register from a ModRM byte.
macro_rules! modrmv { macro_rules! modrmv {
($self:ident, $variant:ident) => {{ ($self:ident, $variant:ident) => {{
let (target, reg) = $self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = $self.parse_modrm_byte(Operand::Word(0))?;
Mnemonic::$variant(target, Register::by_id(Operand::Word(reg.into()))) Mnemonic::$variant(target, Register::by_id(Operand::Word(reg.into()))?)
}}; }};
} }
@@ -22,7 +22,7 @@ macro_rules! modrmv {
/// Generate a Mnemonic for a 16-bit Segment Register from a ModRM byte. /// Generate a Mnemonic for a 16-bit Segment Register from a ModRM byte.
macro_rules! modrms { macro_rules! modrms {
($self:ident, $variant:ident) => {{ ($self:ident, $variant:ident) => {{
let (target, reg) = $self.parse_modrm_byte(Operand::Word(0)); let (target, reg) = $self.parse_modrm_byte(Operand::Word(0))?;
Mnemonic::$variant(target, SegmentRegister::by_id(reg)) Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
}}; }};
} }

View File

@@ -141,27 +141,31 @@ pub struct Pointer {
impl Pointer { impl Pointer {
pub fn new(disasm: &mut Disassembler) -> Result<Self, DisasmError> { pub fn new(disasm: &mut Disassembler) -> Result<Self, DisasmError> {
log::debug!(
"Seeking 4 bytes ahead of current text offset... ({} + 4)",
disasm.offset
);
let byte0 = disasm let byte0 = disasm
.text .text
.get(disasm.offset) .get(disasm.offset)
.ok_or(DisasmError::IndexOutOfBounds(disasm.offset))?; .ok_or(DisasmError::ReadBeyondTextSection(disasm.clone()))?;
let byte1 = disasm let byte1 = disasm
.text .text
.get(disasm.offset + 1) .get(disasm.offset + 1)
.ok_or(DisasmError::IndexOutOfBounds(disasm.offset + 1))?; .ok_or(DisasmError::ReadBeyondTextSection(disasm.clone()))?;
let byte2 = disasm let byte2 = disasm
.text .text
.get(disasm.offset + 2) .get(disasm.offset + 2)
.ok_or(DisasmError::IndexOutOfBounds(disasm.offset + 2))?; .ok_or(DisasmError::ReadBeyondTextSection(disasm.clone()))?;
let byte3 = disasm let byte3 = disasm
.text .text
.get(disasm.offset + 3) .get(disasm.offset + 3)
.ok_or(DisasmError::IndexOutOfBounds(disasm.offset + 3))?; .ok_or(DisasmError::ReadBeyondTextSection(disasm.clone()))?;
Ok(Pointer { Ok(Pointer {
raw: DWord::from_le_bytes([*byte0, *byte1, *byte2, *byte3]), raw: DWord::from_le_bytes([*byte0, *byte1, *byte2, *byte3]),
segment: disasm.parse_word(), segment: disasm.parse_word()?,
offset: disasm.parse_word(), offset: disasm.parse_word()?,
}) })
} }
} }

View File

@@ -1,6 +1,6 @@
//! Internal abstraction of all 8086 registers for disassembly. //! Internal abstraction of all 8086 registers for disassembly.
use crate::operands::Operand; use crate::{disasm::DisasmError, operands::Operand};
use core::fmt; use core::fmt;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -36,29 +36,29 @@ pub type RegisterId = u8;
#[allow(dead_code)] #[allow(dead_code)]
impl Register { impl Register {
/// Find the register corresponding to the 8086 bytecode ID /// Find the register corresponding to the 8086 bytecode ID
pub fn by_id(id: Operand) -> Self { pub fn by_id(id: Operand) -> Result<Self, DisasmError> {
match id { match id {
Operand::Byte(b) => match b { Operand::Byte(b) => match b {
0b000 => Self::AL, 0b000 => Ok(Self::AL),
0b001 => Self::CL, 0b001 => Ok(Self::CL),
0b010 => Self::DL, 0b010 => Ok(Self::DL),
0b011 => Self::BL, 0b011 => Ok(Self::BL),
0b100 => Self::AH, 0b100 => Ok(Self::AH),
0b101 => Self::CH, 0b101 => Ok(Self::CH),
0b110 => Self::DH, 0b110 => Ok(Self::DH),
0b111 => Self::BH, 0b111 => Ok(Self::BH),
_ => panic!("Invalid 8bit register ID encountered"), _ => Err(DisasmError::UnknownRegister(b as usize)),
}, },
Operand::Word(w) => match w { Operand::Word(w) => match w {
0b000 => Self::AX, 0b000 => Ok(Self::AX),
0b001 => Self::CX, 0b001 => Ok(Self::CX),
0b010 => Self::DX, 0b010 => Ok(Self::DX),
0b011 => Self::BX, 0b011 => Ok(Self::BX),
0b100 => Self::SP, 0b100 => Ok(Self::SP),
0b101 => Self::BP, 0b101 => Ok(Self::BP),
0b110 => Self::SI, 0b110 => Ok(Self::SI),
0b111 => Self::DI, 0b111 => Ok(Self::DI),
_ => panic!("Invalid 16bit register ID encountered"), _ => Err(DisasmError::UnknownRegister(w as usize)),
}, },
} }
} }
@@ -100,13 +100,13 @@ pub enum SegmentRegister {
#[allow(dead_code)] #[allow(dead_code)]
impl SegmentRegister { impl SegmentRegister {
/// Find the SRegister corresponding to the 8086 bytecode ID /// Find the SRegister corresponding to the 8086 bytecode ID
pub fn by_id(id: u8) -> Self { pub fn by_id(id: u8) -> Result<Self, DisasmError> {
match id { match id {
0x00 => Self::ES, 0x00 => Ok(Self::ES),
0x01 => Self::CS, 0x01 => Ok(Self::CS),
0x10 => Self::SS, 0x10 => Ok(Self::SS),
0x11 => Self::DS, 0x11 => Ok(Self::DS),
_ => panic!("Invalid segment register ID encountered"), _ => Err(DisasmError::UnknownRegister(id as usize)),
} }
} }
} }