/// <summary> /// Encodes the displacement in the <see cref="EncodedInstruction"/>. /// </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> /// <param name="addressSize">The address size used by the effective address.</param> void EncodeDisplacement(Context context, EncodedInstruction instr, DataSize addressSize) { DataSize displacementSize = DataSize.None; ReferenceOffset displacementExpression = null; if (Displacement != null) { // Let's evaluate the displacement expression. displacementExpression = Displacement.Compile()(context); // Determine the size of the displacement. displacementSize = addressSize; if (displacementSize == DataSize.None) { // Does the result have a (resolved or not resolved) reference? if (displacementExpression.Reference != null && !displacementExpression.Reference.Resolved) { // When the result has a reference, use the architecture's address size. displacementSize = context.AddressingMode; } else { // Otherwise, use the most efficient word size. displacementSize = Extensions.GetSizeOfValue(displacementExpression.Evaluate(context)); } } } instr.DisplacementSize = displacementSize; instr.Displacement = displacementExpression; }
/// <summary> /// Emits the immediate value as part of the instruction, if any. /// </summary> /// <param name="writer">The <see cref="BinaryWriter"/> to which the encoded instruction is written.</param> /// <param name="instructionOffset">The offset of the instruction in the stream underlying /// <paramref name="writer"/>.</param> /// <param name="context">The <see cref="Context"/> of the instruction.</param> /// <param name="expression">The <see cref="ReferenceOffset"/> to emit.</param> /// <param name="size">The size of the value to emit.</param> void EmitReferenceOffset(BinaryWriter writer, long instructionOffset, Context context, ReferenceOffset expression, DataSize size) { if (expression == null) { return; } // Number of bytes before the expression. var relocationDiff = (ulong)(writer.BaseStream.Position - instructionOffset); Relocation relocation = null; var actualValue = expression.Evaluate(context); if (expression.Reference != null) { relocation = new Relocation(expression.Reference.Symbol, (long)context.Address, actualValue, RelocationType.Default32); } // Emit the expression's value. EmitConstant(writer, size, actualValue); // Add the relocation to the context. if (relocation != null) { relocation.Offset += (long)relocationDiff; context.RelocationTable.Add(relocation); } }