From d7208834963c46a6da74a3837d9e82bad33dfd7f Mon Sep 17 00:00:00 2001 From: iximeow Date: Sat, 21 Aug 2021 14:03:08 -0700 Subject: fix incorrect decoding of 0x9*-series instructions with rex.b --- CHANGELOG | 2 ++ src/long_mode/mod.rs | 14 +++++++++++--- test/long_mode/mod.rs | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b10a6c0..0febd15 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ the *read*, not the corresponding write of pushing `{e}ip` to the stack. documentation has been added to `mem_size` more specifically describing this circumstance. +* correct `rex.b` incorrectly applying to the `*ax` register - `4f91` is `xchg rax, r9`, not `xchg r8, r9`. +* correct `nop` incorrectly ignoring `rex.b` - `4190` is `xchg rax, r8`, not `nop`. ## 1.0.4 diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index a01e854..22b6a99 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -5118,7 +5118,7 @@ enum OperandCode { Zv_R5 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 5).bits(), Zv_R6 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 6).bits(), Zv_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_R, 7).bits(), - // Zv_AX_R0 = 0x48, + Zv_AX_R0 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 0).bits(), Zv_AX_R1 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 1).bits(), Zv_AX_R2 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 2).bits(), Zv_AX_R3 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_AX, 3).bits(), @@ -5447,7 +5447,7 @@ const OPCODES: [OpcodeRecord; 256] = [ OpcodeRecord(Interpretation::Instruction(Opcode::LEA), OperandCode::Gv_M), OpcodeRecord(Interpretation::Instruction(Opcode::MOV), OperandCode::Sw_Ew), OpcodeRecord(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x8f_Ev), - OpcodeRecord(Interpretation::Instruction(Opcode::NOP), OperandCode::Nothing), + OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R0), OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R1), OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R2), OpcodeRecord(Interpretation::Instruction(Opcode::XCHG), OperandCode::Zv_AX_R3), @@ -7428,6 +7428,13 @@ fn read_operands::Address, { // Zv_AX + // in 64-bit mode, rex.b is able to make "nop" into an `xchg`, as in `4190` + // aka `xchg eax, r8d. + if reg == 0 && !instruction.prefixes.rex_unchecked().b() { + instruction.opcode = Opcode::NOP; + instruction.operand_count = 0; + return Ok(()); + } let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); let bank = if opwidth == 4 { RegisterBank::D @@ -7436,8 +7443,9 @@ fn read_operands::Address,