ft: use instructionwidth instead of immediateoperand
Previously an immediate operand with data of 0 was use to encode width, now use a dedicated enum for improved clarity.
This commit is contained in:
@@ -14,6 +14,13 @@ use crate::{modrm_8b_register, modrm_16b_register, modrm_sregister};
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::{fs::File, io::Read};
|
use std::{fs::File, io::Read};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// Select, wheter 8, or 16-bit Registers should be selected.
|
||||||
|
pub enum InstructionWidth {
|
||||||
|
Byte,
|
||||||
|
Word,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Generic errors, which are encountered during parsing.
|
/// Generic errors, which are encountered during parsing.
|
||||||
pub enum DisasmError {
|
pub enum DisasmError {
|
||||||
@@ -240,7 +247,7 @@ impl Disassembler {
|
|||||||
/// or even mnemonic in the group-type instructions.
|
/// or even mnemonic in the group-type instructions.
|
||||||
fn parse_modrm_byte(
|
fn parse_modrm_byte(
|
||||||
&mut self,
|
&mut self,
|
||||||
register_width: ImmediateOperand,
|
register_width: Option<InstructionWidth>,
|
||||||
) -> Result<(ModRmTarget, RegisterId), DisasmError> {
|
) -> Result<(ModRmTarget, RegisterId), DisasmError> {
|
||||||
let modrm = self.parse_byte()?;
|
let modrm = self.parse_byte()?;
|
||||||
|
|
||||||
@@ -292,13 +299,17 @@ impl Disassembler {
|
|||||||
log::debug!(
|
log::debug!(
|
||||||
"ModRM selected Register to Register: ({rm:#b}) to/from RegID ({reg:#b})"
|
"ModRM selected Register to Register: ({rm:#b}) to/from RegID ({reg:#b})"
|
||||||
);
|
);
|
||||||
let target = match register_width {
|
let target = if let Some(width) = register_width {
|
||||||
ImmediateOperand::Byte(_) => {
|
match width {
|
||||||
ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?)
|
InstructionWidth::Byte => {
|
||||||
}
|
ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?)
|
||||||
ImmediateOperand::Word(_) => {
|
}
|
||||||
ModRmTarget::Register(Register::by_id(ImmediateOperand::Word(rm as Word))?)
|
InstructionWidth::Word => ModRmTarget::Register(Register::by_id(
|
||||||
|
ImmediateOperand::Word(rm as Word),
|
||||||
|
)?),
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
panic!("No Register width provided, when it was needed");
|
||||||
};
|
};
|
||||||
return Ok((target, reg));
|
return Ok((target, reg));
|
||||||
}
|
}
|
||||||
@@ -359,9 +370,9 @@ impl Disassembler {
|
|||||||
fn modrm_reg_to_grp1(
|
fn modrm_reg_to_grp1(
|
||||||
reg: u8,
|
reg: u8,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
instruction_width: ImmediateOperand,
|
val: ImmediateOperand,
|
||||||
) -> Result<Mnemonic, DisasmError> {
|
) -> Result<Mnemonic, DisasmError> {
|
||||||
match instruction_width {
|
match val {
|
||||||
ImmediateOperand::Byte(b) => match reg {
|
ImmediateOperand::Byte(b) => match reg {
|
||||||
0b000 => Ok(Mnemonic::ADD_Ib(target, b)),
|
0b000 => Ok(Mnemonic::ADD_Ib(target, b)),
|
||||||
0b001 => Ok(Mnemonic::OR_Ib(target, b)),
|
0b001 => Ok(Mnemonic::OR_Ib(target, b)),
|
||||||
@@ -432,12 +443,12 @@ impl Disassembler {
|
|||||||
&mut self,
|
&mut self,
|
||||||
reg: u8,
|
reg: u8,
|
||||||
target: ModRmTarget,
|
target: ModRmTarget,
|
||||||
width: ImmediateOperand,
|
width: InstructionWidth,
|
||||||
) -> Result<Mnemonic, DisasmError> {
|
) -> Result<Mnemonic, DisasmError> {
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => match width {
|
0b000 => match width {
|
||||||
ImmediateOperand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
|
InstructionWidth::Byte => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)),
|
||||||
ImmediateOperand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
|
InstructionWidth::Word => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)),
|
||||||
},
|
},
|
||||||
// 0b001 => // unused
|
// 0b001 => // unused
|
||||||
0b010 => Ok(Mnemonic::NOT(target)),
|
0b010 => Ok(Mnemonic::NOT(target)),
|
||||||
@@ -639,24 +650,24 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 1
|
// Group 1
|
||||||
0x80 => {
|
0x80 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
0x81 => {
|
0x81 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
let imm = self.parse_word()?;
|
let imm = self.parse_word()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))?
|
||||||
}
|
}
|
||||||
0x82 => {
|
0x82 => {
|
||||||
// same as 0x80
|
// same as 0x80
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
0x83 => {
|
0x83 => {
|
||||||
// byte extended version
|
// byte extended version
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
let imm = self.parse_byte()?;
|
let imm = self.parse_byte()?;
|
||||||
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))?
|
||||||
}
|
}
|
||||||
@@ -677,7 +688,7 @@ impl Disassembler {
|
|||||||
0x8D => modrm_16b_register!(self, LEA),
|
0x8D => modrm_16b_register!(self, LEA),
|
||||||
|
|
||||||
0x8F => {
|
0x8F => {
|
||||||
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
let mem = match target {
|
let mem = match target {
|
||||||
ModRmTarget::Memory(idx) => idx,
|
ModRmTarget::Memory(idx) => idx,
|
||||||
_ => {
|
_ => {
|
||||||
@@ -753,24 +764,24 @@ impl Disassembler {
|
|||||||
0xC3 => Mnemonic::RET,
|
0xC3 => Mnemonic::RET,
|
||||||
|
|
||||||
0xC4 => {
|
0xC4 => {
|
||||||
let (target, reg_id) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
||||||
let ptr = Pointer16::try_from(target)?;
|
let ptr = Pointer16::try_from(target)?;
|
||||||
Mnemonic::LES(reg, ptr)
|
Mnemonic::LES(reg, ptr)
|
||||||
}
|
}
|
||||||
0xC5 => {
|
0xC5 => {
|
||||||
let (target, reg_id) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg_id) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
let reg = Register::by_id(ImmediateOperand::Word(reg_id as Word))?;
|
||||||
let ptr = Pointer16::try_from(target)?;
|
let ptr = Pointer16::try_from(target)?;
|
||||||
Mnemonic::LDS(reg, ptr)
|
Mnemonic::LDS(reg, ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
0xC6 => {
|
0xC6 => {
|
||||||
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
Mnemonic::MOV_Ib(target, self.parse_byte()?)
|
Mnemonic::MOV_Ib(target, self.parse_byte()?)
|
||||||
}
|
}
|
||||||
0xC7 => {
|
0xC7 => {
|
||||||
let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
Mnemonic::MOV_Iv(target, self.parse_word()?)
|
Mnemonic::MOV_Iv(target, self.parse_word()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,19 +798,19 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 2
|
// Group 2
|
||||||
0xD0 => {
|
0xD0 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(None)?;
|
||||||
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(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(None)?;
|
||||||
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(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(None)?;
|
||||||
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(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(None)?;
|
||||||
Self::modrm_reg_to_grp2_cl(reg, target)?
|
Self::modrm_reg_to_grp2_cl(reg, target)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,13 +857,13 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 3a
|
// Group 3a
|
||||||
0xF6 => {
|
0xF6 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Byte(0))?
|
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Byte)?
|
||||||
}
|
}
|
||||||
// Group 3b
|
// Group 3b
|
||||||
0xF7 => {
|
0xF7 => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Word(0))?
|
self.modrm_reg_to_grp3(reg, target, InstructionWidth::Word)?
|
||||||
}
|
}
|
||||||
|
|
||||||
0xF8 => Mnemonic::CLC,
|
0xF8 => Mnemonic::CLC,
|
||||||
@@ -864,7 +875,7 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 4
|
// Group 4
|
||||||
0xFE => {
|
0xFE => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
match reg {
|
match reg {
|
||||||
0b0 => Mnemonic::INC_Mod(target),
|
0b0 => Mnemonic::INC_Mod(target),
|
||||||
0b1 => Mnemonic::DEC_Mod(target),
|
0b1 => Mnemonic::DEC_Mod(target),
|
||||||
@@ -874,7 +885,7 @@ impl Disassembler {
|
|||||||
|
|
||||||
// Group 5
|
// Group 5
|
||||||
0xFF => {
|
0xFF => {
|
||||||
let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
match reg {
|
match reg {
|
||||||
0b000 => Mnemonic::INC_Mod(target),
|
0b000 => Mnemonic::INC_Mod(target),
|
||||||
0b001 => Mnemonic::DEC_Mod(target),
|
0b001 => Mnemonic::DEC_Mod(target),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
/// 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! modrm_8b_register {
|
macro_rules! modrm_8b_register {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Byte(0))?;
|
let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Byte))?;
|
||||||
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Byte(reg))?)
|
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Byte(reg))?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ macro_rules! modrm_8b_register {
|
|||||||
/// 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! modrm_16b_register {
|
macro_rules! modrm_16b_register {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Word(reg.into()))?)
|
Mnemonic::$variant(target, Register::by_id(ImmediateOperand::Word(reg.into()))?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ macro_rules! modrm_16b_register {
|
|||||||
/// 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! modrm_sregister {
|
macro_rules! modrm_sregister {
|
||||||
($self:ident, $variant:ident) => {{
|
($self:ident, $variant:ident) => {{
|
||||||
let (target, reg) = $self.parse_modrm_byte(ImmediateOperand::Word(0))?;
|
let (target, reg) = $self.parse_modrm_byte(Some(InstructionWidth::Word))?;
|
||||||
Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
|
Mnemonic::$variant(target, SegmentRegister::by_id(reg)?)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user