private X86Operand GetRegOrMemOperand32(byte registerToken, X86OperandSize size)
{
// Mechanism:
// http://ref.x86asm.net/coder32.html#modrm_byte_32
// ModR/M byte:
// mod | reg/mem | (reg2)
// -----+---------+-------
// 7 6 | 5 4 3 | (2 1 0)
var modifier = (X86RegOrMemModifier)(registerToken >> 6);
var operand = new X86Operand();
// Register-only operands:
if (modifier == X86RegOrMemModifier.RegisterOnly)
{
operand.Value = GetRegisterFromToken((byte)(registerToken & 0x7), GetRegisterSize(size));
operand.OperandUsage = X86OperandUsage.Normal;
return operand;
}
// Register-pointer operands are always 32-bit registers.
var register = GetRegisterFromToken((byte)(registerToken & 0x7), X86RegisterSize.Dword);
operand.OperandUsage = GetOperandType(size);
operand.Value = register;
// EBP register is replaced by a direct address.
if (modifier == X86RegOrMemModifier.RegisterPointer && register == X86Register.Ebp)
{
operand.Value = _reader.ReadUInt32();
return operand;
}
// ESP register are replaced by a scaled index operand.
if (register == X86Register.Esp)
MakeScaledIndexOperandFromToken(operand, _reader.ReadByte());
// Read correction based on modifier.
switch (modifier)
{
case X86RegOrMemModifier.RegisterDispShortPointer:
operand.Offset = _reader.ReadSByte();
operand.OffsetType = X86OffsetType.Short;
break;
case X86RegOrMemModifier.RegisterDispLongPointer:
operand.Offset = _reader.ReadInt32();
operand.OffsetType = X86OffsetType.Long;
break;
}
return operand;
}