ft: Implement memory pointer (Mp) operand
This commit is contained in:
@@ -19,6 +19,7 @@ pub enum DisasmError {
|
||||
NoFile(Option<String>),
|
||||
IoError(std::io::Error),
|
||||
OpcodeUndefined(u8),
|
||||
IndexOutOfBounds(usize),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for DisasmError {
|
||||
@@ -37,6 +38,7 @@ impl fmt::Display for DisasmError {
|
||||
"Instruction '{:#x} is considered undefined by the Spec",
|
||||
opcode
|
||||
),
|
||||
DisasmError::IndexOutOfBounds(msg) => write!(f, "Out of bounds read at {}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,7 +69,7 @@ fn path_to_buf(args: &Args) -> Result<Vec<u8>, DisasmError> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Disassembler {
|
||||
pub struct Disassembler {
|
||||
pub offset: usize, // the current offset in the disasm process
|
||||
pub text: Vec<u8>, // the aout binary
|
||||
pub instruction: Instruction, // the instruction, which is currently being parsed
|
||||
@@ -97,6 +99,7 @@ impl Disassembler {
|
||||
pub fn parse_word(&mut self) -> u16 {
|
||||
// advance to operand
|
||||
self.offset += 1;
|
||||
// XXX: wrap in Result<>
|
||||
let byte1 = self.text[self.offset];
|
||||
let byte2 = self.text[self.offset + 1];
|
||||
// jump onto last operand
|
||||
@@ -327,6 +330,15 @@ impl Disassembler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an Mp Operand (Memory Pointer).
|
||||
/// An Mp is a ModRM byte with the `reg` bits ignored and an additional
|
||||
/// 2 words parsed for a `Pointer` type.
|
||||
pub fn modrm_mp(&mut self) -> Result<(ModRmTarget, Pointer), DisasmError> {
|
||||
let (target, _) = self.parse_modrm_byte(Operand::Byte(0));
|
||||
let ptr = Pointer::new(self)?;
|
||||
Ok((target, ptr))
|
||||
}
|
||||
|
||||
/// Decode instructions from the text section of the provided binary
|
||||
pub fn decode_instructions(&mut self) -> Result<Vec<Instruction>, DisasmError> {
|
||||
// naive approach:
|
||||
@@ -602,7 +614,14 @@ impl Disassembler {
|
||||
0xC2 => Mnemonic::RET_Iw(self.parse_word()),
|
||||
0xC3 => Mnemonic::RET,
|
||||
|
||||
0xC4..=0xC5 => todo!("LES and LDS not yet implemented"),
|
||||
0xC4 => {
|
||||
let (target, ptr) = self.modrm_mp()?;
|
||||
Mnemonic::LES(target, ptr)
|
||||
}
|
||||
0xC5 => {
|
||||
let (target, ptr) = self.modrm_mp()?;
|
||||
Mnemonic::LDS(target, ptr)
|
||||
}
|
||||
|
||||
0xC6 => {
|
||||
let (target, _) = self.parse_modrm_byte(Operand::Byte(0));
|
||||
@@ -664,16 +683,7 @@ impl Disassembler {
|
||||
0xE8 => Mnemonic::CALL_v(self.parse_j_word()),
|
||||
|
||||
0xE9 => Mnemonic::JMP_v(self.parse_j_word()),
|
||||
0xEA => Mnemonic::JMP_p(Pointer {
|
||||
raw: DWord::from_le_bytes([
|
||||
self.text[self.offset],
|
||||
self.text[self.offset + 1],
|
||||
self.text[self.offset + 2],
|
||||
self.text[self.offset + 3],
|
||||
]),
|
||||
segment: self.parse_word(),
|
||||
offset: self.parse_word(),
|
||||
}),
|
||||
0xEA => Mnemonic::JMP_p(Pointer::new(self)?),
|
||||
0xEB => Mnemonic::JMP_b(self.parse_j_byte()),
|
||||
|
||||
0xEC => Mnemonic::IN_ALDX,
|
||||
@@ -722,9 +732,9 @@ impl Disassembler {
|
||||
0b000 => Mnemonic::INC_Mod(target),
|
||||
0b001 => Mnemonic::DEC_Mod(target),
|
||||
0b010 => Mnemonic::CALL_Mod(target),
|
||||
0b011 => todo!("Implement CALL Mp"),
|
||||
0b011 => Mnemonic::CALL_Mp(target, Pointer::new(self)?),
|
||||
0b100 => Mnemonic::JMP_Mod(target),
|
||||
0b101 => todo!("Implement JMP Mp"),
|
||||
0b101 => Mnemonic::JMP_Mp(target, Pointer::new(self)?),
|
||||
0b110 => Mnemonic::PUSH_Mod(target),
|
||||
// 0b111 => unused
|
||||
_ => panic!("Illegal Group 5 mnemonic"),
|
||||
|
||||
Reference in New Issue
Block a user