fix: fix modrm parsing

Previously the wrong register was read in, now
the byte is deconstructed correctly
This commit is contained in:
2025-05-12 15:38:20 +09:00
parent 1dcd231f51
commit 317b5e5db4
2 changed files with 48 additions and 33 deletions

View File

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

View File

@@ -61,6 +61,7 @@ impl fmt::Display for Opcode {
} }
/// Registers of a 8086 processor /// Registers of a 8086 processor
/// -x are 16bit, -l are 8bit
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[allow(dead_code)] #[allow(dead_code)]
pub enum Register { pub enum Register {