ft: add debug script
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
/target
|
/target
|
||||||
|
test.out
|
||||||
|
|||||||
43
gen.py
Normal file
43
gen.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
### Python script to generate specific instructions for testing
|
||||||
|
import struct
|
||||||
|
|
||||||
|
output_file = "test.out"
|
||||||
|
|
||||||
|
machine_code = bytes([
|
||||||
|
0xC5, 0x06, 0x34, 0x12, 0xFF, 0x1E, 0x34, 0x12, 0x9A, 0x78, 0x56, 0x34, 0x12, 0xEA, 0x78, 0x56, 0x34, 0x12, 0xFF, 0x1E, 0x34, 0x12, 0xFF, 0x2E, 0x34, 0x12
|
||||||
|
])
|
||||||
|
|
||||||
|
magic = b'\x01\x03'
|
||||||
|
flags = 0x20
|
||||||
|
cpu = 0x0
|
||||||
|
hdrlen = 0x20
|
||||||
|
unused = 0x00
|
||||||
|
version = 0
|
||||||
|
text = len(machine_code)
|
||||||
|
data = 0x00 # 4b
|
||||||
|
bss = 0x00 # 4b
|
||||||
|
entry = 0x00 # 4b
|
||||||
|
total = text + data + bss + entry # 4b
|
||||||
|
syms = 0x00 # 4b
|
||||||
|
|
||||||
|
# pack with LE
|
||||||
|
header = struct.pack('<2sBBBBHLLLLLL',
|
||||||
|
magic,
|
||||||
|
flags,
|
||||||
|
cpu,
|
||||||
|
hdrlen,
|
||||||
|
unused,
|
||||||
|
version,
|
||||||
|
text,
|
||||||
|
data,
|
||||||
|
bss,
|
||||||
|
entry,
|
||||||
|
total,
|
||||||
|
syms
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(output_file, "wb") as f:
|
||||||
|
f.write(header + machine_code)
|
||||||
|
|
||||||
|
print(f"a.out written to: {output_file}")
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ impl fmt::Display for DisasmError {
|
|||||||
DisasmError::IoError(msg) => write!(f, "{}", msg),
|
DisasmError::IoError(msg) => write!(f, "{}", msg),
|
||||||
DisasmError::OpcodeUndefined(opcode) => write!(
|
DisasmError::OpcodeUndefined(opcode) => write!(
|
||||||
f,
|
f,
|
||||||
"Error (Undefined Opcode). '{:#x} is considered undefined by the Spec",
|
"Error (Undefined Opcode). '{:#04x} is considered undefined by the Spec",
|
||||||
opcode
|
opcode
|
||||||
),
|
),
|
||||||
DisasmError::IllegalGroupMnemonic(group, mnemonic) => write!(
|
DisasmError::IllegalGroupMnemonic(group, mnemonic) => write!(
|
||||||
@@ -244,6 +244,8 @@ impl Disassembler {
|
|||||||
rm
|
rm
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// not unused, but overwritten before first read
|
||||||
|
#[allow(unused_assignments)]
|
||||||
let mut displacement = None;
|
let mut displacement = None;
|
||||||
match mode {
|
match mode {
|
||||||
0b00 => {
|
0b00 => {
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
//! All types which a Mnemonic can have as some kind of operand.
|
//! All types which a Mnemonic can have as some kind of operand.
|
||||||
//! This includes things such as immediates, ModRM byte targets, etc. etc.
|
//! This includes things such as immediates, ModRM byte targets, etc. etc.
|
||||||
|
|
||||||
|
// used in doc, but not code
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use crate::register::SegmentRegister;
|
||||||
|
|
||||||
use crate::{disasm::DisasmError, register::Register};
|
use crate::{disasm::DisasmError, register::Register};
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
@@ -39,7 +43,8 @@ impl fmt::LowerHex for Operand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
/// ModRM byte can either target a memory location or some register.
|
/// ModRM byte can either target a [`MemoryIndex`] (location in memory) or some
|
||||||
|
/// [`Register`].
|
||||||
pub enum ModRmTarget {
|
pub enum ModRmTarget {
|
||||||
Memory(MemoryIndex),
|
Memory(MemoryIndex),
|
||||||
Register(Register),
|
Register(Register),
|
||||||
@@ -57,6 +62,12 @@ impl std::fmt::Display for ModRmTarget {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
/// Memory displacements are signed versions of Byte and Word operands.
|
/// Memory displacements are signed versions of Byte and Word operands.
|
||||||
/// Encodes either Byte- or Word-sized operands.
|
/// Encodes either Byte- or Word-sized operands.
|
||||||
|
/// Generally, a [`Displacement`] is the result of a ModRM byte parse and
|
||||||
|
/// usually really is the signed displacement of a [`MemoryIndex`] for memory
|
||||||
|
/// operations.
|
||||||
|
/// Although, some instructions use this parsed displacement as an unsigned
|
||||||
|
/// pointer, hence the [`Displacement`] will be cast to [`Pointer16`], when this
|
||||||
|
/// is the case.
|
||||||
pub enum Displacement {
|
pub enum Displacement {
|
||||||
IByte(IByte),
|
IByte(IByte),
|
||||||
IWord(IWord),
|
IWord(IWord),
|
||||||
@@ -133,6 +144,8 @@ impl fmt::Display for MemoryIndex {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
/// 16-bit pointer for access, usually with a [`SegmentRegister`] as segment
|
/// 16-bit pointer for access, usually with a [`SegmentRegister`] as segment
|
||||||
/// and [`Pointer16`] as offset.
|
/// and [`Pointer16`] as offset.
|
||||||
|
/// Generally, this type only gets constructed in rare scenarios, when the
|
||||||
|
/// [`Displacement`] of ModRM byte is used as a raw pointer.
|
||||||
pub struct Pointer16 {
|
pub struct Pointer16 {
|
||||||
pub word: Word,
|
pub word: Word,
|
||||||
}
|
}
|
||||||
@@ -152,15 +165,21 @@ impl TryFrom<ModRmTarget> for Pointer16 {
|
|||||||
Some(disp) => match disp {
|
Some(disp) => match disp {
|
||||||
Displacement::IWord(word) => Ok(Pointer16 { word: word as Word }),
|
Displacement::IWord(word) => Ok(Pointer16 { word: word as Word }),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(DisasmError::IllegalOperand("Word expected".into()));
|
return Err(DisasmError::IllegalOperand(
|
||||||
|
"Tried to construct Pointer16 with Byte, when a Word is expected"
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(DisasmError::IllegalOperand("Displacement expected".into()));
|
return Err(DisasmError::IllegalOperand("Tried to construct Pointer16 with Register, when a Displacement was expected".into()));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(DisasmError::IllegalOperand("MemoryIndex expected".into()));
|
return Err(DisasmError::IllegalOperand(
|
||||||
|
"Tried to construct Pointer16 with Register, when a MemoryIndex expected"
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user