From 7d5f891a93efd4fed5b1c0fd1d9bf8c8b608062d Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Tue, 17 Jun 2025 19:57:00 +0900 Subject: [PATCH] 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. --- src/disasm.rs | 73 +++++++++++++++++++++++++------------------- src/disasm_macros.rs | 6 ++-- 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/src/disasm.rs b/src/disasm.rs index b0974a8..4d87bf4 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -14,6 +14,13 @@ use crate::{modrm_8b_register, modrm_16b_register, modrm_sregister}; use core::fmt; 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)] /// Generic errors, which are encountered during parsing. pub enum DisasmError { @@ -240,7 +247,7 @@ impl Disassembler { /// or even mnemonic in the group-type instructions. fn parse_modrm_byte( &mut self, - register_width: ImmediateOperand, + register_width: Option, ) -> Result<(ModRmTarget, RegisterId), DisasmError> { let modrm = self.parse_byte()?; @@ -292,13 +299,17 @@ impl Disassembler { log::debug!( "ModRM selected Register to Register: ({rm:#b}) to/from RegID ({reg:#b})" ); - let target = match register_width { - ImmediateOperand::Byte(_) => { - ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?) - } - ImmediateOperand::Word(_) => { - ModRmTarget::Register(Register::by_id(ImmediateOperand::Word(rm as Word))?) + let target = if let Some(width) = register_width { + match width { + InstructionWidth::Byte => { + ModRmTarget::Register(Register::by_id(ImmediateOperand::Byte(rm))?) + } + 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)); } @@ -359,9 +370,9 @@ impl Disassembler { fn modrm_reg_to_grp1( reg: u8, target: ModRmTarget, - instruction_width: ImmediateOperand, + val: ImmediateOperand, ) -> Result { - match instruction_width { + match val { ImmediateOperand::Byte(b) => match reg { 0b000 => Ok(Mnemonic::ADD_Ib(target, b)), 0b001 => Ok(Mnemonic::OR_Ib(target, b)), @@ -432,12 +443,12 @@ impl Disassembler { &mut self, reg: u8, target: ModRmTarget, - width: ImmediateOperand, + width: InstructionWidth, ) -> Result { match reg { 0b000 => match width { - ImmediateOperand::Byte(_) => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)), - ImmediateOperand::Word(_) => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)), + InstructionWidth::Byte => Ok(Mnemonic::TEST_Ib(target, self.parse_byte()?)), + InstructionWidth::Word => Ok(Mnemonic::TEST_Iv(target, self.parse_word()?)), }, // 0b001 => // unused 0b010 => Ok(Mnemonic::NOT(target)), @@ -639,24 +650,24 @@ impl Disassembler { // Group 1 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()?; Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? } 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()?; Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Word(imm))? } 0x82 => { // 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()?; Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? } 0x83 => { // 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()?; Self::modrm_reg_to_grp1(reg, target, ImmediateOperand::Byte(imm))? } @@ -677,7 +688,7 @@ impl Disassembler { 0x8D => modrm_16b_register!(self, LEA), 0x8F => { - let (target, _) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; + let (target, _) = self.parse_modrm_byte(Some(InstructionWidth::Word))?; let mem = match target { ModRmTarget::Memory(idx) => idx, _ => { @@ -753,24 +764,24 @@ impl Disassembler { 0xC3 => Mnemonic::RET, 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 ptr = Pointer16::try_from(target)?; Mnemonic::LES(reg, ptr) } 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 ptr = Pointer16::try_from(target)?; Mnemonic::LDS(reg, ptr) } 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()?) } 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()?) } @@ -787,19 +798,19 @@ impl Disassembler { // Group 2 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)? } 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)? } 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)? } 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)? } @@ -846,13 +857,13 @@ impl Disassembler { // Group 3a 0xF6 => { - let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; - self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Byte(0))? + 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(ImmediateOperand::Word(0))?; - self.modrm_reg_to_grp3(reg, target, ImmediateOperand::Word(0))? + let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?; + self.modrm_reg_to_grp3(reg, target, InstructionWidth::Word)? } 0xF8 => Mnemonic::CLC, @@ -864,7 +875,7 @@ impl Disassembler { // Group 4 0xFE => { - let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Byte(0))?; + let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Byte))?; match reg { 0b0 => Mnemonic::INC_Mod(target), 0b1 => Mnemonic::DEC_Mod(target), @@ -874,7 +885,7 @@ impl Disassembler { // Group 5 0xFF => { - let (target, reg) = self.parse_modrm_byte(ImmediateOperand::Word(0))?; + let (target, reg) = self.parse_modrm_byte(Some(InstructionWidth::Word))?; match reg { 0b000 => Mnemonic::INC_Mod(target), 0b001 => Mnemonic::DEC_Mod(target), diff --git a/src/disasm_macros.rs b/src/disasm_macros.rs index c0e1bc2..3c5b1f1 100644 --- a/src/disasm_macros.rs +++ b/src/disasm_macros.rs @@ -4,7 +4,7 @@ /// Generate a Mnemonic for an 8-bit Register from a ModRM byte. macro_rules! modrm_8b_register { ($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))?) }}; } @@ -13,7 +13,7 @@ macro_rules! modrm_8b_register { /// Generate a Mnemonic for a 16-bit Register from a ModRM byte. macro_rules! modrm_16b_register { ($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()))?) }}; } @@ -22,7 +22,7 @@ macro_rules! modrm_16b_register { /// Generate a Mnemonic for a 16-bit Segment Register from a ModRM byte. macro_rules! modrm_sregister { ($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)?) }}; }