From b215908d7695e8f4b2c66c24567b994e2f9d4937 Mon Sep 17 00:00:00 2001 From: bird_egop Date: Sun, 13 Apr 2025 03:56:39 +0300 Subject: [PATCH] fixups --- X86Disassembler/Program.cs | 10 ++++ X86Disassembler/X86/Handlers/Int3Handler.cs | 6 +-- .../X86/Handlers/Mov/MovRegMemHandler.cs | 50 +++++++++++++------ .../Group1SignExtendedHandlerTests.cs | 19 +++---- X86DisassemblerTests/HandlerSelectionTests.cs | 1 + 5 files changed, 57 insertions(+), 29 deletions(-) diff --git a/X86Disassembler/Program.cs b/X86Disassembler/Program.cs index cf27ff3..c19ded2 100644 --- a/X86Disassembler/Program.cs +++ b/X86Disassembler/Program.cs @@ -74,6 +74,16 @@ public class Program // Disassemble all instructions var instructions = disassembler.Disassemble(); + + var unknownIndex = instructions.FindIndex( + x => x.ToString() + .Contains("??") || x.ToString() + .Contains("TODO") + ); + if (unknownIndex != -1) + { + _ = 5; + } // Print the first 100 instructions int count = Math.Min(100, instructions.Count); diff --git a/X86Disassembler/X86/Handlers/Int3Handler.cs b/X86Disassembler/X86/Handlers/Int3Handler.cs index d104af1..4bb26cd 100644 --- a/X86Disassembler/X86/Handlers/Int3Handler.cs +++ b/X86Disassembler/X86/Handlers/Int3Handler.cs @@ -1,12 +1,12 @@ namespace X86Disassembler.X86.Handlers; /// -/// Handler for CALL rel32 instruction (0xE8) +/// Handler for INT3 instruction (0xCC) /// public class Int3Handler : InstructionHandler { /// - /// Initializes a new instance of the CallRel32Handler class + /// Initializes a new instance of the Int3Handler class /// /// The buffer containing the code to decode /// The instruction decoder that owns this handler @@ -27,7 +27,7 @@ public class Int3Handler : InstructionHandler } /// - /// Decodes a CALL rel32 instruction + /// Decodes an INT3 instruction /// /// The opcode of the instruction /// The instruction object to populate diff --git a/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs b/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs index 7599714..b949bcf 100644 --- a/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs +++ b/X86Disassembler/X86/Handlers/Mov/MovRegMemHandler.cs @@ -34,36 +34,56 @@ public class MovRegMemHandler : InstructionHandler /// True if the instruction was successfully decoded public override bool Decode(byte opcode, Instruction instruction) { + // Save the original position for raw bytes calculation + int startPosition = Decoder.GetPosition(); + // Set the mnemonic instruction.Mnemonic = "mov"; - int position = Decoder.GetPosition(); - - if (position >= Length) + if (startPosition >= Length) { - return false; + instruction.Operands = "??"; + instruction.RawBytes = new byte[] { opcode }; + return true; } // Determine operand size (0 = 8-bit, 1 = 32-bit) bool operandSize32 = (opcode & 0x01) != 0; int operandSize = operandSize32 ? 32 : 8; - // Read the ModR/M byte - var (mod, reg, rm, memOperand) = ModRMDecoder.ReadModRM(); + // Use ModRMDecoder to decode the ModR/M byte + var (mod, reg, rm, rmOperand) = ModRMDecoder.ReadModRM(false); // false for 32-bit operand // Get register name based on size - string regName = ModRMDecoder.GetRegisterName(reg, operandSize); + string regName; + if (operandSize == 8) + { + regName = GetRegister8(reg); + } + else + { + regName = GetRegister32(reg); + } - // For mod == 3, both operands are registers - if (mod == 3) + // Get the position after decoding the ModR/M byte + int newPosition = Decoder.GetPosition(); + + // Set the operands - register is the destination, r/m is the source (for 0x8B) + // This matches the correct x86 instruction format: MOV r32, r/m32 + instruction.Operands = $"{regName}, {rmOperand}"; + + // Set the raw bytes + int totalBytes = newPosition - startPosition + 1; // +1 for opcode + byte[] rawBytes = new byte[totalBytes]; + rawBytes[0] = opcode; + for (int i = 0; i < totalBytes - 1; i++) { - string rmRegName = ModRMDecoder.GetRegisterName(rm, operandSize); - instruction.Operands = $"{rmRegName}, {regName}"; - } - else // Memory operand - { - instruction.Operands = $"{memOperand}, {regName}"; + if (startPosition + i < Length) + { + rawBytes[i + 1] = CodeBuffer[startPosition + i]; + } } + instruction.RawBytes = rawBytes; return true; } diff --git a/X86DisassemblerTests/Group1SignExtendedHandlerTests.cs b/X86DisassemblerTests/Group1SignExtendedHandlerTests.cs index d38f4ba..638a281 100644 --- a/X86DisassemblerTests/Group1SignExtendedHandlerTests.cs +++ b/X86DisassemblerTests/Group1SignExtendedHandlerTests.cs @@ -37,8 +37,8 @@ public class Group1SignExtendedHandlerTests { // Arrange // This is the sequence from the problematic example: - // 08 83 C1 04 50 E8 42 01 00 00 - byte[] codeBuffer = new byte[] { 0x08, 0x83, 0xC1, 0x04, 0x50, 0xE8, 0x42, 0x01, 0x00, 0x00 }; + // 83 C1 04 50 E8 42 01 00 00 + byte[] codeBuffer = new byte[] { 0x83, 0xC1, 0x04, 0x50, 0xE8, 0x42, 0x01, 0x00, 0x00 }; var disassembler = new Disassembler(codeBuffer, 0); // Act @@ -47,15 +47,12 @@ public class Group1SignExtendedHandlerTests // Assert Assert.True(instructions.Count >= 3, $"Expected at least 3 instructions, but got {instructions.Count}"); - // First instruction should be OR r/m8, r8 (but might be incomplete) - Assert.Equal("or", instructions[0].Mnemonic); + // First instruction should be ADD ecx, 0x04 + Assert.Equal("add", instructions[0].Mnemonic); + Assert.Equal("ecx, 0x00000004", instructions[0].Operands); - // Second instruction should be ADD ecx, 0x04 - Assert.Equal("add", instructions[1].Mnemonic); - Assert.Equal("ecx, 0x00000004", instructions[1].Operands); - - // Third instruction should be PUSH eax - Assert.Equal("push", instructions[2].Mnemonic); - Assert.Equal("eax", instructions[2].Operands); + // Second instruction should be PUSH eax + Assert.Equal("push", instructions[1].Mnemonic); + Assert.Equal("eax", instructions[1].Operands); } } diff --git a/X86DisassemblerTests/HandlerSelectionTests.cs b/X86DisassemblerTests/HandlerSelectionTests.cs index aafddbf..34a8ccc 100644 --- a/X86DisassemblerTests/HandlerSelectionTests.cs +++ b/X86DisassemblerTests/HandlerSelectionTests.cs @@ -56,5 +56,6 @@ public class HandlerSelectionTests // Third instruction should be PUSH eax Assert.Equal("push", instructions[2].Mnemonic); + Assert.Equal("eax", instructions[2].Operands); } }