chore: split up some structs and add comments
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
//! Internal a.out File abstraction.
|
||||||
|
|
||||||
use std::ffi::{c_uchar, c_ushort};
|
use std::ffi::{c_uchar, c_ushort};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
use core::fmt;
|
//! The main dissembling logic.
|
||||||
use std::{fs::File, io::Read, process::exit};
|
|
||||||
|
|
||||||
use crate::aout::Aout;
|
use crate::aout::Aout;
|
||||||
use crate::instructions::{Displacement, IByte, IWord, MemoryIndex, ModRmTarget, Operand, Pointer};
|
use crate::operands::{Displacement, IByte, IWord, MemoryIndex, ModRmTarget, Operand, Pointer};
|
||||||
use crate::register::{Register, RegisterId, SegmentRegister};
|
use crate::register::{Register, RegisterId, SegmentRegister};
|
||||||
use crate::{
|
use crate::{
|
||||||
Args,
|
Args,
|
||||||
instructions::{Instruction, Mnemonic},
|
instructions::{Instruction, Mnemonic},
|
||||||
};
|
};
|
||||||
use crate::{modrmb, modrms, modrmv};
|
use crate::{modrmb, modrms, modrmv};
|
||||||
|
use core::fmt;
|
||||||
|
use std::{fs::File, io::Read, process::exit};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Generic errors, which are encountered during parsing.
|
/// Generic errors, which are encountered during parsing.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//! Some macros to help with disassembly parsing.
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Generate a Mnemonic for an 8-bit Register from a ModRM byte.
|
/// Generate a Mnemonic for an 8-bit Register from a ModRM byte.
|
||||||
macro_rules! modrmb {
|
macro_rules! modrmb {
|
||||||
|
|||||||
@@ -1,38 +1,11 @@
|
|||||||
|
//! Internal abstraction of the 8086 instructions.
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
operands::{Byte, MemoryIndex, ModRmTarget, Pointer, Word},
|
||||||
|
register::{Register, SegmentRegister},
|
||||||
|
};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use crate::register::{Register, SegmentRegister};
|
|
||||||
|
|
||||||
pub type Byte = u8; // b
|
|
||||||
pub type IByte = i8; // used for displacements of memory access
|
|
||||||
pub type Word = u16; // w or v
|
|
||||||
pub type IWord = i16; // used for displacement of memory access
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[allow(dead_code)]
|
|
||||||
/// Encodes either Byte- or Word-sized operands.
|
|
||||||
pub enum Operand {
|
|
||||||
Byte(Byte),
|
|
||||||
Word(Word),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Operand {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Byte(byte) => write!(f, "{}", byte),
|
|
||||||
Self::Word(word) => write!(f, "{}", word),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::LowerHex for Operand {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Byte(b) => fmt::LowerHex::fmt(b, f),
|
|
||||||
Self::Word(v) => fmt::LowerHex::fmt(v, f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// A single 'line' of executable ASM is called an Instruction, which
|
/// A single 'line' of executable ASM is called an Instruction, which
|
||||||
@@ -561,108 +534,3 @@ impl fmt::Display for Mnemonic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
/// ModRM byte can either target a memory location or some register
|
|
||||||
pub enum ModRmTarget {
|
|
||||||
Memory(MemoryIndex),
|
|
||||||
Register(Register),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for ModRmTarget {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Memory(idx) => write!(f, "{}", idx),
|
|
||||||
Self::Register(reg) => write!(f, "{}", reg),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
/// Memory displacements are signed versions of u8 and u16.
|
|
||||||
/// Encodes either Byte- or Word-sized operands.
|
|
||||||
pub enum Displacement {
|
|
||||||
IByte(i8),
|
|
||||||
IWord(i16),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::LowerHex for Displacement {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::IByte(b) => fmt::LowerHex::fmt(b, f),
|
|
||||||
Self::IWord(v) => fmt::LowerHex::fmt(v, f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Displacement {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::IByte(b) => {
|
|
||||||
if *b > 0 {
|
|
||||||
write!(f, " + {:#x}", b)
|
|
||||||
} else {
|
|
||||||
write!(f, " - {:#x}", b * -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Self::IWord(w) => {
|
|
||||||
if *w > 0 {
|
|
||||||
write!(f, " + {:#x}", w)
|
|
||||||
} else {
|
|
||||||
write!(f, " - {:#x}", w * -1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A memory index operand is usually created by ModRM bytes or words.
|
|
||||||
/// e.g. [bx+si]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct MemoryIndex {
|
|
||||||
pub base: Option<Register>,
|
|
||||||
pub index: Option<Register>,
|
|
||||||
pub displacement: Option<Displacement>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for MemoryIndex {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match &self.base {
|
|
||||||
Some(base) => match &self.index {
|
|
||||||
Some(index) => match &self.displacement {
|
|
||||||
Some(displacement) => {
|
|
||||||
write!(f, "[{} + {}{}]", base, index, displacement)
|
|
||||||
}
|
|
||||||
None => write!(f, "[{} + {}]", base, index),
|
|
||||||
},
|
|
||||||
None => match &self.displacement {
|
|
||||||
Some(displacement) => write!(f, "[{}{}]", base, displacement),
|
|
||||||
None => write!(f, "[{}]", base),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
None => match &self.index {
|
|
||||||
Some(index) => match &self.displacement {
|
|
||||||
Some(displacement) => write!(f, "[{}{}]", index, displacement),
|
|
||||||
None => write!(f, "[{}]", index),
|
|
||||||
},
|
|
||||||
None => match &self.displacement {
|
|
||||||
Some(displacement) => write!(f, "[{:#x}]", displacement),
|
|
||||||
None => panic!("Memory Index without base, index and displacement"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
/// 32-bit segment:offset pointer (e.g. for CALL instruction)
|
|
||||||
pub struct Pointer {
|
|
||||||
pub segment: Word,
|
|
||||||
pub offset: Word,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for Pointer {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(f, "{}:{}", self.segment, self.offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod aout;
|
|||||||
mod disasm;
|
mod disasm;
|
||||||
mod disasm_macros;
|
mod disasm_macros;
|
||||||
mod instructions;
|
mod instructions;
|
||||||
|
mod operands;
|
||||||
mod register;
|
mod register;
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
|
|||||||
141
src/operands.rs
Normal file
141
src/operands.rs
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
//! All types which a Mnemonic can have as some kind of operand.
|
||||||
|
//! This includes things such as immediates, ModRM byte targets, etc. etc.
|
||||||
|
|
||||||
|
use crate::register::Register;
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
pub type Byte = u8; // b
|
||||||
|
pub type IByte = i8; // used for displacements of memory access
|
||||||
|
pub type Word = u16; // w or v
|
||||||
|
pub type IWord = i16; // used for displacement of memory access
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
/// Encodes either Byte- or Word-sized operands.
|
||||||
|
pub enum Operand {
|
||||||
|
Byte(Byte),
|
||||||
|
Word(Word),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Operand {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Byte(byte) => write!(f, "{}", byte),
|
||||||
|
Self::Word(word) => write!(f, "{}", word),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::LowerHex for Operand {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Byte(b) => fmt::LowerHex::fmt(b, f),
|
||||||
|
Self::Word(v) => fmt::LowerHex::fmt(v, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// ModRM byte can either target a memory location or some register
|
||||||
|
pub enum ModRmTarget {
|
||||||
|
Memory(MemoryIndex),
|
||||||
|
Register(Register),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ModRmTarget {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Memory(idx) => write!(f, "{}", idx),
|
||||||
|
Self::Register(reg) => write!(f, "{}", reg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// Memory displacements are signed versions of u8 and u16.
|
||||||
|
/// Encodes either Byte- or Word-sized operands.
|
||||||
|
pub enum Displacement {
|
||||||
|
IByte(i8),
|
||||||
|
IWord(i16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::LowerHex for Displacement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::IByte(b) => fmt::LowerHex::fmt(b, f),
|
||||||
|
Self::IWord(v) => fmt::LowerHex::fmt(v, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Displacement {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::IByte(b) => {
|
||||||
|
if *b > 0 {
|
||||||
|
write!(f, " + {:#x}", b)
|
||||||
|
} else {
|
||||||
|
write!(f, " - {:#x}", b * -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::IWord(w) => {
|
||||||
|
if *w > 0 {
|
||||||
|
write!(f, " + {:#x}", w)
|
||||||
|
} else {
|
||||||
|
write!(f, " - {:#x}", w * -1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A memory index operand is usually created by ModRM bytes or words.
|
||||||
|
/// e.g. [bx+si]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct MemoryIndex {
|
||||||
|
pub base: Option<Register>,
|
||||||
|
pub index: Option<Register>,
|
||||||
|
pub displacement: Option<Displacement>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MemoryIndex {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match &self.base {
|
||||||
|
Some(base) => match &self.index {
|
||||||
|
Some(index) => match &self.displacement {
|
||||||
|
Some(displacement) => {
|
||||||
|
write!(f, "[{} + {}{}]", base, index, displacement)
|
||||||
|
}
|
||||||
|
None => write!(f, "[{} + {}]", base, index),
|
||||||
|
},
|
||||||
|
None => match &self.displacement {
|
||||||
|
Some(displacement) => write!(f, "[{}{}]", base, displacement),
|
||||||
|
None => write!(f, "[{}]", base),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => match &self.index {
|
||||||
|
Some(index) => match &self.displacement {
|
||||||
|
Some(displacement) => write!(f, "[{}{}]", index, displacement),
|
||||||
|
None => write!(f, "[{}]", index),
|
||||||
|
},
|
||||||
|
None => match &self.displacement {
|
||||||
|
Some(displacement) => write!(f, "[{:#x}]", displacement),
|
||||||
|
None => panic!("Memory Index without base, index and displacement"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
/// 32-bit segment:offset pointer (e.g. for CALL instruction)
|
||||||
|
pub struct Pointer {
|
||||||
|
pub segment: Word,
|
||||||
|
pub offset: Word,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Pointer {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "{}:{}", self.segment, self.offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use core::fmt;
|
//! Internal abstraction of all 8086 registers for disassembly.
|
||||||
|
|
||||||
use crate::instructions::Operand;
|
use crate::operands::Operand;
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|||||||
Reference in New Issue
Block a user