fix: fix modrm parsing
Previously the wrong register was read in, now the byte is deconstructed correctly
This commit is contained in:
@@ -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())),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user