diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Float32OperationHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Float32OperationHandler.cs index 0eb961f..e40a5f8 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Float32OperationHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Float32OperationHandler.cs @@ -70,7 +70,7 @@ public class Float32OperationHandler : FloatingPointBaseHandler if (mod != 3) // Memory operand { string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - instruction.Operands = $"dword ptr {operand}"; + instruction.Operands = operand; } else // Register operand (ST(i)) { diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Float64OperationHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Float64OperationHandler.cs index 2aceddf..dd161ff 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Float64OperationHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Float64OperationHandler.cs @@ -69,8 +69,8 @@ public class Float64OperationHandler : FloatingPointBaseHandler // For memory operands, set the operand if (mod != 3) // Memory operand { - string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - instruction.Operands = $"qword ptr {operand}"; + string operand = ModRMDecoder.DecodeModRM(mod, rm, true); // true for 64-bit operand + instruction.Operands = operand; } else // Register operand (ST(i)) { diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Int16OperationHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Int16OperationHandler.cs index e375852..31d54e1 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Int16OperationHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Int16OperationHandler.cs @@ -69,8 +69,10 @@ public class Int16OperationHandler : FloatingPointBaseHandler // For memory operands, set the operand if (mod != 3) // Memory operand { + // Need to modify the default dword ptr to word ptr for 16-bit integers string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - instruction.Operands = $"word ptr {operand}"; + operand = operand.Replace("dword ptr", "word ptr"); + instruction.Operands = operand; } else // Register operand (ST(i)) { diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs index 9776071..5763f2e 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/Int32OperationHandler.cs @@ -70,7 +70,7 @@ public class Int32OperationHandler : FloatingPointBaseHandler if (mod != 3) // Memory operand { string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - instruction.Operands = $"dword ptr {operand}"; + instruction.Operands = operand; } else // Register operand (ST(i)) { diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs index dfbe247..67a586c 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreControlHandler.cs @@ -74,11 +74,20 @@ public class LoadStoreControlHandler : FloatingPointBaseHandler // Different operand types based on the instruction if (reg == 0 || reg == 2 || reg == 3) // fld, fst, fstp { - instruction.Operands = $"dword ptr {operand}"; + // Keep the dword ptr prefix from ModRMDecoder + instruction.Operands = operand; } else // fldenv, fldcw, fnstenv, fnstcw { - instruction.Operands = operand; + if (reg == 5) // fldcw - should use word ptr + { + instruction.Operands = operand.Replace("dword ptr", "word ptr"); + } + else // fldenv, fnstenv, fnstcw + { + // Remove the dword ptr prefix for other control operations + instruction.Operands = operand.Replace("dword ptr ", ""); + } } } else // Register operand (ST(i)) diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreFloat64Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreFloat64Handler.cs index e760a27..7ea6400 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreFloat64Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreFloat64Handler.cs @@ -68,15 +68,16 @@ public class LoadStoreFloat64Handler : FloatingPointBaseHandler // For memory operands, set the operand if (mod != 3) // Memory operand { - string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - + string operand = ModRMDecoder.DecodeModRM(mod, rm, true); // true for 64-bit operand + if (reg == 0 || reg == 2 || reg == 3) // fld, fst, fstp { - instruction.Operands = $"qword ptr {operand}"; + instruction.Operands = operand; } else // frstor, fnsave, fnstsw { - instruction.Operands = operand; + // Remove the qword ptr prefix for these operations + instruction.Operands = operand.Replace("qword ptr ", ""); } } else // Register operand (ST(i)) diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt16Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt16Handler.cs index 1b420dc..a92f8a6 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt16Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt16Handler.cs @@ -77,21 +77,27 @@ public class LoadStoreInt16Handler : FloatingPointBaseHandler if (mod != 3) // Memory operand { string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - + if (reg == 0 || reg == 2 || reg == 3 || reg == 5 || reg == 7) // fild, fist, fistp, fild, fistp { if (reg == 5 || reg == 7) // 64-bit integer { - instruction.Operands = $"qword ptr {operand}"; + // Replace dword ptr with qword ptr for 64-bit integers + operand = operand.Replace("dword ptr", "qword ptr"); + instruction.Operands = operand; } else // 16-bit integer { - instruction.Operands = $"word ptr {operand}"; + // Replace dword ptr with word ptr for 16-bit integers + operand = operand.Replace("dword ptr", "word ptr"); + instruction.Operands = operand; } } else if (reg == 4 || reg == 6) // fbld, fbstp { - instruction.Operands = $"tbyte ptr {operand}"; + // Replace dword ptr with tbyte ptr for 80-bit packed BCD + operand = operand.Replace("dword ptr", "tbyte ptr"); + instruction.Operands = operand; } else { diff --git a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt32Handler.cs b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt32Handler.cs index eb7974b..2e97f7b 100644 --- a/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt32Handler.cs +++ b/X86Disassembler/X86/Handlers/FloatingPoint/LoadStoreInt32Handler.cs @@ -70,14 +70,17 @@ public class LoadStoreInt32Handler : FloatingPointBaseHandler if (mod != 3) // Memory operand { string operand = ModRMDecoder.DecodeModRM(mod, rm, false); - + if (reg == 0 || reg == 2 || reg == 3) // fild, fist, fistp { - instruction.Operands = $"dword ptr {operand}"; + // Keep the dword ptr prefix for integer operations + instruction.Operands = operand; } else if (reg == 5 || reg == 7) // fld, fstp (extended precision) { - instruction.Operands = $"tword ptr {operand}"; + // Replace dword ptr with tword ptr for extended precision + operand = operand.Replace("dword ptr", "tword ptr"); + instruction.Operands = operand; } else { diff --git a/X86DisassemblerTests/FloatingPointInstructionTests.cs b/X86DisassemblerTests/FloatingPointInstructionTests.cs index 0c3b2b8..482bda7 100644 --- a/X86DisassemblerTests/FloatingPointInstructionTests.cs +++ b/X86DisassemblerTests/FloatingPointInstructionTests.cs @@ -4,6 +4,7 @@ using System; using Xunit; using X86Disassembler.X86; using X86Disassembler.X86.Handlers; +using X86Disassembler.X86.Handlers.FloatingPoint; /// /// Tests for floating-point instruction handlers @@ -29,4 +30,224 @@ public class FloatingPointInstructionTests Assert.Equal("fnstsw", instruction.Mnemonic); Assert.Equal("ax", instruction.Operands); } + + /// + /// Tests the Float32OperationHandler for decoding FADD ST(0), ST(1) instruction + /// + [Fact] + public void Float32OperationHandler_DecodesAddSt0St1_Correctly() + { + // Arrange + // FADD ST(0), ST(1) (D8 C1) + byte[] codeBuffer = new byte[] { 0xD8, 0xC1 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fadd", instruction.Mnemonic); + Assert.Equal("st(0), st(1)", instruction.Operands); + } + + /// + /// Tests the Float32OperationHandler for decoding FADD dword ptr [eax] instruction + /// + [Fact] + public void Float32OperationHandler_DecodesAddMemory_Correctly() + { + // Arrange + // FADD dword ptr [eax] (D8 00) + byte[] codeBuffer = new byte[] { 0xD8, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fadd", instruction.Mnemonic); + Assert.Equal("dword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the LoadStoreControlHandler for decoding FLD dword ptr [eax] instruction + /// + [Fact] + public void LoadStoreControlHandler_DecodesLoadMemory_Correctly() + { + // Arrange + // FLD dword ptr [eax] (D9 00) + byte[] codeBuffer = new byte[] { 0xD9, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fld", instruction.Mnemonic); + Assert.Equal("dword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the LoadStoreControlHandler for decoding FLDCW [eax] instruction + /// + [Fact] + public void LoadStoreControlHandler_DecodesLoadControlWord_Correctly() + { + // Arrange + // FLDCW [eax] (D9 28) + byte[] codeBuffer = new byte[] { 0xD9, 0x28 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fldcw", instruction.Mnemonic); + Assert.Equal("word ptr [eax]", instruction.Operands); + } + + /// + /// Tests the Int32OperationHandler for decoding FIADD dword ptr [eax] instruction + /// + [Fact] + public void Int32OperationHandler_DecodesIntegerAdd_Correctly() + { + // Arrange + // FIADD dword ptr [eax] (DA 00) + byte[] codeBuffer = new byte[] { 0xDA, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fiadd", instruction.Mnemonic); + Assert.Equal("dword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the LoadStoreInt32Handler for decoding FILD dword ptr [eax] instruction + /// + [Fact] + public void LoadStoreInt32Handler_DecodesIntegerLoad_Correctly() + { + // Arrange + // FILD dword ptr [eax] (DB 00) + byte[] codeBuffer = new byte[] { 0xDB, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fild", instruction.Mnemonic); + Assert.Equal("dword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the Float64OperationHandler for decoding FADD qword ptr [eax] instruction + /// + [Fact] + public void Float64OperationHandler_DecodesDoubleAdd_Correctly() + { + // Arrange + // FADD qword ptr [eax] (DC 00) + byte[] codeBuffer = new byte[] { 0xDC, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fadd", instruction.Mnemonic); + Assert.Equal("qword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the Float64OperationHandler for decoding FADD ST(1), ST(0) instruction + /// + [Fact] + public void Float64OperationHandler_DecodesAddSt1St0_Correctly() + { + // Arrange + // FADD ST(1), ST(0) (DC C1) + byte[] codeBuffer = new byte[] { 0xDC, 0xC1 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fadd", instruction.Mnemonic); + Assert.Equal("st(1), st(0)", instruction.Operands); + } + + /// + /// Tests the LoadStoreFloat64Handler for decoding FLD qword ptr [eax] instruction + /// + [Fact] + public void LoadStoreFloat64Handler_DecodesDoubleLoad_Correctly() + { + // Arrange + // FLD qword ptr [eax] (DD 00) + byte[] codeBuffer = new byte[] { 0xDD, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fld", instruction.Mnemonic); + Assert.Equal("qword ptr [eax]", instruction.Operands); + } + + /// + /// Tests the Int16OperationHandler for decoding FIADD word ptr [eax] instruction + /// + [Fact] + public void Int16OperationHandler_DecodesShortAdd_Correctly() + { + // Arrange + // FIADD word ptr [eax] (DE 00) + byte[] codeBuffer = new byte[] { 0xDE, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fiadd", instruction.Mnemonic); + Assert.Equal("word ptr [eax]", instruction.Operands); + } + + /// + /// Tests the LoadStoreInt16Handler for decoding FILD word ptr [eax] instruction + /// + [Fact] + public void LoadStoreInt16Handler_DecodesShortLoad_Correctly() + { + // Arrange + // FILD word ptr [eax] (DF 00) + byte[] codeBuffer = new byte[] { 0xDF, 0x00 }; + var decoder = new InstructionDecoder(codeBuffer, codeBuffer.Length); + + // Act + var instruction = decoder.DecodeInstruction(); + + // Assert + Assert.NotNull(instruction); + Assert.Equal("fild", instruction.Mnemonic); + Assert.Equal("word ptr [eax]", instruction.Operands); + } }