mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2025-05-19 20:01:17 +03:00
split float handlers
This commit is contained in:
parent
bb695cf3bb
commit
82653f96f2
@ -0,0 +1,83 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point operations on float32 (D8 opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class Float32OperationHandler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// D8 opcode - operations on float32
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fadd",
|
||||||
|
"fmul",
|
||||||
|
"fcom",
|
||||||
|
"fcomp",
|
||||||
|
"fsub",
|
||||||
|
"fsubr",
|
||||||
|
"fdiv",
|
||||||
|
"fdivr"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Float32OperationHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public Float32OperationHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xD8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for float32 operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
instruction.Operands = $"dword ptr {operand}";
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// For register operands, we need to handle the stack registers
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point operations on float64 (DC opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class Float64OperationHandler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DC opcode - operations on float64
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fadd",
|
||||||
|
"fmul",
|
||||||
|
"fcom",
|
||||||
|
"fcomp",
|
||||||
|
"fsub",
|
||||||
|
"fsubr",
|
||||||
|
"fdiv",
|
||||||
|
"fdivr"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Float64OperationHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public Float64OperationHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for float64 operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte)((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte)((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte)(modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
instruction.Operands = $"qword ptr {operand}";
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// For DC C0-DC FF, the operands are reversed: ST(i), ST(0)
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Base class for floating-point instruction handlers
|
||||||
|
/// </summary>
|
||||||
|
public abstract class FloatingPointBaseHandler : InstructionHandler
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the FloatingPointBaseHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
protected FloatingPointBaseHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
namespace X86Disassembler.X86.Handlers;
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handler for FNSTSW instruction (0xDFE0)
|
/// Handler for FNSTSW instruction (0xDFE0)
|
@ -0,0 +1,128 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point operations on int16 (DE opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class Int16OperationHandler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DE opcode - operations on int16
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fiadd",
|
||||||
|
"fimul",
|
||||||
|
"ficom",
|
||||||
|
"ficomp",
|
||||||
|
"fisub",
|
||||||
|
"fisubr",
|
||||||
|
"fidiv",
|
||||||
|
"fidivr"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Int16OperationHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public Int16OperationHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for int16 operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
instruction.Operands = $"word ptr {operand}";
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for register-register operations
|
||||||
|
if (reg == 0) // FADDP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "faddp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else if (reg == 1) // FMULP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fmulp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else if (reg == 2 && rm == 1) // FCOMP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcomp";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else if (reg == 3 && rm == 1) // FCOMPP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcompp";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else if (reg == 4) // FSUBP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fsubp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else if (reg == 5) // FSUBRP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fsubrp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else if (reg == 6) // FDIVP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fdivp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else if (reg == 7) // FDIVRP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fdivrp";
|
||||||
|
instruction.Operands = $"st({rm}), st(0)";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown instruction
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point operations on int32 (DA opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class Int32OperationHandler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DA opcode - operations on int32
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
{
|
||||||
|
"fiadd",
|
||||||
|
"fimul",
|
||||||
|
"ficom",
|
||||||
|
"ficomp",
|
||||||
|
"fisub",
|
||||||
|
"fisubr",
|
||||||
|
"fidiv",
|
||||||
|
"fidivr",
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the Int32OperationHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public Int32OperationHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for int32 operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
instruction.Operands = $"dword ptr {operand}";
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for register-register operations
|
||||||
|
if (reg == 0) // FCMOVB
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovb";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 1) // FCMOVE
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmove";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 2) // FCMOVBE
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovbe";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 3) // FCMOVU
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovu";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 5 && rm == 1) // FUCOMPP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fucompp";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown instruction
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,213 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point load, store, and control operations (D9 opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class LoadStoreControlHandler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// D9 opcode - load, store, and control operations
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fld",
|
||||||
|
"??",
|
||||||
|
"fst",
|
||||||
|
"fstp",
|
||||||
|
"fldenv",
|
||||||
|
"fldcw",
|
||||||
|
"fnstenv",
|
||||||
|
"fnstcw"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the LoadStoreControlHandler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public LoadStoreControlHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xD9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for load, store, and control operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte)((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte)((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte)(modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
|
||||||
|
// Different operand types based on the instruction
|
||||||
|
if (reg == 0 || reg == 2 || reg == 3) // fld, fst, fstp
|
||||||
|
{
|
||||||
|
instruction.Operands = $"dword ptr {operand}";
|
||||||
|
}
|
||||||
|
else // fldenv, fldcw, fnstenv, fnstcw
|
||||||
|
{
|
||||||
|
instruction.Operands = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for D9C0-D9FF (register-register operations)
|
||||||
|
if (reg == 0) // FLD ST(i)
|
||||||
|
{
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 1) // FXCH ST(i)
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fxch";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 4)
|
||||||
|
{
|
||||||
|
// D9E0-D9EF special instructions
|
||||||
|
switch (rm)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
instruction.Mnemonic = "fchs";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
instruction.Mnemonic = "fabs";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
instruction.Mnemonic = "ftst";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
instruction.Mnemonic = "fxam";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reg == 5)
|
||||||
|
{
|
||||||
|
// D9F0-D9FF special instructions
|
||||||
|
switch (rm)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
instruction.Mnemonic = "f2xm1";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
instruction.Mnemonic = "fyl2x";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
instruction.Mnemonic = "fptan";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
instruction.Mnemonic = "fpatan";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
instruction.Mnemonic = "fxtract";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
instruction.Mnemonic = "fprem1";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
instruction.Mnemonic = "fdecstp";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
instruction.Mnemonic = "fincstp";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reg == 6)
|
||||||
|
{
|
||||||
|
// D9F0-D9FF more special instructions
|
||||||
|
switch (rm)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
instruction.Mnemonic = "fprem";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
instruction.Mnemonic = "fyl2xp1";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
instruction.Mnemonic = "fsqrt";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
instruction.Mnemonic = "fsincos";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
instruction.Mnemonic = "frndint";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
instruction.Mnemonic = "fscale";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
instruction.Mnemonic = "fsin";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
instruction.Mnemonic = "fcos";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point load/store float64 operations (DD opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class LoadStoreFloat64Handler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DD opcode - load/store float64
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fld",
|
||||||
|
"??",
|
||||||
|
"fst",
|
||||||
|
"fstp",
|
||||||
|
"frstor",
|
||||||
|
"fnsave",
|
||||||
|
"fnstsw"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the LoadStoreFloat64Handler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public LoadStoreFloat64Handler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for load/store float64 operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
if (mod != 3) // Memory operand
|
||||||
|
{
|
||||||
|
string operand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
|
||||||
|
if (reg == 0 || reg == 2 || reg == 3) // fld, fst, fstp
|
||||||
|
{
|
||||||
|
instruction.Operands = $"qword ptr {operand}";
|
||||||
|
}
|
||||||
|
else // frstor, fnsave, fnstsw
|
||||||
|
{
|
||||||
|
instruction.Operands = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for register-register operations
|
||||||
|
if (reg == 0) // FFREE
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "ffree";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 2) // FST
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fst";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 3) // FSTP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fstp";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 4) // FUCOM
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fucom";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 5) // FUCOMP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fucomp";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown instruction
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point load/store int16 and miscellaneous operations (DF opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class LoadStoreInt16Handler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DF opcode - load/store int16, misc
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fild",
|
||||||
|
"??",
|
||||||
|
"fist",
|
||||||
|
"fistp",
|
||||||
|
"fbld",
|
||||||
|
"fild",
|
||||||
|
"fbstp",
|
||||||
|
"fistp"
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the LoadStoreInt16Handler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public LoadStoreInt16Handler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for load/store int16 and miscellaneous operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Check for FNSTSW AX (DF E0)
|
||||||
|
if (mod == 3 && reg == 7 && rm == 0)
|
||||||
|
{
|
||||||
|
// This is handled by the FnstswHandler, so we should not handle it here
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
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}";
|
||||||
|
}
|
||||||
|
else // 16-bit integer
|
||||||
|
{
|
||||||
|
instruction.Operands = $"word ptr {operand}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reg == 4 || reg == 6) // fbld, fbstp
|
||||||
|
{
|
||||||
|
instruction.Operands = $"tbyte ptr {operand}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instruction.Operands = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for register-register operations
|
||||||
|
if (reg == 0) // FFREEP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "ffreep";
|
||||||
|
instruction.Operands = $"st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 1 && rm == 0) // FXCH
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fxch";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else if (reg == 2 && rm == 0) // FSTP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fstp";
|
||||||
|
instruction.Operands = "st(1)";
|
||||||
|
}
|
||||||
|
else if (reg == 3 && rm == 0) // FSTP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fstp";
|
||||||
|
instruction.Operands = "st(1)";
|
||||||
|
}
|
||||||
|
else if (reg == 4) // FNSTSW
|
||||||
|
{
|
||||||
|
// This should not happen as FNSTSW AX is handled by FnstswHandler
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else if (reg == 5) // FUCOMIP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fucomip";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 6) // FCOMIP
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcomip";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown instruction
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
namespace X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for floating-point load/store int32 and miscellaneous operations (DB opcode)
|
||||||
|
/// </summary>
|
||||||
|
public class LoadStoreInt32Handler : FloatingPointBaseHandler
|
||||||
|
{
|
||||||
|
// DB opcode - load/store int32, misc
|
||||||
|
private static readonly string[] Mnemonics =
|
||||||
|
[
|
||||||
|
"fild",
|
||||||
|
"??",
|
||||||
|
"fist",
|
||||||
|
"fistp",
|
||||||
|
"??",
|
||||||
|
"fld",
|
||||||
|
"??",
|
||||||
|
"fstp",
|
||||||
|
];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the LoadStoreInt32Handler class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
||||||
|
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
||||||
|
/// <param name="length">The length of the buffer</param>
|
||||||
|
public LoadStoreInt32Handler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
|
: base(codeBuffer, decoder, length)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if this handler can decode the given opcode
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode to check</param>
|
||||||
|
/// <returns>True if this handler can decode the opcode</returns>
|
||||||
|
public override bool CanHandle(byte opcode)
|
||||||
|
{
|
||||||
|
return opcode == 0xDB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decodes a floating-point instruction for load/store int32 and miscellaneous operations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="opcode">The opcode of the instruction</param>
|
||||||
|
/// <param name="instruction">The instruction object to populate</param>
|
||||||
|
/// <returns>True if the instruction was successfully decoded</returns>
|
||||||
|
public override bool Decode(byte opcode, Instruction instruction)
|
||||||
|
{
|
||||||
|
int position = Decoder.GetPosition();
|
||||||
|
|
||||||
|
if (position >= Length)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the ModR/M byte
|
||||||
|
byte modRM = CodeBuffer[position++];
|
||||||
|
Decoder.SetPosition(position);
|
||||||
|
|
||||||
|
// Extract the fields from the ModR/M byte
|
||||||
|
byte mod = (byte) ((modRM & 0xC0) >> 6);
|
||||||
|
byte reg = (byte) ((modRM & 0x38) >> 3);
|
||||||
|
byte rm = (byte) (modRM & 0x07);
|
||||||
|
|
||||||
|
// Set the mnemonic based on the opcode and reg field
|
||||||
|
instruction.Mnemonic = Mnemonics[reg];
|
||||||
|
|
||||||
|
// For memory operands, set the operand
|
||||||
|
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}";
|
||||||
|
}
|
||||||
|
else if (reg == 5 || reg == 7) // fld, fstp (extended precision)
|
||||||
|
{
|
||||||
|
instruction.Operands = $"tword ptr {operand}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instruction.Operands = operand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Register operand (ST(i))
|
||||||
|
{
|
||||||
|
// Special handling for register-register operations
|
||||||
|
if (reg == 0) // FCMOVNB
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovnb";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 1) // FCMOVNE
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovne";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 2) // FCMOVNBE
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovnbe";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 3) // FCMOVNU
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcmovnu";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 4)
|
||||||
|
{
|
||||||
|
if (rm == 2) // FCLEX
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fclex";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else if (rm == 3) // FINIT
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "finit";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reg == 5) // FUCOMI
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fucomi";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else if (reg == 6) // FCOMI
|
||||||
|
{
|
||||||
|
instruction.Mnemonic = "fcomi";
|
||||||
|
instruction.Operands = $"st(0), st({rm})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unknown instruction
|
||||||
|
instruction.Mnemonic = "??";
|
||||||
|
instruction.Operands = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,167 +0,0 @@
|
|||||||
namespace X86Disassembler.X86.Handlers;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handler for floating-point instructions (D8-DF opcodes)
|
|
||||||
/// </summary>
|
|
||||||
public class FloatingPointHandler : InstructionHandler
|
|
||||||
{
|
|
||||||
// Floating-point instruction mnemonics based on opcode and ModR/M reg field
|
|
||||||
private static readonly string[][] FpuMnemonics = new string[8][];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Static constructor to initialize the FPU mnemonic tables
|
|
||||||
/// </summary>
|
|
||||||
static FloatingPointHandler()
|
|
||||||
{
|
|
||||||
InitializeFpuMnemonics();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes the FPU mnemonic tables
|
|
||||||
/// </summary>
|
|
||||||
private static void InitializeFpuMnemonics()
|
|
||||||
{
|
|
||||||
// Initialize all tables
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
FpuMnemonics[i] = new string[8];
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
FpuMnemonics[i][j] = "??";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// D8 opcode - operations on float32
|
|
||||||
FpuMnemonics[0][0] = "fadd";
|
|
||||||
FpuMnemonics[0][1] = "fmul";
|
|
||||||
FpuMnemonics[0][2] = "fcom";
|
|
||||||
FpuMnemonics[0][3] = "fcomp";
|
|
||||||
FpuMnemonics[0][4] = "fsub";
|
|
||||||
FpuMnemonics[0][5] = "fsubr";
|
|
||||||
FpuMnemonics[0][6] = "fdiv";
|
|
||||||
FpuMnemonics[0][7] = "fdivr";
|
|
||||||
|
|
||||||
// D9 opcode - load, store, and control operations
|
|
||||||
FpuMnemonics[1][0] = "fld";
|
|
||||||
FpuMnemonics[1][2] = "fst";
|
|
||||||
FpuMnemonics[1][3] = "fstp";
|
|
||||||
FpuMnemonics[1][4] = "fldenv";
|
|
||||||
FpuMnemonics[1][5] = "fldcw";
|
|
||||||
FpuMnemonics[1][6] = "fnstenv";
|
|
||||||
FpuMnemonics[1][7] = "fnstcw";
|
|
||||||
|
|
||||||
// DA opcode - operations on int32
|
|
||||||
FpuMnemonics[2][0] = "fiadd";
|
|
||||||
FpuMnemonics[2][1] = "fimul";
|
|
||||||
FpuMnemonics[2][2] = "ficom";
|
|
||||||
FpuMnemonics[2][3] = "ficomp";
|
|
||||||
FpuMnemonics[2][4] = "fisub";
|
|
||||||
FpuMnemonics[2][5] = "fisubr";
|
|
||||||
FpuMnemonics[2][6] = "fidiv";
|
|
||||||
FpuMnemonics[2][7] = "fidivr";
|
|
||||||
|
|
||||||
// DB opcode - load/store int32, misc
|
|
||||||
FpuMnemonics[3][0] = "fild";
|
|
||||||
FpuMnemonics[3][2] = "fist";
|
|
||||||
FpuMnemonics[3][3] = "fistp";
|
|
||||||
FpuMnemonics[3][5] = "fld";
|
|
||||||
FpuMnemonics[3][7] = "fstp";
|
|
||||||
|
|
||||||
// DC opcode - operations on float64
|
|
||||||
FpuMnemonics[4][0] = "fadd";
|
|
||||||
FpuMnemonics[4][1] = "fmul";
|
|
||||||
FpuMnemonics[4][2] = "fcom";
|
|
||||||
FpuMnemonics[4][3] = "fcomp";
|
|
||||||
FpuMnemonics[4][4] = "fsub";
|
|
||||||
FpuMnemonics[4][5] = "fsubr";
|
|
||||||
FpuMnemonics[4][6] = "fdiv";
|
|
||||||
FpuMnemonics[4][7] = "fdivr";
|
|
||||||
|
|
||||||
// DD opcode - load/store float64
|
|
||||||
FpuMnemonics[5][0] = "fld";
|
|
||||||
FpuMnemonics[5][2] = "fst";
|
|
||||||
FpuMnemonics[5][3] = "fstp";
|
|
||||||
FpuMnemonics[5][4] = "frstor";
|
|
||||||
FpuMnemonics[5][6] = "fnsave";
|
|
||||||
FpuMnemonics[5][7] = "fnstsw";
|
|
||||||
|
|
||||||
// DE opcode - operations on int16
|
|
||||||
FpuMnemonics[6][0] = "fiadd";
|
|
||||||
FpuMnemonics[6][1] = "fimul";
|
|
||||||
FpuMnemonics[6][2] = "ficom";
|
|
||||||
FpuMnemonics[6][3] = "ficomp";
|
|
||||||
FpuMnemonics[6][4] = "fisub";
|
|
||||||
FpuMnemonics[6][5] = "fisubr";
|
|
||||||
FpuMnemonics[6][6] = "fidiv";
|
|
||||||
FpuMnemonics[6][7] = "fidivr";
|
|
||||||
|
|
||||||
// DF opcode - load/store int16, misc
|
|
||||||
FpuMnemonics[7][0] = "fild";
|
|
||||||
FpuMnemonics[7][2] = "fist";
|
|
||||||
FpuMnemonics[7][3] = "fistp";
|
|
||||||
FpuMnemonics[7][4] = "fbld";
|
|
||||||
FpuMnemonics[7][5] = "fild";
|
|
||||||
FpuMnemonics[7][6] = "fbstp";
|
|
||||||
FpuMnemonics[7][7] = "fistp";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the FloatingPointHandler class
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="codeBuffer">The buffer containing the code to decode</param>
|
|
||||||
/// <param name="decoder">The instruction decoder that owns this handler</param>
|
|
||||||
/// <param name="length">The length of the buffer</param>
|
|
||||||
public FloatingPointHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
|
||||||
: base(codeBuffer, decoder, length)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if this handler can decode the given opcode
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="opcode">The opcode to check</param>
|
|
||||||
/// <returns>True if this handler can decode the opcode</returns>
|
|
||||||
public override bool CanHandle(byte opcode)
|
|
||||||
{
|
|
||||||
return opcode >= 0xD8 && opcode <= 0xDF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decodes a floating-point instruction
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="opcode">The opcode of the instruction</param>
|
|
||||||
/// <param name="instruction">The instruction object to populate</param>
|
|
||||||
/// <returns>True if the instruction was successfully decoded</returns>
|
|
||||||
public override bool Decode(byte opcode, Instruction instruction)
|
|
||||||
{
|
|
||||||
int position = Decoder.GetPosition();
|
|
||||||
|
|
||||||
if (position >= Length)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The opcode index in our tables (0-7 for D8-DF)
|
|
||||||
int opcodeIndex = opcode - 0xD8;
|
|
||||||
|
|
||||||
// Read the ModR/M byte
|
|
||||||
var (mod, reg, rm, operand) = ModRMDecoder.ReadModRM(opcodeIndex == 7); // DF uses 64-bit operands
|
|
||||||
|
|
||||||
// Set the mnemonic based on the opcode and reg field
|
|
||||||
instruction.Mnemonic = FpuMnemonics[opcodeIndex][reg];
|
|
||||||
|
|
||||||
// For memory operands, set the operand
|
|
||||||
if (mod != 3) // Memory operand
|
|
||||||
{
|
|
||||||
instruction.Operands = operand;
|
|
||||||
}
|
|
||||||
else // Register operand (ST(i))
|
|
||||||
{
|
|
||||||
// For register operands, we need to handle the stack registers
|
|
||||||
// This is a simplified implementation and may need to be expanded
|
|
||||||
instruction.Operands = $"st({rm})";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
using X86Disassembler.X86.Handlers.Call;
|
using X86Disassembler.X86.Handlers.Call;
|
||||||
|
using X86Disassembler.X86.Handlers.FloatingPoint;
|
||||||
using X86Disassembler.X86.Handlers.Group1;
|
using X86Disassembler.X86.Handlers.Group1;
|
||||||
using X86Disassembler.X86.Handlers.Group3;
|
using X86Disassembler.X86.Handlers.Group3;
|
||||||
using X86Disassembler.X86.Handlers.Jump;
|
using X86Disassembler.X86.Handlers.Jump;
|
||||||
@ -68,8 +69,7 @@ public class InstructionHandlerFactory
|
|||||||
RegisterDataTransferHandlers();
|
RegisterDataTransferHandlers();
|
||||||
|
|
||||||
// Register floating point handlers
|
// Register floating point handlers
|
||||||
_handlers.Add(new FnstswHandler(_codeBuffer, _decoder, _length));
|
RegisterFloatingPointHandlers();
|
||||||
_handlers.Add(new FloatingPointHandler(_codeBuffer, _decoder, _length));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -220,6 +220,23 @@ public class InstructionHandlerFactory
|
|||||||
_handlers.Add(new XchgEaxRegHandler(_codeBuffer, _decoder, _length));
|
_handlers.Add(new XchgEaxRegHandler(_codeBuffer, _decoder, _length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers all Floating Point instruction handlers
|
||||||
|
/// </summary>
|
||||||
|
private void RegisterFloatingPointHandlers()
|
||||||
|
{
|
||||||
|
// Add Floating Point handlers
|
||||||
|
_handlers.Add(new FnstswHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new Float32OperationHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new LoadStoreControlHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new Int32OperationHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new LoadStoreInt32Handler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new Float64OperationHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new LoadStoreFloat64Handler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new Int16OperationHandler(_codeBuffer, _decoder, _length));
|
||||||
|
_handlers.Add(new LoadStoreInt16Handler(_codeBuffer, _decoder, _length));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the handler that can decode the given opcode
|
/// Gets the handler that can decode the given opcode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -5,9 +5,6 @@ namespace X86Disassembler.X86.Handlers.Test;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TestRegMem8Handler : InstructionHandler
|
public class TestRegMem8Handler : InstructionHandler
|
||||||
{
|
{
|
||||||
// ModR/M decoder
|
|
||||||
private readonly ModRMDecoder _modRMDecoder;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the TestRegMem8Handler class
|
/// Initializes a new instance of the TestRegMem8Handler class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -17,7 +14,6 @@ public class TestRegMem8Handler : InstructionHandler
|
|||||||
public TestRegMem8Handler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
public TestRegMem8Handler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
: base(codeBuffer, decoder, length)
|
: base(codeBuffer, decoder, length)
|
||||||
{
|
{
|
||||||
_modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -73,7 +69,7 @@ public class TestRegMem8Handler : InstructionHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decode the memory operand
|
// Decode the memory operand
|
||||||
string memOperand = _modRMDecoder.DecodeModRM(mod, rm, true);
|
string memOperand = ModRMDecoder.DecodeModRM(mod, rm, true);
|
||||||
|
|
||||||
// Get the register name
|
// Get the register name
|
||||||
string regReg = GetRegister8(reg);
|
string regReg = GetRegister8(reg);
|
||||||
@ -84,15 +80,4 @@ public class TestRegMem8Handler : InstructionHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 8-bit register name for the given register index
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reg">The register index</param>
|
|
||||||
/// <returns>The register name</returns>
|
|
||||||
private static string GetRegister8(byte reg)
|
|
||||||
{
|
|
||||||
string[] registerNames = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
|
|
||||||
return registerNames[reg & 0x07];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,6 @@ namespace X86Disassembler.X86.Handlers.Test;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TestRegMemHandler : InstructionHandler
|
public class TestRegMemHandler : InstructionHandler
|
||||||
{
|
{
|
||||||
// ModR/M decoder
|
|
||||||
private readonly ModRMDecoder _modRMDecoder;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the TestRegMemHandler class
|
/// Initializes a new instance of the TestRegMemHandler class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -17,7 +14,6 @@ public class TestRegMemHandler : InstructionHandler
|
|||||||
public TestRegMemHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
public TestRegMemHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
: base(codeBuffer, decoder, length)
|
: base(codeBuffer, decoder, length)
|
||||||
{
|
{
|
||||||
_modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -73,7 +69,7 @@ public class TestRegMemHandler : InstructionHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Decode the memory operand
|
// Decode the memory operand
|
||||||
string memOperand = _modRMDecoder.DecodeModRM(mod, rm, false);
|
string memOperand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
|
||||||
// Get the register name
|
// Get the register name
|
||||||
string regReg = GetRegister32(reg);
|
string regReg = GetRegister32(reg);
|
||||||
@ -84,15 +80,4 @@ public class TestRegMemHandler : InstructionHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 32-bit register name for the given register index
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reg">The register index</param>
|
|
||||||
/// <returns>The register name</returns>
|
|
||||||
private static string GetRegister32(byte reg)
|
|
||||||
{
|
|
||||||
string[] registerNames = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
|
|
||||||
return registerNames[reg & 0x07];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,6 @@ namespace X86Disassembler.X86.Handlers.Xor;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class XorMemRegHandler : InstructionHandler
|
public class XorMemRegHandler : InstructionHandler
|
||||||
{
|
{
|
||||||
// ModR/M decoder
|
|
||||||
private readonly ModRMDecoder _modRMDecoder;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the XorMemRegHandler class
|
/// Initializes a new instance of the XorMemRegHandler class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -17,7 +14,6 @@ public class XorMemRegHandler : InstructionHandler
|
|||||||
public XorMemRegHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
public XorMemRegHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
: base(codeBuffer, decoder, length)
|
: base(codeBuffer, decoder, length)
|
||||||
{
|
{
|
||||||
_modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -58,7 +54,7 @@ public class XorMemRegHandler : InstructionHandler
|
|||||||
byte rm = (byte)(modRM & 0x07);
|
byte rm = (byte)(modRM & 0x07);
|
||||||
|
|
||||||
// Decode the destination operand
|
// Decode the destination operand
|
||||||
string destOperand = _modRMDecoder.DecodeModRM(mod, rm, false);
|
string destOperand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
|
||||||
// Get the source register
|
// Get the source register
|
||||||
string srcReg = GetRegister32(reg);
|
string srcReg = GetRegister32(reg);
|
||||||
@ -68,15 +64,4 @@ public class XorMemRegHandler : InstructionHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 32-bit register name for the given register index
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reg">The register index</param>
|
|
||||||
/// <returns>The register name</returns>
|
|
||||||
private static string GetRegister32(byte reg)
|
|
||||||
{
|
|
||||||
string[] registerNames = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
|
|
||||||
return registerNames[reg & 0x07];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,6 @@ namespace X86Disassembler.X86.Handlers.Xor;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class XorRegMemHandler : InstructionHandler
|
public class XorRegMemHandler : InstructionHandler
|
||||||
{
|
{
|
||||||
// ModR/M decoder
|
|
||||||
private readonly ModRMDecoder _modRMDecoder;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the XorRegMemHandler class
|
/// Initializes a new instance of the XorRegMemHandler class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -17,7 +14,6 @@ public class XorRegMemHandler : InstructionHandler
|
|||||||
public XorRegMemHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
public XorRegMemHandler(byte[] codeBuffer, InstructionDecoder decoder, int length)
|
||||||
: base(codeBuffer, decoder, length)
|
: base(codeBuffer, decoder, length)
|
||||||
{
|
{
|
||||||
_modRMDecoder = new ModRMDecoder(codeBuffer, decoder, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -58,7 +54,7 @@ public class XorRegMemHandler : InstructionHandler
|
|||||||
byte rm = (byte)(modRM & 0x07);
|
byte rm = (byte)(modRM & 0x07);
|
||||||
|
|
||||||
// Decode the source operand
|
// Decode the source operand
|
||||||
string srcOperand = _modRMDecoder.DecodeModRM(mod, rm, false);
|
string srcOperand = ModRMDecoder.DecodeModRM(mod, rm, false);
|
||||||
|
|
||||||
// Get the destination register
|
// Get the destination register
|
||||||
string destReg = GetRegister32(reg);
|
string destReg = GetRegister32(reg);
|
||||||
@ -68,15 +64,4 @@ public class XorRegMemHandler : InstructionHandler
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the 32-bit register name for the given register index
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="reg">The register index</param>
|
|
||||||
/// <returns>The register name</returns>
|
|
||||||
private static string GetRegister32(byte reg)
|
|
||||||
{
|
|
||||||
string[] registerNames = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
|
|
||||||
return registerNames[reg & 0x07];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user