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.
|
/// 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
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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
|
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"),
|
_ => 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())),
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user