/// <summary> /// Encodes a 32-bit effective address. /// </summary> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param> private void Encode32BitEffectiveAddress(EncodedInstruction instr) { instr.SetModRMByte(); if (baseRegister == Register.None && indexRegister == Register.None) { // R/M instr.ModRM.RM = 0x05; // Mod instr.ModRM.Mod = 0x00; // Only 32-bit displacements can be encoded without a base and index register. instr.DisplacementSize = DataSize.Bit32; if (instr.Displacement == null) { instr.Displacement = new SimpleExpression(0); } } else if (baseRegister != Register.ESP && indexRegister == Register.None) { // R/M instr.ModRM.RM = (byte)((int)baseRegister & 0x07); // Displacement. if (instr.Displacement == null && baseRegister == Register.EBP) { // [EBP] will be represented as [EBP+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new SimpleExpression(0); } // Mod if (instr.DisplacementSize == DataSize.None) { instr.ModRM.Mod = 0x00; } else if (instr.DisplacementSize == DataSize.Bit8) { instr.ModRM.Mod = 0x01; } else if (instr.DisplacementSize <= DataSize.Bit32) { instr.ModRM.Mod = 0x02; } } else { // Encode the SIB byte too. instr.SetSIBByte(); // R/M instr.ModRM.RM = 0x04; // Displacement if (instr.Displacement == null && baseRegister == Register.EBP) { // [EBP+REG*s] will be represented as [EBP+REG*s+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new SimpleExpression(0); } // Mod if (instr.DisplacementSize == DataSize.None) { instr.ModRM.Mod = 0x00; } else if (instr.DisplacementSize == DataSize.Bit8) { instr.ModRM.Mod = 0x01; } else if (instr.DisplacementSize <= DataSize.Bit32) { instr.ModRM.Mod = 0x02; } // Base instr.Sib.Base = (byte)((int)baseRegister & 0x07); if (baseRegister == Register.None) { instr.Sib.Base = 0x05; } // Index instr.Sib.Index = (byte)((int)indexRegister & 0x07); if (indexRegister == Register.None) { instr.Sib.Index = 0x20; } // Scale instr.Sib.Scale = (byte)((int)Math.Log(scale, 2)); } }
/// <summary> /// Encodes a 64-bit effective address. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param> void Encode64BitEffectiveAddress(Context context, EncodedInstruction instr) { instr.SetModRMByte(); bool ripRelative = RelativeAddress ?? context.UseRIPRelativeAddressing; bool forceRipRelative = RelativeAddress.HasValue && RelativeAddress == true; if (BaseRegister.IsNone && IndexRegister.IsNone) { if (ripRelative) { // [RIP+disp32] instr.ModRM.RM = 0x05; instr.ModRM.Mod = 0x00; } else { // [disp32] instr.ModRM.RM = 0x04; instr.ModRM.Mod = 0x00; instr.SetSIBByte(); instr.Sib.Base = 0x05; instr.Sib.Index = 0x04; instr.Sib.Scale = 0x00; } // Only 32-bit displacements can be encoded without a base and index register. instr.DisplacementSize = DataSize.Bit32; if (instr.Displacement == null) instr.Displacement = new ReferenceOffset(0); } else { if (forceRipRelative) throw new AssemblerException("The effective address cannot be encoded with RIP-relative addressing."); if (BaseRegister != Register.RSP && IndexRegister.IsNone) { // [REG+...] instr.ModRM.RM = BaseRegister.Value; } else { // [REG+REG*s+...] // Encode the SIB byte too. instr.SetSIBByte(); // R/M instr.ModRM.RM = 0x04; // Base if (!BaseRegister.IsNone) instr.Sib.Base = BaseRegister.Value; else instr.Sib.Base = 0x05; // Index if (!IndexRegister.IsNone) instr.Sib.Index = IndexRegister.Value; else instr.Sib.Index = 0x20; // Scale instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2)); } if (instr.Displacement == null && BaseRegister == Register.RBP) { // [RBP] will be represented as [RBP+disp8]. // [RBP+REG*s] will be represented as [RBP+REG*s+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new ReferenceOffset(0); } switch (instr.DisplacementSize) { case DataSize.None: instr.ModRM.Mod = 0x00; break; case DataSize.Bit8: instr.ModRM.Mod = 0x01; break; case DataSize.Bit16: case DataSize.Bit32: instr.ModRM.Mod = 0x02; break; default: throw new NotSupportedException(); } } }
/// <summary> /// Encodes a 64-bit effective address. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param> void Encode64BitEffectiveAddress(Context context, EncodedInstruction instr) { instr.SetModRMByte(); bool ripRelative = RelativeAddress ?? context.UseRIPRelativeAddressing; bool forceRipRelative = RelativeAddress.HasValue && RelativeAddress == true; if (BaseRegister.IsNone && IndexRegister.IsNone) { if (ripRelative) { // [RIP+disp32] instr.ModRM.RM = 0x05; instr.ModRM.Mod = 0x00; } else { // [disp32] instr.ModRM.RM = 0x04; instr.ModRM.Mod = 0x00; instr.SetSIBByte(); instr.Sib.Base = 0x05; instr.Sib.Index = 0x04; instr.Sib.Scale = 0x00; } // Only 32-bit displacements can be encoded without a base and index register. instr.DisplacementSize = DataSize.Bit32; if (instr.Displacement == null) { instr.Displacement = new ReferenceOffset(0); } } else { if (forceRipRelative) { throw new AssemblerException("The effective address cannot be encoded with RIP-relative addressing."); } if (BaseRegister != Register.RSP && IndexRegister.IsNone) { // [REG+...] instr.ModRM.RM = BaseRegister.Value; } else { // [REG+REG*s+...] // Encode the SIB byte too. instr.SetSIBByte(); // R/M instr.ModRM.RM = 0x04; // Base if (!BaseRegister.IsNone) { instr.Sib.Base = BaseRegister.Value; } else { instr.Sib.Base = 0x05; } // Index if (!IndexRegister.IsNone) { instr.Sib.Index = IndexRegister.Value; } else { instr.Sib.Index = 0x20; } // Scale instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2)); } if (instr.Displacement == null && BaseRegister == Register.RBP) { // [RBP] will be represented as [RBP+disp8]. // [RBP+REG*s] will be represented as [RBP+REG*s+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new ReferenceOffset(0); } switch (instr.DisplacementSize) { case DataSize.None: instr.ModRM.Mod = 0x00; break; case DataSize.Bit8: instr.ModRM.Mod = 0x01; break; case DataSize.Bit16: case DataSize.Bit32: instr.ModRM.Mod = 0x02; break; default: throw new NotSupportedException(); } } }
/// <summary> /// Encodes a 32-bit effective address. /// </summary> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the operand.</param> void Encode32BitEffectiveAddress(EncodedInstruction instr) { instr.SetModRMByte(); if (BaseRegister.IsNone && IndexRegister.IsNone) { // R/M instr.ModRM.RM = 0x05; // Mod instr.ModRM.Mod = 0x00; // Only 32-bit displacements can be encoded without a base and index register. instr.DisplacementSize = DataSize.Bit32; if (instr.Displacement == null) instr.Displacement = new ReferenceOffset(0); } else if (BaseRegister != Register.ESP && IndexRegister.IsNone) { // R/M instr.ModRM.RM = (byte)(BaseRegister.Full & 0x07); // Displacement. if (instr.Displacement == null && BaseRegister == Register.EBP) { // [EBP] will be represented as [EBP+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new ReferenceOffset(0); } // Mod if (instr.DisplacementSize == DataSize.None) instr.ModRM.Mod = 0x00; else if (instr.DisplacementSize == DataSize.Bit8) instr.ModRM.Mod = 0x01; else if (instr.DisplacementSize <= DataSize.Bit32) instr.ModRM.Mod = 0x02; } else { // Encode the SIB byte too. instr.SetSIBByte(); // R/M instr.ModRM.RM = 0x04; // Displacement if (instr.Displacement == null && BaseRegister == Register.EBP) { // [EBP+REG*s] will be represented as [EBP+REG*s+disp8]. instr.DisplacementSize = DataSize.Bit8; instr.Displacement = new ReferenceOffset(0); } // Mod if (instr.DisplacementSize == DataSize.None) instr.ModRM.Mod = 0x00; else if (instr.DisplacementSize == DataSize.Bit8) instr.ModRM.Mod = 0x01; else if (instr.DisplacementSize <= DataSize.Bit32) instr.ModRM.Mod = 0x02; // Base instr.Sib.Base = (byte)(BaseRegister.Full & 0x07); if (BaseRegister.IsNone) instr.Sib.Base = 0x05; // Index instr.Sib.Index = (byte)(IndexRegister.Full & 0x07); if (IndexRegister.IsNone) instr.Sib.Index = 0x20; // Scale instr.Sib.Scale = (byte)((int)Math.Log(Scale, 2)); } }