diff --git a/src/disasm.rs b/src/disasm.rs index 692c588..ade724e 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -8,7 +8,7 @@ use crate::{ Args, instructions::{Instruction, Mnemonic}, }; -use crate::{modrmb, modrmgprb, modrmgprv, modrms, modrmv}; +use crate::{modrmb, modrmgpr1b, modrmgpr1v, modrms, modrmv}; #[derive(Debug)] /// Generic errors, which are encountered during parsing. @@ -143,7 +143,7 @@ impl Disassembler { displacement = Some(Operand::Word(self.parse_word())); } 0b11 => { - log::debug!("ModRM (0b{:b}) to/from Register (0b{: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) let target = match width { Operand::Byte(_) => ModRmTarget::Register(Register::by_id(Operand::Byte(rm))), @@ -368,7 +368,7 @@ impl Disassembler { 0x5E => Mnemonic::POP_R(Register::SI), 0x5F => Mnemonic::POP_R(Register::DI), - 0x60..=0x6F => panic!("0x06 to 0x06F is considered undefined."), + 0x60..=0x6F => panic!("{:#x} is considered undefined", opcode), 0x70 => Mnemonic::JO(self.parse_byte()), 0x71 => Mnemonic::JNO(self.parse_byte()), @@ -387,9 +387,10 @@ impl Disassembler { 0x7E => Mnemonic::JLE(self.parse_byte()), 0x7F => Mnemonic::JG(self.parse_byte()), - 0x80 => modrmgprb!(self), - 0x81 => modrmgprv!(self), - 0x82 => modrmgprb!(self), // same as 0x80 + // Group 1 + 0x80 => modrmgpr1b!(self), + 0x81 => modrmgpr1v!(self), + 0x82 => modrmgpr1b!(self), // same as 0x80 0x83 => panic!("Sign extented GPR1 not yet implemented"), 0x84 => modrmb!(self, TEST), @@ -440,9 +441,55 @@ impl Disassembler { 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 => panic!("{:#x} is considered in undefined", opcode), + + 0xC2 => Mnemonic::RETIw(self.parse_word()), + 0xC3 => Mnemonic::RET, + + 0xC4..=0xC5 => panic!("{:#x} not yet implemented (LDS or LES)", opcode), + + 0xC8..=0xC9 => panic!("{:#x} is considered in undefined", opcode), + 0xCD => Mnemonic::INT(self.parse_byte()), - 0xBB => Mnemonic::MOV_BXIv(self.parse_word()), + // Group 3 _ => { eprintln!("Encountered unknown instruction '0x{:x}'", opcode); eprintln!("Offset might be misaligned and data is being interpreted."); diff --git a/src/disasm_macros.rs b/src/disasm_macros.rs index e4f47bb..fd4a60a 100644 --- a/src/disasm_macros.rs +++ b/src/disasm_macros.rs @@ -29,7 +29,7 @@ macro_rules! modrms { /// Generate the resulting Mnemonic from a GPR instruction with Byte-sized /// Immediate, encoded in a ModRM byte. /// GPR always has an imm value as second operand. -macro_rules! modrmgprb { +macro_rules! modrmgpr1b { ($self:ident) => {{ let (target, reg) = $self.parse_modrm_byte(Operand::Byte(0)); let imm = $self.parse_byte(); @@ -41,7 +41,7 @@ macro_rules! modrmgprb { /// Generate the resulting Mnemonic from a GPR instruction with Word-sized /// Immediate, encoded in a ModRM byte. /// GPR always has an imm value as second operand. -macro_rules! modrmgprv { +macro_rules! modrmgpr1v { ($self:ident) => {{ let (target, reg) = $self.parse_modrm_byte(Operand::Word(0)); let imm = $self.parse_word(); diff --git a/src/instructions.rs b/src/instructions.rs index 12e8c0d..ac4fd50 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -160,6 +160,8 @@ pub enum Mnemonic { JG(Byte), // TEST TEST(ModRmTarget, Register), + TEST_ALIb(Byte), + TEST_AXIv(Word), //XHCG XHCG(ModRmTarget, Register), XCHG_AX(Register), // from AX @@ -168,7 +170,27 @@ pub enum Mnemonic { MOV_ToReg(ModRmTarget, Register), MOV_FromSReg(ModRmTarget, SegmentRegister), MOV_ToSReg(ModRmTarget, SegmentRegister), + MOV_AL0b(Byte), + MOV_AX0v(Word), + MOV_0bAL(Byte), + MOV_0vAX(Word), + + MOV_ALIb(Byte), + MOV_CLIb(Byte), + MOV_DLIb(Byte), + MOV_BLIb(Byte), + MOV_AHIb(Byte), + MOV_CHIb(Byte), + MOV_DHIb(Byte), + MOV_BHIb(Byte), + MOV_AXIv(Word), + MOV_CXIv(Word), + MOV_DXIv(Word), MOV_BXIv(Word), + MOV_SPIv(Word), + MOV_BPIv(Word), + MOV_SIIv(Word), + MOV_DIIv(Word), // LEA LEA(ModRmTarget, Register), // Sign extensions @@ -183,6 +205,23 @@ pub enum Mnemonic { POPF, SAHF, LAHF, + // String Byte Operations + MOVSB, + MOVSW, + CMPSB, + CMPSW, + STOSB, + STOSW, + LODSB, + LODSW, + SCASB, + SCASW, + // RET + RETIw(Word), + RET, + // Load ES/DS Register + LES(ModRmTarget), + LDS(ModRmTarget), // INT INT(Byte), }