ft: add debug script

This commit is contained in:
2025-05-28 14:13:12 +09:00
parent c396d33f76
commit a21cc2b4b3
4 changed files with 70 additions and 5 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/target
test.out

43
gen.py Normal file
View 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}")

View File

@@ -43,7 +43,7 @@ impl fmt::Display for DisasmError {
DisasmError::IoError(msg) => write!(f, "{}", msg),
DisasmError::OpcodeUndefined(opcode) => write!(
f,
"Error (Undefined Opcode). '{:#x} is considered undefined by the Spec",
"Error (Undefined Opcode). '{:#04x} is considered undefined by the Spec",
opcode
),
DisasmError::IllegalGroupMnemonic(group, mnemonic) => write!(
@@ -244,6 +244,8 @@ impl Disassembler {
rm
);
// not unused, but overwritten before first read
#[allow(unused_assignments)]
let mut displacement = None;
match mode {
0b00 => {

View File

@@ -1,6 +1,10 @@
//! All types which a Mnemonic can have as some kind of operand.
//! 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 core::fmt;
@@ -39,7 +43,8 @@ impl fmt::LowerHex for Operand {
}
#[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 {
Memory(MemoryIndex),
Register(Register),
@@ -57,6 +62,12 @@ impl std::fmt::Display for ModRmTarget {
#[derive(Debug, Clone, PartialEq, Eq)]
/// Memory displacements are signed versions of Byte and Word 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 {
IByte(IByte),
IWord(IWord),
@@ -133,6 +144,8 @@ impl fmt::Display for MemoryIndex {
#[derive(Debug, Clone, PartialEq, Eq)]
/// 16-bit pointer for access, usually with a [`SegmentRegister`] as segment
/// 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 word: Word,
}
@@ -152,15 +165,21 @@ impl TryFrom<ModRmTarget> for Pointer16 {
Some(disp) => match disp {
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(),
));
}
}
}