From 3fe58e8bac505086e972dcc66e8532d9f6dc4cee Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Tue, 20 May 2025 10:46:52 +0900 Subject: [PATCH] ft: implement fmt::Display for all mnemonics --- src/disasm.rs | 4 +- src/instructions.rs | 243 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 235 insertions(+), 12 deletions(-) diff --git a/src/disasm.rs b/src/disasm.rs index a701cc8..5fc7e44 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -486,8 +486,8 @@ impl Disassembler { 0x84 => modrmb!(self, TEST), 0x85 => modrmv!(self, TEST), - 0x86 => modrmb!(self, XHCG), - 0x87 => modrmv!(self, XHCG), + 0x86 => modrmb!(self, XCHG), + 0x87 => modrmv!(self, XCHG), 0x88 => modrmb!(self, MOV_FromReg), 0x89 => modrmv!(self, MOV_FromReg), diff --git a/src/instructions.rs b/src/instructions.rs index 868e155..0ac2cad 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -193,7 +193,7 @@ pub enum Mnemonic { TEST_ALIb(Byte), TEST_AXIv(Word), //XHCG - XHCG(ModRmTarget, Register), + XCHG(ModRmTarget, Register), XCHG_AX(Register), // from AX // MOV MOV_FromReg(ModRmTarget, Register), @@ -326,15 +326,237 @@ pub enum Mnemonic { impl fmt::Display for Mnemonic { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Self::INT(byte) => write!(f, "int, {:x}", byte), - Self::ADD_FromReg(mem, reg) => write!(f, "add {}, {}", mem, reg), - Self::ADD_ToReg(mem, reg) => write!(f, "add {}, {}", reg, mem), - Self::CMP_Iv(mem, imm) => write!(f, "cmp {}, {:04x}", mem, imm), - Self::CMP_Ib(target, imm) => write!(f, "cmp {}, {:04x}", target, imm), + Self::ADD_FromReg(target, reg) => write!(f, "add {target}, {reg}"), + Self::ADD_ToReg(target, reg) => write!(f, "add {reg}, {target}"), + Self::ADD_Ib(target, byte) => write!(f, "add {target}, {byte:#04x}"), + Self::ADD_Iv(target, word) => write!(f, "add {target}, {word:#04x}"), + Self::ADD_ALIb(byte) => write!(f, "add {}, {byte:#04x}", Register::AL), + Self::ADD_AXIv(word) => write!(f, "add {}, {word:#04x}", Register::AX), + + Self::PUSH_R(reg) => write!(f, "push {reg}"), + Self::PUSH_S(reg) => write!(f, "push {reg}"), + Self::PUSH_Mod(target) => write!(f, "push {target}"), + + Self::POP_R(reg) => write!(f, "pop {reg}"), + Self::POP_S(reg) => write!(f, "pop {reg}"), + Self::POP_M(mem) => write!(f, "pop {mem}"), + + Self::OR_FromReg(target, reg) => write!(f, "or {target}, {reg}"), + Self::OR_ToReg(target, reg) => write!(f, "or {reg}, {target}"), + Self::OR_Ib(target, byte) => write!(f, "or {target}, {byte:#04x}"), + Self::OR_Iv(target, word) => write!(f, "or {target}, {word:#04x}"), + Self::OR_ALIb(byte) => write!(f, "or {}, {byte:#04x}", Register::AL), + Self::OR_AXIv(word) => write!(f, "or {}, {word:#04x}", Register::AX), + + Self::ADC_FromReg(target, reg) => write!(f, "adc {target}, {reg}"), + Self::ADC_ToReg(target, reg) => write!(f, "adc {reg}, {target}"), + Self::ADC_Ib(target, byte) => write!(f, "adc {target}, {byte:#04x}"), + Self::ADC_Iv(target, word) => write!(f, "adc {target}, {word:#04x}"), + Self::ADC_ALIb(byte) => write!(f, "adc {}, {byte:#04x}", Register::AL), + Self::ADC_AXIv(word) => write!(f, "adc {}, {word:#04x}", Register::AX), + + Self::SBB_FromReg(target, reg) => write!(f, "sbb {target}, {reg}"), + Self::SBB_ToReg(target, reg) => write!(f, "sbb {reg}, {target}"), + Self::SBB_Ib(target, byte) => write!(f, "sbb {target}, {byte:#04x}"), + Self::SBB_Iv(target, word) => write!(f, "sbb {target}, {word:#04x}"), + Self::SBB_ALIb(byte) => write!(f, "sbb {}, {byte:#04x}", Register::AL), + Self::SBB_AXIv(word) => write!(f, "sbb {}, {word:#04x}", Register::AX), + + Self::AND_FromReg(target, reg) => write!(f, "and {target}, {reg}"), + Self::AND_ToReg(target, reg) => write!(f, "and {reg}, {target}"), + Self::AND_Ib(target, byte) => write!(f, "and {target}, {byte:#04x}"), + Self::AND_Iv(target, word) => write!(f, "and {target}, {word:#04x}"), + Self::AND_ALIb(byte) => write!(f, "and {}, {byte:#04x}", Register::AL), + Self::AND_AXIv(word) => write!(f, "and {}, {word:#04x}", Register::AX), + + Self::OVERRIDE(reg) => write!(f, "{reg}:"), + + Self::DAA => write!(f, "DAA"), + Self::DAS => write!(f, "DAS"), + Self::AAA => write!(f, "AAA"), + Self::AAS => write!(f, "AAS"), + + Self::SUB_FromReg(target, reg) => write!(f, "sub {target}, {reg}"), + Self::SUB_ToReg(target, reg) => write!(f, "sub {reg}, {target}"), + Self::SUB_Ib(target, byte) => write!(f, "sub {target}, {byte:#04x}"), + Self::SUB_Iv(target, word) => write!(f, "sub {target}, {word:#04x}"), + Self::SUB_ALIb(byte) => write!(f, "sub {}, {byte:#04x}", Register::AL), + Self::SUB_AXIv(word) => write!(f, "sub {}, {word:#04x}", Register::AX), + + Self::XOR_FromReg(target, reg) => write!(f, "xor {target}, {reg}"), + Self::XOR_ToReg(target, reg) => write!(f, "xor {reg}, {target}"), + Self::XOR_Ib(target, byte) => write!(f, "xor {target}, {byte:#04x}"), + Self::XOR_Iv(target, word) => write!(f, "xor {target}, {word:#04x}"), + Self::XOR_ALIb(byte) => write!(f, "xor {}, {byte:#04x}", Register::AL), + Self::XOR_AXIv(word) => write!(f, "xor {}, {word:#04x}", Register::AX), + + Self::CMP_FromReg(target, reg) => write!(f, "cmp {target}, {reg}"), + Self::CMP_ToReg(target, reg) => write!(f, "cmp {reg}, {target}"), + Self::CMP_Ib(target, byte) => write!(f, "cmp {target}, {byte:#04x}"), + Self::CMP_Iv(target, word) => write!(f, "cmp {target}, {word:#04x}"), + Self::CMP_ALIb(byte) => write!(f, "cmp {}, {byte:#04x}", Register::AL), + Self::CMP_AXIv(word) => write!(f, "cmp {}, {word:#04x}", Register::AX), + + Self::INC_Reg(reg) => write!(f, "INC {reg}"), + Self::INC_Mod(target) => write!(f, "INC {target}"), + + Self::DEC_Reg(reg) => write!(f, "dec {reg}"), + Self::DEC_Mod(target) => write!(f, "dec {target}"), + + Self::JO(ibyte) => write!(f, "jo {ibyte}"), + Self::JNO(ibyte) => write!(f, "jno {ibyte}"), + Self::JB(ibyte) => write!(f, "jb {ibyte}"), + Self::JNB(ibyte) => write!(f, "jnb {ibyte}"), + Self::JZ(ibyte) => write!(f, "jz {ibyte}"), + Self::JNZ(ibyte) => write!(f, "jnz {ibyte}"), + Self::JBE(ibyte) => write!(f, "jbe {ibyte}"), + Self::JA(ibyte) => write!(f, "ja {ibyte}"), + Self::JS(ibyte) => write!(f, "js {ibyte}"), + Self::JNS(ibyte) => write!(f, "jns {ibyte}"), + Self::JPE(ibyte) => write!(f, "jpe {ibyte}"), + Self::JPO(ibyte) => write!(f, "jpo {ibyte}"), + Self::JL(ibyte) => write!(f, "jl {ibyte}"), + Self::JGE(ibyte) => write!(f, "jge {ibyte}"), + Self::JLE(ibyte) => write!(f, "jle {ibyte}"), + Self::JG(ibyte) => write!(f, "jg {ibyte}"), + Self::LOOPNZ(ibyte) => write!(f, "loopnz {ibyte}"), + Self::LOOPZ(ibyte) => write!(f, "loopz {ibyte}"), + Self::LOOP(ibyte) => write!(f, "loop {ibyte}"), + Self::JCXZ(ibyte) => write!(f, "jcxz {ibyte}"), + + Self::TEST(target, reg) => write!(f, "test {target}, {reg}"), + Self::TEST_Ib(target, byte) => write!(f, "test byte {target}, {byte:#04x}"), + Self::TEST_Iv(target, word) => write!(f, "test word {target}, {word:#04x}"), + Self::TEST_ALIb(byte) => write!(f, "test {}, {byte:#04x}", Register::AL), + Self::TEST_AXIv(word) => write!(f, "test {}, {word:#04x}", Register::AX), + + Self::XCHG(target, reg) => write!(f, "xchg {target}, {reg}"), + Self::XCHG_AX(reg) => write!(f, "xchg, {reg}, {}", Register::AX), + + Self::MOV_FromReg(target, reg) => write!(f, "mov {target}, {reg}"), + Self::MOV_ToReg(target, reg) => write!(f, "mov {reg}, {target}"), + Self::MOV_FromSReg(target, reg) => write!(f, "mov {target}, {reg}"), + Self::MOV_ToSReg(target, reg) => write!(f, "mov {reg}, {target}"), + Self::MOV_Ib(target, byte) => write!(f, "mov {target}, {byte:#04x}"), + Self::MOV_Iv(target, word) => write!(f, "mov {target}, {word:#04x}"), + + Self::MOV_AL0b(byte) => write!(f, "mov {}, {byte:#04x}", Register::AL), + Self::MOV_AX0v(word) => write!(f, "mov {}, {word:#04x}", Register::AX), + Self::MOV_0bAL(byte) => write!(f, "mov {byte:#04x}, {}", Register::AL), + Self::MOV_0vAX(word) => write!(f, "mov {word:#04x}, {}", Register::AX), + + Self::MOV_ALIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::AL), + Self::MOV_CLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::CL), + Self::MOV_DLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::DL), + Self::MOV_BLIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::BL), + Self::MOV_AHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::AH), + Self::MOV_CHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::CH), + Self::MOV_DHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::DH), + Self::MOV_BHIb(byte) => write!(f, "mov {}, {byte:#04x}", Register::BH), + Self::MOV_AXIv(word) => write!(f, "mov {}, {word:#04x}", Register::AX), + Self::MOV_CXIv(word) => write!(f, "mov {}, {word:#04x}", Register::CX), + Self::MOV_DXIv(word) => write!(f, "mov {}, {word:#04x}", Register::DX), + Self::MOV_BXIv(word) => write!(f, "mov {}, {word:#04x}", Register::BX), + Self::MOV_SPIv(word) => write!(f, "mov {}, {word:#04x}", Register::SP), + Self::MOV_BPIv(word) => write!(f, "mov {}, {word:#04x}", Register::BP), + Self::MOV_SIIv(word) => write!(f, "mov {}, {word:#04x}", Register::SI), + Self::MOV_DIIv(word) => write!(f, "mov {}, {word:#04x}", Register::DI), + Self::LEA(mem, reg) => write!(f, "lea {}, {}", reg, mem), - Self::MOV_BXIv(word) => write!(f, "mov bx, {:04x}", word), - Self::MOV_FromReg(target, reg) => write!(f, "mov {}, {}", target, reg), - Self::XOR_FromReg(mem, reg) => write!(f, "xor {}, {}", mem, reg), + + Self::CBW => write!(f, "CBW"), + Self::CWD => write!(f, "CWD"), + + Self::CALL_p(ptr) => write!(f, "call {ptr}"), + Self::CALL_v(word) => write!(f, "call {word:#04x}"), + Self::CALL_Mod(target) => write!(f, "call {target}"), + + Self::JMP_p(ptr) => write!(f, "jmp {ptr}"), + Self::JMP_b(byte) => write!(f, "jmp {byte:#04}"), + Self::JMP_v(word) => write!(f, "jmp {word:#04}"), + Self::JMP_Mod(target) => write!(f, "jmp {target}"), + + Self::WAIT => write!(f, "WAIT"), + + Self::PUSHF => write!(f, "PUSHF"), + Self::POPF => write!(f, "POPF"), + Self::SAHF => write!(f, "SAHF"), + Self::LAHF => write!(f, "LAHF"), + + Self::MOVSB => write!(f, "MOVSB"), + Self::MOVSW => write!(f, "MOVSW"), + Self::CMPSB => write!(f, "CMPSB"), + Self::CMPSW => write!(f, "CMPSW"), + Self::STOSB => write!(f, "STOSB"), + Self::STOSW => write!(f, "STOSW"), + Self::LODSB => write!(f, "LODSB"), + Self::LODSW => write!(f, "LODSW"), + Self::SCASB => write!(f, "SCASB"), + Self::SCASW => write!(f, "SCASW"), + + Self::RET_Iw(word) => write!(f, "ret {word:#04x}"), + Self::RET => write!(f, "ret"), + Self::RETF_Iw(word) => write!(f, "retf {word:#04x}"), + Self::RETF => write!(f, "retf"), + Self::IRET => write!(f, "iret"), + + Self::LES(target) => write!(f, "les {target}"), + Self::LDS(target) => write!(f, "lds {target}"), + + Self::NOT(target) => write!(f, "not {target}"), + Self::NEG(target) => write!(f, "neg {target}"), + + Self::MUL(target) => write!(f, "mul {target}"), + Self::IMUL(target) => write!(f, "imul {target}"), + Self::DIV(target) => write!(f, "mdiv {target}"), + Self::IDIV(target) => write!(f, "idiv {target}"), + + Self::HLT => write!(f, "HLT"), + + Self::ROL_b(target, byte) => write!(f, "rol {target}, {byte:#04x}"), + Self::ROR_b(target, byte) => write!(f, "ror {target}, {byte:#04x}"), + Self::RCL_b(target, byte) => write!(f, "rcl {target}, {byte:#04x}"), + Self::RCR_b(target, byte) => write!(f, "rcr {target}, {byte:#04x}"), + Self::SHL_b(target, byte) => write!(f, "shl {target}, {byte:#04x}"), + Self::SHR_b(target, byte) => write!(f, "shr {target}, {byte:#04x}"), + Self::SAR_b(target, byte) => write!(f, "sar {target}, {byte:#04x}"), + Self::ROL_fromReg(target, reg) => write!(f, "rol {target}, {reg}"), + Self::ROR_fromReg(target, reg) => write!(f, "ror {target}, {reg}"), + Self::RCL_fromReg(target, reg) => write!(f, "rcl {target}, {reg}"), + Self::RCR_fromReg(target, reg) => write!(f, "rcr {target}, {reg}"), + Self::SHL_fromReg(target, reg) => write!(f, "shl {target}, {reg}"), + Self::SHR_fromReg(target, reg) => write!(f, "shr {target}, {reg}"), + Self::SAR_fromReg(target, reg) => write!(f, "sar {target}, {reg}"), + + Self::IN_AL(byte) => write!(f, "in {}, {byte:#04x}", Register::AL), + Self::IN_AX(byte) => write!(f, "in {}, {byte:#04x}", Register::AX), + Self::IN_ALDX => write!(f, "in {}, {}", Register::AL, Register::DX), + Self::IN_AXDX => write!(f, "in {}, {}", Register::AX, Register::DX), + + Self::OUT_AL(byte) => write!(f, "out {}, {byte:#04x}", Register::AL), + Self::OUT_AX(byte) => write!(f, "out {}, {byte:#04x}", Register::AX), + Self::OUT_ALDX => write!(f, "out {}, {}", Register::AL, Register::DX), + Self::OUT_AXDX => write!(f, "out {}, {}", Register::AX, Register::DX), + + Self::INT(byte) => write!(f, "int {byte:#04x}"), + Self::INTO => write!(f, "into"), + + Self::CLC => write!(f, "clc"), + Self::STC => write!(f, "stc"), + Self::CLI => write!(f, "cli"), + Self::STI => write!(f, "sti"), + Self::CLD => write!(f, "cld"), + Self::STD => write!(f, "std"), + Self::CMC => write!(f, "cmc"), + + Self::REPNZ => write!(f, "repnz"), + Self::REPZ => write!(f, "repz"), + + Self::AAM(byte) => write!(f, "aam {byte:#04x}"), + Self::AAD(byte) => write!(f, "aad {byte:#04x}"), + + Self::XLAT => write!(f, "xlat"), + _ => write!(f, "??? ??, ??"), } } @@ -357,7 +579,8 @@ impl std::fmt::Display for ModRmTarget { } #[derive(Debug, Clone)] -/// Displacements are signed versions of u8 and u16. +/// Memory displacements are signed versions of u8 and u16. +/// Encodes either Byte- or Word-sized operands. pub enum Displacement { IByte(i8), IWord(i16),