From a21cc2b4b3ddaae5e407098c0b101e55fad68973 Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 28 May 2025 14:13:12 +0900 Subject: [PATCH] ft: add debug script --- .gitignore | 1 + gen.py | 43 +++++++++++++++++++++++++++++++++++++++++++ src/disasm.rs | 4 +++- src/operands.rs | 27 +++++++++++++++++++++++---- 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 gen.py diff --git a/.gitignore b/.gitignore index ea8c4bf..0932038 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +test.out diff --git a/gen.py b/gen.py new file mode 100644 index 0000000..45a8342 --- /dev/null +++ b/gen.py @@ -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}") + diff --git a/src/disasm.rs b/src/disasm.rs index cf90aad..68e3160 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -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 => { diff --git a/src/operands.rs b/src/operands.rs index d5f2718..da22a72 100644 --- a/src/operands.rs +++ b/src/operands.rs @@ -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 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(), + )); } } }