fix: fix displacement parsing
1. correctly return when only displacement in modrm mem adressing Previously the disassmbler wouldn't stop if only a displacement value should be used without any base or offset index. 2. Displacement can be negative, so use the signed version where applicable
This commit is contained in:
@@ -2,7 +2,7 @@ use core::fmt;
|
||||
use std::{fs::File, io::Read, process::exit};
|
||||
|
||||
use crate::aout::Aout;
|
||||
use crate::instructions::{MemoryIndex, ModRmTarget, Operand, Pointer};
|
||||
use crate::instructions::{Displacement, MemoryIndex, ModRmTarget, Operand, Pointer};
|
||||
use crate::register::{Register, RegisterId, SegmentRegister};
|
||||
use crate::{
|
||||
Args,
|
||||
@@ -123,7 +123,7 @@ impl Disassembler {
|
||||
let (mode, reg, rm) = Self::deconstruct_modrm_byte(modrm);
|
||||
|
||||
log::debug!(
|
||||
"0x{:04x} deconstructed into: 0b{:b}, 0b{:b}, 0b{:b}",
|
||||
"{:#04x} deconstructed into: {:#b}, {:#b}, {:#b}",
|
||||
modrm,
|
||||
mode,
|
||||
reg,
|
||||
@@ -135,18 +135,26 @@ impl Disassembler {
|
||||
0b00 => {
|
||||
if rm == 0b110 {
|
||||
log::debug!("Additional word during ModRM parsing was read with mod 0.");
|
||||
displacement = Some(Operand::Word(self.parse_word()));
|
||||
displacement = Some(Displacement::IWord(self.parse_word() as i16));
|
||||
return (
|
||||
ModRmTarget::Memory(MemoryIndex {
|
||||
base: None,
|
||||
index: None,
|
||||
displacement,
|
||||
}),
|
||||
reg,
|
||||
);
|
||||
} else {
|
||||
displacement = None;
|
||||
}
|
||||
}
|
||||
0b01 => {
|
||||
log::debug!("Additional byte during ModRM parsing was read.");
|
||||
displacement = Some(Operand::Byte(self.parse_byte()))
|
||||
displacement = Some(Displacement::IByte(self.parse_byte() as i8))
|
||||
}
|
||||
0b10 => {
|
||||
log::debug!("Additional word during ModRM parsing was read.");
|
||||
displacement = Some(Operand::Word(self.parse_word()));
|
||||
displacement = Some(Displacement::IWord(self.parse_word() as i16));
|
||||
}
|
||||
0b11 => {
|
||||
log::debug!("ModRM ({:#b}) to/from Register ({:#b})", rm, reg);
|
||||
@@ -213,9 +221,9 @@ impl Disassembler {
|
||||
/// Group 1 always have an ModRM target (all modrm bits, without reg) as
|
||||
/// first and an imm value as second operand (which has to be parsed before
|
||||
/// call to this function), but is available in both Byte and Word length.
|
||||
pub fn modrm_reg_to_grp1(reg: u8, target: ModRmTarget, imm: Operand) -> Mnemonic {
|
||||
pub fn modrm_reg_to_grp1(reg: u8, target: ModRmTarget, imm: Displacement) -> Mnemonic {
|
||||
match imm {
|
||||
Operand::Byte(b) => match reg {
|
||||
Displacement::IByte(b) => match reg {
|
||||
0b000 => Mnemonic::ADD_Ib(target, b),
|
||||
0b001 => Mnemonic::OR_Ib(target, b),
|
||||
0b010 => Mnemonic::ADC_Ib(target, b),
|
||||
@@ -226,7 +234,7 @@ impl Disassembler {
|
||||
0b111 => Mnemonic::CMP_Ib(target, b),
|
||||
_ => panic!("Illegal Group 1 mnemonic"),
|
||||
},
|
||||
Operand::Word(w) => match reg {
|
||||
Displacement::IWord(w) => match reg {
|
||||
0b000 => Mnemonic::ADD_Iv(target, w),
|
||||
0b001 => Mnemonic::OR_Iv(target, w),
|
||||
0b010 => Mnemonic::ADC_Iv(target, w),
|
||||
@@ -454,25 +462,25 @@ impl Disassembler {
|
||||
// Group 1
|
||||
0x80 => {
|
||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0));
|
||||
let imm = self.parse_byte();
|
||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))
|
||||
let imm = self.parse_byte() as i8;
|
||||
Self::modrm_reg_to_grp1(reg, target, Displacement::IByte(imm))
|
||||
}
|
||||
0x81 => {
|
||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0));
|
||||
let imm = self.parse_word();
|
||||
Self::modrm_reg_to_grp1(reg, target, Operand::Word(imm))
|
||||
let imm = self.parse_word() as i16;
|
||||
Self::modrm_reg_to_grp1(reg, target, Displacement::IWord(imm))
|
||||
}
|
||||
0x82 => {
|
||||
// same as 0x80
|
||||
let (target, reg) = self.parse_modrm_byte(Operand::Byte(0));
|
||||
let imm = self.parse_byte();
|
||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))
|
||||
let imm = self.parse_byte() as i8;
|
||||
Self::modrm_reg_to_grp1(reg, target, Displacement::IByte(imm))
|
||||
}
|
||||
0x83 => {
|
||||
// byte extended version
|
||||
let (target, reg) = self.parse_modrm_byte(Operand::Word(0));
|
||||
let imm = self.parse_byte();
|
||||
Self::modrm_reg_to_grp1(reg, target, Operand::Byte(imm))
|
||||
let imm = self.parse_byte() as i8;
|
||||
Self::modrm_reg_to_grp1(reg, target, Displacement::IByte(imm))
|
||||
}
|
||||
|
||||
0x84 => modrmb!(self, TEST),
|
||||
|
||||
Reference in New Issue
Block a user