diff --git a/src/disasm.rs b/src/disasm.rs index c22ac3d..0188799 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -74,8 +74,10 @@ impl Disassembler { /// Parse a single byte of binary, return it and advance the offset. /// Returns the read byte. pub fn parse_byte(&mut self) -> u8 { + // advance to operand self.offset += 1; let byte = self.text[self.offset]; + // jump to right after operand self.offset += 1; self.instruction.raw.push(byte); byte @@ -84,9 +86,11 @@ impl Disassembler { /// Parse a single word of binary, return it and advance the offset. /// Returns the read word. pub fn parse_word(&mut self) -> u16 { + // advance to operand self.offset += 1; let byte1 = self.text[self.offset]; let byte2 = self.text[self.offset + 1]; + // jump right after operand self.offset += 2; self.instruction.raw.push(byte1); self.instruction.raw.push(byte2); @@ -94,75 +98,84 @@ impl Disassembler { } /// Parse a single modrm byte, return the resulting MemoryIndex and advance the offset. - /// Returns the parsed modrm memory access, as well as all read raw bytes - pub fn parse_modrm_byte(&mut self) -> MemoryIndex { + /// Returns the parsed modrm memory access and the source register + pub fn parse_modrm_byte_to_memindex(&mut self) -> (MemoryIndex, Register) { + // advance to operand + self.offset += 1; + let modrm = self.text[self.offset]; + self.instruction.raw.push(modrm); + // jump right after operand + self.offset += 1; + // Calculate ModRM byte with bitmask - let opcode = self.text[self.offset]; - let modulo = opcode >> 6; - let reg = (opcode >> 3) & 7; - let rm = opcode & 7; + let modulo = modrm >> 6; + let reg = (modrm >> 3) & 7; + let rm = modrm & 7; let displacement = match modulo { - 0 => { - if rm == 6 { - // XXX: handle special case - panic!("Handle modulo == 0, rm == 6"); + 0b00 => { + if rm == 0b110 { + log::debug!("Additional word during ModRM parsing was read with mod 0."); + Some(Displacement::Word(self.parse_word())) + } else { + None } + } + 0b01 => { + log::debug!("Additional byte during ModRM parsing was read."); + Some(Displacement::Byte(self.parse_byte())) + } + 0b10 => { + log::debug!("Additional word during ModRM parsing was read."); + Some(Displacement::Word(self.parse_word())) + } + 0b11 => { + // XXX is this correct? + log::debug!( + "No displacement, as reg to reg - maybe some implementation is missing here" + ); None } - 1 => { - // self.offset += 2; // one additional byte was read - let byte = self.parse_byte(); - log::debug!("Additional byte during ModRM parsing was read."); - Some(Displacement::Byte(byte)) - } - 2 => { - // self.offset += 3; // two additional bytes (word) was read - let word = self.parse_word(); - log::debug!("Additional two bytes during ModRM parsing was read."); - Some(Displacement::Word(word)) - } - 3 => panic!("TODO: handle modulo == 3"), _ => panic!("Invalid ModRM byte encountered"), }; let index = match rm { - 0 => MemoryIndex { + 0b0000 => MemoryIndex { base: Some(Register::BX), index: Some(Register::SI), displacement, }, - 1 => MemoryIndex { + 0b0001 => MemoryIndex { base: Some(Register::BX), index: Some(Register::DI), displacement, }, - 2 => MemoryIndex { + 0b0010 => MemoryIndex { base: Some(Register::BP), index: Some(Register::SI), displacement, }, - 3 => MemoryIndex { + 0b0011 => MemoryIndex { base: Some(Register::BP), index: Some(Register::DI), displacement, }, - 4 => MemoryIndex { + 0b0100 => MemoryIndex { base: None, index: Some(Register::SI), displacement, }, - 5 => MemoryIndex { + 0b0101 => MemoryIndex { base: None, index: Some(Register::DI), displacement, }, - 6 => MemoryIndex { + 0b0110 => MemoryIndex { base: Some(Register::BP), index: None, displacement, }, - 7 => MemoryIndex { + 0b0111 => MemoryIndex { base: Some(Register::BX), index: None, displacement, @@ -170,7 +183,7 @@ impl Disassembler { _ => panic!("Invalid ModRM byte encountered"), }; - index + (index, Register::by_id(reg)) } /// Decode instructions from the text section of the provided binary @@ -193,7 +206,8 @@ impl Disassembler { self.instruction.opcode = match opcode { // ADD 0x00 => { - Opcode::ADD_EbGb(self.parse_modrm_byte(), Register::by_id(self.parse_byte())) + let (idx, reg) = self.parse_modrm_byte_to_memindex(); + Opcode::ADD_EbGb(idx, reg) } // INT 0xCD => Opcode::INT(ImmediateByte(self.parse_byte())), diff --git a/src/instructions.rs b/src/instructions.rs index 57ec2fc..882d4b0 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -61,6 +61,7 @@ impl fmt::Display for Opcode { } /// Registers of a 8086 processor +/// -x are 16bit, -l are 8bit #[derive(Debug, Clone)] #[allow(dead_code)] pub enum Register {