/// <summary> /// Consumes the next byte, word, or dword. /// </summary> /// <returns>The next byte, word, or dword, sign-extended.</returns> public Operand.LocationAware <int> ReadImmediate(CpuSize size) { int pos = this.Position; int value; if (size == CpuSize.Use8Bit) { value = (sbyte)ReadByte(); } else if (size == CpuSize.Use16Bit) { value = ReadInt16(); } else if (size == CpuSize.Use32Bit) { value = ReadInt32(); } else { throw new ArgumentException("size must be 1, 2, or 4."); } return(new Operand.LocationAware <int>( new Operand.Location((byte)pos, (byte)size), value)); }
public virtual string FormatOperand(MemoryOperand operand) { CpuSize size = operand.Size; string prefix = (size == CpuSize.Use8Bit) ? "byte" : (size == CpuSize.Use16Bit) ? "word" : (size == CpuSize.Use32Bit) ? "dword" : (size == CpuSize.Use64Bit) ? "qword" : (size == CpuSize.Use128Bit) ? "dqword" : ""; StringBuilder sb = new StringBuilder(); if (prefix != "") { sb.Append(prefix); sb.Append(" ptr "); } if (operand.Segment != Register.None) { FormatRegister(sb, operand.Segment); sb.Append(':'); } string strDisplacement = FormatFixableLocation(operand); sb.Append('['); if (operand.Base == Register.None) // only displacement { if (strDisplacement != null) { sb.Append(strDisplacement); } else { FormatNumber(sb, (UInt16)operand.Displacement.Value); } } else // base+index*scale+displacement { FormatRegister(sb, operand.Base); if (operand.Index != Register.None) { sb.Append('+'); FormatRegister(sb, operand.Index); if (operand.Scaling != 1) { sb.Append('*'); sb.Append(operand.Scaling); } } if (strDisplacement != null) { sb.Append('+'); sb.Append(strDisplacement); } else { int displacement = operand.Displacement.Value; if (displacement > 0) // e.g. [BX+1] { sb.Append('+'); FormatNumber(sb, (uint)displacement); } else if (displacement < 0) { sb.Append('-'); FormatNumber(sb, (uint)-displacement); } } } sb.Append(']'); return(sb.ToString()); }
/// <summary> /// Consumes the next byte, word, or dword. /// </summary> /// <returns>The next byte, word, or dword, sign-extended.</returns> public Operand.LocationAware<int> ReadImmediate(CpuSize size) { int pos = this.Position; int value; if (size == CpuSize.Use8Bit) value = (sbyte)ReadByte(); else if (size == CpuSize.Use16Bit) value = ReadInt16(); else if (size == CpuSize.Use32Bit) value = ReadInt32(); else throw new ArgumentException("size must be 1, 2, or 4."); return new Operand.LocationAware<int>( new Operand.Location((byte)pos, (byte)size), value); }
public Register Resize(CpuSize newSize) { int newId = (int)id & 0xFF | ((int)newSize << 8); return(new Register((RegisterId)newId)); }
public Register(RegisterType type, int number, CpuSize size) { id = (RegisterId)(number | ((int)type << 4) | ((int)size << 8)); }
public Register Resize(CpuSize newSize) { int newId = (int)id & 0xFF | ((int)newSize << 8); return new Register((RegisterId)newId); }
public ImmediateOperand(int value, CpuSize size) { this.immediate = new LocationAware <int>(value); this.size = size; }
public ImmediateOperand(LocationAware <int> immediate, CpuSize size) { this.immediate = immediate; this.size = size; }
static RegisterOperand CreateRegisterOperand(RegisterType type, int number, CpuSize size) { return new RegisterOperand(new Register(type, number, size)); }
static RelativeOperand DecodeRelativeOperand(InstructionReader reader, CpuSize size) { return new RelativeOperand(reader.ReadImmediate(size)); }
static ImmediateOperand DecodeImmediateOperand(InstructionReader reader, CpuSize size) { return new ImmediateOperand(reader.ReadImmediate(size), size); }
// Note: we need to take into account OperandSizeOverride and // AddressSizeOverride!!!!!! /// <summary> /// Decodes a memory operand encoded by the ModRM byte, SIB byte, and /// Displacement, or a register operand if MOD=3 and registerType is /// specified. /// </summary> /// <param name="reader">Instruction reader.</param> /// <param name="registerType">Type of the register to return if the /// Mod field of the ModR/M byte is 3. If this parameter is set to /// RegisterType.None, an exception is thrown if Mod=3.</param> /// <param name="operandSize">Size of the returned operand.</param> /// <param name="context">Decoding context.</param> /// <returns>The decoded memory or register operand.</returns> /// <exception cref="InvalidInstructionException">If registerType is /// set to None but the ModR/M byte encodes a register.</exception> static Operand DecodeMemoryOperand( InstructionReader reader, RegisterType registerType, CpuSize operandSize, DecoderContext context) { if (context.CpuMode == CpuMode.X64Mode) throw new NotSupportedException(); //if (operandSize == CpuSize.Default) // throw new ArgumentException("operandSize is not specified."); if (context.AddressSize != CpuSize.Use16Bit) throw new NotSupportedException("32-bit addressing mode is not supported."); ModRM modrm = reader.GetModRM(); int rm = modrm.RM; int mod = modrm.MOD; // Decode a register if MOD = (11). if (mod == 3) { // If the instruction expects a memory operand, throw an exception. if (registerType == RegisterType.None) { throw new InvalidInstructionException( "The instruction expects a memory operand, but the ModR/M byte encodes a register."); } // Treat AH-DH specially. if (registerType == RegisterType.General && operandSize == CpuSize.Use8Bit && rm >= 4) { return new RegisterOperand(new Register( RegisterType.HighByte, rm - 4, CpuSize.Use8Bit)); } else { return new RegisterOperand(new Register(registerType, rm, operandSize)); } } // Take into account segment override prefix if present. Register segment = context.SegmentOverride; // Special treatment for MOD = (00) and RM = (110). // This encodes a 16-bit sign-extended displacement. if (mod == 0 && rm == 6) { return new MemoryOperand { Size = operandSize, Segment = segment, Displacement = reader.ReadImmediate(CpuSize.Use16Bit) }; } /* Decode an indirect memory address XX[+YY][+disp]. */ MemoryOperand mem = new MemoryOperand(); mem.Size = operandSize; mem.Segment = segment; switch (rm) { case 0: /* [BX+SI] */ mem.Base = Register.BX; mem.Index = Register.SI; break; case 1: /* [BX+DI] */ mem.Base = Register.BX; mem.Index = Register.DI; break; case 2: /* [BP+SI] */ mem.Base = Register.BP; mem.Index = Register.SI; break; case 3: /* [BP+DI] */ mem.Base = Register.BP; mem.Index = Register.DI; break; case 4: /* [SI] */ mem.Base = Register.SI; break; case 5: /* [DI] */ mem.Base = Register.DI; break; case 6: /* [BP] */ mem.Base = Register.BP; break; case 7: /* [BX] */ mem.Base = Register.BX; break; } if (mod == 1) /* disp8, sign-extended */ { mem.Displacement = reader.ReadImmediate(CpuSize.Use8Bit); } else if (mod == 2) /* disp16, sign-extended */ { mem.Displacement = reader.ReadImmediate(CpuSize.Use16Bit); } return mem; }
/// <summary> /// Decodes a register operand from the REG field of the ModR/M byte. /// Since the REG field only contains the register number, additional /// parameters are used to determine the register's type and size. /// </summary> /// <param name="reader">Instruction reader.</param> /// <param name="registerType">Type of the register to return.</param> /// <param name="operandSize">Size of the register to return.</param> /// <param name="context">Decoding context.</param> /// <returns>The decoded register operand.</returns> private static RegisterOperand DecodeRegisterOperand( InstructionReader reader, RegisterType registerType, CpuSize operandSize, DecoderContext context) { if (context.CpuMode == CpuMode.X64Mode) throw new NotSupportedException(); if (operandSize == CpuSize.Default) throw new ArgumentException("operandSize is not specified."); int reg = reader.GetModRM().REG; if (registerType == RegisterType.General && operandSize == CpuSize.Use8Bit && reg >= 4) { return new RegisterOperand(new Register( RegisterType.HighByte, reg - 4, CpuSize.Use8Bit)); } return new RegisterOperand(new Register(registerType, reg, operandSize)); }