diff --git a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
index a0e2d13..9d69a35 100644
--- a/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
+++ b/X86Disassembler/X86/Handlers/InstructionHandlerFactory.cs
@@ -149,9 +149,14 @@ public class InstructionHandlerFactory
///
private void RegisterJumpHandlers()
{
- // JMP handlers
- _handlers.Add(new JmpRel32Handler(_decoder));
- _handlers.Add(new JmpRel8Handler(_decoder));
+ // JMP handlers for relative jumps
+ _handlers.Add(new JmpRel32Handler(_decoder)); // JMP rel32 (opcode E9)
+ _handlers.Add(new JmpRel8Handler(_decoder)); // JMP rel8 (opcode EB)
+
+ // JMP handler for register/memory operands
+ _handlers.Add(new JmpRm32Handler(_decoder)); // JMP r/m32 (opcode FF /4)
+
+ // Conditional jump handlers
_handlers.Add(new JgeRel8Handler(_decoder));
_handlers.Add(new ConditionalJumpHandler(_decoder));
_handlers.Add(new TwoByteConditionalJumpHandler(_decoder));
diff --git a/X86Disassembler/X86/Handlers/Jump/JmpRm32Handler.cs b/X86Disassembler/X86/Handlers/Jump/JmpRm32Handler.cs
new file mode 100644
index 0000000..0bbaee0
--- /dev/null
+++ b/X86Disassembler/X86/Handlers/Jump/JmpRm32Handler.cs
@@ -0,0 +1,76 @@
+using X86Disassembler.X86.Operands;
+
+namespace X86Disassembler.X86.Handlers.Jump;
+
+///
+/// Handler for JMP r/m32 instruction (opcode FF /4)
+///
+public class JmpRm32Handler : InstructionHandler
+{
+ ///
+ /// Initializes a new instance of the JmpRm32Handler class
+ ///
+ /// The instruction decoder that owns this handler
+ public JmpRm32Handler(InstructionDecoder decoder)
+ : base(decoder)
+ {
+ }
+
+ ///
+ /// Checks if this handler can decode the given opcode
+ ///
+ /// The opcode to check
+ /// True if this handler can decode the opcode
+ public override bool CanHandle(byte opcode)
+ {
+ // JMP r/m32 is encoded as FF /4
+ if (opcode != 0xFF)
+ {
+ return false;
+ }
+
+ // Check if we have enough bytes to read the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Extract the reg field (bits 3-5)
+ var reg = ModRMDecoder.PeakModRMReg();
+
+ // JMP r/m32 is encoded as FF /4 (reg field = 4)
+ return reg == 4;
+ }
+
+ ///
+ /// Decodes a JMP r/m32 instruction
+ ///
+ /// The opcode of the instruction
+ /// The instruction object to populate
+ /// True if the instruction was successfully decoded
+ public override bool Decode(byte opcode, Instruction instruction)
+ {
+ // Set the instruction type
+ instruction.Type = InstructionType.Jmp;
+
+ // Check if we have enough bytes for the ModR/M byte
+ if (!Decoder.CanReadByte())
+ {
+ return false;
+ }
+
+ // Read the ModR/M byte
+ // For JMP r/m32 (FF /4):
+ // - The r/m field with mod specifies the operand (register or memory)
+ var (_, _, _, operand) = ModRMDecoder.ReadModRM();
+
+ // Set the structured operands
+ // JMP has only one operand
+ instruction.StructuredOperands =
+ [
+ operand
+ ];
+
+ return true;
+ }
+}
diff --git a/X86DisassemblerTests/TestData/jmp_tests.csv b/X86DisassemblerTests/TestData/jmp_tests.csv
index 2b272ea..ca5f9c1 100644
--- a/X86DisassemblerTests/TestData/jmp_tests.csv
+++ b/X86DisassemblerTests/TestData/jmp_tests.csv
@@ -41,10 +41,11 @@ FF6610;[{ "Type": "Jmp", "Operands": ["dword ptr [esi+0x10]"] }]
FF6710;[{ "Type": "Jmp", "Operands": ["dword ptr [edi+0x10]"] }]
# JMP m32 (opcode FF /4) with SIB byte
-FF24C5;[{ "Type": "Jmp", "Operands": ["dword ptr [eax*8+ebp]"] }]
-FF24CD;[{ "Type": "Jmp", "Operands": ["dword ptr [ecx*8+ebp]"] }]
-FF24D5;[{ "Type": "Jmp", "Operands": ["dword ptr [edx*8+ebp]"] }]
-FF24DD;[{ "Type": "Jmp", "Operands": ["dword ptr [ebx*8+ebp]"] }]
+# not recognized by ghidra or online disasms
+# FF24C5;[{ "Type": "Jmp", "Operands": ["dword ptr [eax*8+ebp]"] }]
+# FF24CD;[{ "Type": "Jmp", "Operands": ["dword ptr [ecx*8+ebp]"] }]
+# FF24D5;[{ "Type": "Jmp", "Operands": ["dword ptr [edx*8+ebp]"] }]
+# FF24DD;[{ "Type": "Jmp", "Operands": ["dword ptr [ebx*8+ebp]"] }]
# JMP m32 (opcode FF /4) with direct memory operand
FF2578563412;[{ "Type": "Jmp", "Operands": ["dword ptr [0x12345678]"] }]