/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { if (context.AddressingMode != DataSize.Bit64 && Register.Size == DataSize.Bit64) { throw new AssemblerException($"The 64-bit register {Register} cannot be used with non-64-bit operand sizes."); } // Encode the register as part of the opcode or ModRM byte. switch (Encoding) { case OperandEncoding.Default: instruction.SetModRMByte(); instruction.ModRM.Reg = Register.Value; break; case OperandEncoding.AddToOpcode: instruction.OpcodeReg = (byte)(Register.Value & 0xF); break; case OperandEncoding.ModRm: instruction.SetModRMByte(); instruction.ModRM.Mod = 0x03; instruction.ModRM.RM = Register.Value; break; case OperandEncoding.Ignore: // The operand is ignored. break; } // Set the operand size to the size of the register. instruction.SetOperandSize(context.AddressingMode, Register.Size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { // Determine the size of the immediate operand. Otherwise the length is not calculated correctly. DataSize size = PreferredSize; if (size == DataSize.None) { size = context.AddressingMode; } if (size >= DataSize.Bit64) { var bit = ((int)size) << 3; throw new AssemblerException($"{bit}-bit operands cannot be encoded."); } else if (size == DataSize.None) { throw new AssemblerException("The operand size is not specified."); } instruction.SetOperandSize(context.AddressingMode, size); instruction.ImmediateSize = size; // Let's evaluate the expression. var result = Expression?.Compile()(context); result = new ReferenceOffset(result.Reference, result.Constant - ((long)context.Address + instruction.Length)); instruction.Immediate = result; }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="X86Context"/> in which the /// operand is used.</param> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the /// operand.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="context"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="instr"/> is <see langword="null"/>.</para> /// </exception> internal override void Construct(X86Context context, EncodedInstruction instr) { #region Contract if (context == null) { throw new ArgumentNullException("context"); } if (instr == null) { throw new ArgumentNullException("instr"); } #endregion // Let's evaluate the expression. ExpressionResult result = new BinaryExpression( expression, BinaryOperation.Subtract, new BinaryExpression( new CurrentPosition(), BinaryOperation.Add, new Constant((long)instr.GetLength()))).Evaluate(context); // Determine the size of the immediate operand. DataSize size = RequestedSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.HasReference) { // When the result has a reference, use the architecture's operand size. size = context.Representation.Architecture.OperandSize; } else { // Otherwise, use the most efficient word size. size = result.Constant.GetSize(); } } if (size >= DataSize.Bit64) { throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable); } else if (size == DataSize.None) { throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified); } // Set the parameters. instr.Immediate = result; instr.ImmediateSize = size; instr.SetOperandSize(context.Representation.Architecture.OperandSize, size); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand SimpleExpression offsetResult = offset(context); SimpleExpression selectorResult = selector(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (offsetResult.Reference != null) { // When the result has a reference, use the architecture's operand size. size = context.Representation.Architecture.OperandSize; } else { // Otherwise, use the most efficient word size. size = MathExt.GetSizeOfValue(offsetResult.Constant); } } if (size <= DataSize.Bit8) { size = DataSize.Bit16; } if (size > DataSize.Bit64) { throw new AssemblerException("The operand cannot be encoded."); } else if (size == DataSize.None) { throw new AssemblerException("The operand size is not specified."); } // Set the parameters. instr.Immediate = offsetResult; instr.ImmediateSize = size; instr.ExtraImmediate = selectorResult; instr.ExtraImmediateSize = (DataSize)2; instr.SetOperandSize(context.Representation.Architecture.OperandSize, size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { // Let's evaluate the expression. var result = Expression?.Compile()(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.Reference != null) { // When the result has a reference, use the architecture's operand size. size = context.AddressingMode; } else { // Otherwise, use the most efficient word size. size = Extensions.GetSizeOfValue(result.Constant); } } if (size > DataSize.Bit64) { throw new AssemblerException("Operands with more than 64 bits cannot be encoded."); } else if (size == DataSize.None) { throw new AssemblerException("The operand size is not specified."); } // Set the parameters. if (!asExtraImmediate) { instruction.Immediate = result; instruction.ImmediateSize = size; } else { instruction.ExtraImmediate = result; instruction.ExtraImmediateSize = size; } instruction.SetOperandSize(context.AddressingMode, size); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand // Let's evaluate the expression. SimpleExpression result = expression(context); result = new SimpleExpression(result.Reference, result.Constant - (context.Address + instr.GetLength())); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.Reference != null) { // When the result has a reference, use the architecture's operand size. size = context.Representation.Architecture.OperandSize; } else { // Otherwise, use the most efficient word size. size = MathExt.GetSizeOfValue(result.Constant); } } if (size >= DataSize.Bit64) { throw new AssemblerException(String.Format(CultureInfo.InvariantCulture, "{0}-bit operands cannot be encoded.", ((int)size) << 3)); } else if (size == DataSize.None) { throw new AssemblerException("The operand size is not specified."); } // Set the parameters. instr.Immediate = result; instr.ImmediateSize = size; instr.SetOperandSize(context.Representation.Architecture.OperandSize, size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { DataSize addressSize = GetAddressSize(context); instruction.SetOperandSize(context.AddressingMode, Size); if (context.AddressingMode != DataSize.Bit64 && Size == DataSize.Bit64) { throw new AssemblerException("A 64-bit operand cannot be used with non-64-bit operand sizes."); } if (context.AddressingMode != DataSize.Bit64 && addressSize == DataSize.Bit64) { throw new AssemblerException("A 64-bit effective address cannot be used with non-64-bit address sizes."); } EncodeDisplacement(context, instruction, addressSize); switch (addressSize) { case DataSize.Bit16: Encode16BitEffectiveAddress(instruction); break; case DataSize.Bit32: Encode32BitEffectiveAddress(instruction); break; case DataSize.Bit64: Encode64BitEffectiveAddress(context, instruction); break; default: throw new NotSupportedException(); } // Address size prefix. // When the registers have a width different from the current // operating mode width, then we have to add an address size prefix. // At this point, we know that the widths are valid. instruction.SetAddressSize(context.AddressingMode, addressSize); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { ReferenceOffset offsetResult = Offset.Compile()(context); ReferenceOffset selectorResult = Selector?.Compile()(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (offsetResult.Reference != null) { // When the result has a reference, use the architecture's operand size. size = context.AddressingMode; } else { // Otherwise, use the most efficient word size. size = Extensions.GetSizeOfValue(offsetResult.Constant); } } if (size <= DataSize.Bit8) { size = DataSize.Bit16; } if (size > DataSize.Bit64) { throw new AssemblerException("The operand cannot be encoded."); } // Set the parameters. instruction.Immediate = offsetResult; instruction.ImmediateSize = size; instruction.ExtraImmediate = selectorResult; instruction.ExtraImmediateSize = (DataSize)2; instruction.SetOperandSize(context.AddressingMode, size); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand if (context.Representation.Architecture.OperandSize != DataSize.Bit64 && register.GetSize() == DataSize.Bit64) { throw new AssemblerException(String.Format( "The 64-bit register {0} cannot be used with non-64-bit operand sizes.", Enum.GetName(typeof(Register), register))); } // Encode the register as part of the opcode or ModRM byte. switch (encoding) { case OperandEncoding.Default: instr.SetModRMByte(); instr.ModRM.Reg = Register.GetValue(); break; case OperandEncoding.AddToOpcode: instr.OpcodeReg = Register.GetValue(); break; case OperandEncoding.ModRm: instr.SetModRMByte(); instr.ModRM.Mod = 0x03; instr.ModRM.RM = Register.GetValue(); break; case OperandEncoding.Ignore: // The operand is ignored. break; } // Set the operand size to the size of the register. instr.SetOperandSize(context.Representation.Architecture.OperandSize, Register.GetSize()); }
/// <summary> /// Constructs the representation of this instruction variant using the specified operands. /// </summary> /// <param name="context">The <see cref="Context"/> used.</param> /// <param name="operands">The <see cref="Operand"/> objects to encode.</param> /// <param name="lockPrefix">Whether to use a lock prefix.</param> /// <returns>The encoded instruction.</returns> public EncodedInstruction Construct(Context context, IEnumerable<IConstructableOperand> operands, bool lockPrefix) { #region Contract Contract.Requires<ArgumentNullException>(context != null); Contract.Requires<ArgumentNullException>(operands != null); Contract.Ensures(Contract.Result<EncodedInstruction>() != null); #endregion EncodedInstruction instr = new EncodedInstruction(); // Set the lock prefix. instr.SetLock(lockPrefix); // Set the opcode. instr.Opcode = opcode; // Set the fixed REG value, if any. instr.FixedReg = fixedReg; int i = 0; foreach(var operand in operands) { if (operand == null) // No operand. Nothing to do. continue; if (i >= descriptors.Length) // No descriptors left. Nothing to be done. break; operand.Adjust(descriptors[i]); operand.Construct(context, instr); i++; } // When the operand size has been explicitly set, set it on the encoded instruction. if (operandSize != DataSize.None) instr.SetOperandSize(context.Representation.Architecture.OperandSize, operandSize); // We are done. return instr; }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="X86Context"/> in which the /// operand is used.</param> /// <param name="instr">The <see cref="EncodedInstruction"/> encoding the /// operand.</param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="context"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="instr"/> is <see langword="null"/>.</para> /// </exception> internal override void Construct(X86Context context, EncodedInstruction instr) { #region Contract if (context == null) throw new ArgumentNullException("context"); if (instr == null) throw new ArgumentNullException("instr"); #endregion // Let's evaluate the expression. ExpressionResult result = new BinaryExpression( expression, BinaryOperation.Subtract, new BinaryExpression( new CurrentPosition(), BinaryOperation.Add, new Constant((long)instr.GetLength()))).Evaluate(context); // Determine the size of the immediate operand. DataSize size = RequestedSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.HasReference) // When the result has a reference, use the architecture's operand size. size = context.Representation.Architecture.OperandSize; else // Otherwise, use the most efficient word size. size = result.Constant.GetSize(); } if (size >= DataSize.Bit64) throw new AssemblerException(ExceptionStrings.OperandSizeNotEncodable); else if (size == DataSize.None) throw new AssemblerException(ExceptionStrings.OperandSizeNotSpecified); // Set the parameters. instr.Immediate = result; instr.ImmediateSize = size; instr.SetOperandSize(context.Representation.Architecture.OperandSize, size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { if (context.AddressingMode != DataSize.Bit64 && Register.Size == DataSize.Bit64) throw new AssemblerException($"The 64-bit register {Register} cannot be used with non-64-bit operand sizes."); // Encode the register as part of the opcode or ModRM byte. switch (Encoding) { case OperandEncoding.Default: instruction.SetModRMByte(); instruction.ModRM.Reg = Register.Value; break; case OperandEncoding.AddToOpcode: instruction.OpcodeReg = (byte)(Register.Value & 0xF); break; case OperandEncoding.ModRm: instruction.SetModRMByte(); instruction.ModRM.Mod = 0x03; instruction.ModRM.RM = Register.Value; break; case OperandEncoding.Ignore: // The operand is ignored. break; } // Set the operand size to the size of the register. instruction.SetOperandSize(context.AddressingMode, Register.Size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { ReferenceOffset offsetResult = Offset.Compile()(context); ReferenceOffset selectorResult = Selector?.Compile()(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (offsetResult.Reference != null) // When the result has a reference, use the architecture's operand size. size = context.AddressingMode; else // Otherwise, use the most efficient word size. size = Extensions.GetSizeOfValue(offsetResult.Constant); } if (size <= DataSize.Bit8) size = DataSize.Bit16; if (size > DataSize.Bit64) throw new AssemblerException("The operand cannot be encoded."); // Set the parameters. instruction.Immediate = offsetResult; instruction.ImmediateSize = size; instruction.ExtraImmediate = selectorResult; instruction.ExtraImmediateSize = (DataSize)2; instruction.SetOperandSize(context.AddressingMode, size); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand // Let's evaluate the expression. SimpleExpression result = expression(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.Reference != null) // When the result has a reference, use the architecture's operand size. size = context.Representation.Architecture.OperandSize; else // Otherwise, use the most efficient word size. size = MathExt.GetSizeOfValue(result.Constant); } if (size >= DataSize.Bit64) throw new AssemblerException("64-bit operands cannot be encoded."); else if (size == DataSize.None) throw new AssemblerException("The operand size is not specified."); // Set the parameters. if (!asExtraImmediate) { instr.Immediate = result; instr.ImmediateSize = size; } else { instr.ExtraImmediate = result; instr.ExtraImmediateSize = size; } instr.SetOperandSize(context.Representation.Architecture.OperandSize, size); }
/// <summary> /// Constructs the operand's representation. /// </summary> /// <param name="context">The <see cref="Context"/> in which the operand is used.</param> /// <param name="instruction">The <see cref="EncodedInstruction"/> encoding the operand.</param> public override void Construct(Context context, EncodedInstruction instruction) { // Let's evaluate the expression. var result = Expression?.Compile()(context); // Determine the size of the immediate operand. DataSize size = PreferredSize; if (size == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (result.Reference != null) // When the result has a reference, use the architecture's operand size. size = context.AddressingMode; else // Otherwise, use the most efficient word size. size = Extensions.GetSizeOfValue(result.Constant); } if (size > DataSize.Bit64) throw new AssemblerException("Operands with more than 64 bits cannot be encoded."); else if (size == DataSize.None) throw new AssemblerException("The operand size is not specified."); // Set the parameters. if (!asExtraImmediate) { instruction.Immediate = result; instruction.ImmediateSize = size; } else { instruction.ExtraImmediate = result; instruction.ExtraImmediateSize = size; } instruction.SetOperandSize(context.AddressingMode, size); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand DataSize addressSize = GetAddressSize(context); instr.SetOperandSize(context.Representation.Architecture.OperandSize, Size); if (context.Representation.Architecture.OperandSize != DataSize.Bit64 && this.Size == DataSize.Bit64) throw new AssemblerException("A 64-bit operand cannot be used with non-64-bit operand sizes."); if (context.Representation.Architecture.AddressSize != DataSize.Bit64 && addressSize == DataSize.Bit64) throw new AssemblerException("A 64-bit effective address cannot be used with non-64-bit address sizes."); EncodeDisplacement(context, instr, addressSize); switch(addressSize) { case DataSize.Bit16: Encode16BitEffectiveAddress(instr); break; case DataSize.Bit32: Encode32BitEffectiveAddress(instr); break; case DataSize.Bit64: Encode64BitEffectiveAddress(context, instr); break; default: throw new NotSupportedException(); } // Address size prefix. // When the registers have a width different from the current // operating mode width, then we have to add an address size prefix. // At this point, we know that the widths are valid. instr.SetAddressSize(context.Representation.Architecture.AddressSize, addressSize); }
/// <summary> /// Constructs the operand's representation. /// </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> internal override void Construct(Context context, EncodedInstruction instr) { // CONTRACT: Operand if (context.Representation.Architecture.OperandSize != DataSize.Bit64 && register.GetSize() == DataSize.Bit64) { throw new AssemblerException(String.Format( "The 64-bit register {0} cannot be used with non-64-bit operand sizes.", Enum.GetName(typeof(Register), register))); } // Encode the register as part of the opcode or ModRM byte. switch (encoding) { case OperandEncoding.Default: instr.SetModRMByte(); instr.ModRM.Reg = Register.GetValue(); break; case OperandEncoding.AddToOpcode: instr.OpcodeReg = Register.GetValue(); break; case OperandEncoding.ModRm: instr.SetModRMByte(); instr.ModRM.Mod = 0x03; instr.ModRM.RM = Register.GetValue(); break; case OperandEncoding.Ignore: // The operand is ignored. break; } // Set the operand size to the size of the register. instr.SetOperandSize(context.Representation.Architecture.OperandSize, Register.GetSize()); }