Example #1
0
        /// <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());
        }
Example #3
0
        /// <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);
        }
Example #4
0
        public Register Resize(CpuSize newSize)
        {
            int newId = (int)id & 0xFF | ((int)newSize << 8);

            return(new Register((RegisterId)newId));
        }
Example #5
0
 public Register(RegisterType type, int number, CpuSize size)
 {
     id = (RegisterId)(number | ((int)type << 4) | ((int)size << 8));
 }
Example #6
0
 public Register Resize(CpuSize newSize)
 {
     int newId = (int)id & 0xFF | ((int)newSize << 8);
     return new Register((RegisterId)newId);
 }
Example #7
0
 public Register(RegisterType type, int number, CpuSize size)
 {
     id = (RegisterId)(number | ((int)type << 4) | ((int)size << 8));
 }
Example #8
0
 public ImmediateOperand(int value, CpuSize size)
 {
     this.immediate = new LocationAware <int>(value);
     this.size      = size;
 }
Example #9
0
 public ImmediateOperand(LocationAware <int> immediate, CpuSize size)
 {
     this.immediate = immediate;
     this.size      = size;
 }
Example #10
0
 static RegisterOperand CreateRegisterOperand(RegisterType type, int number, CpuSize size)
 {
     return new RegisterOperand(new Register(type, number, size));
 }
Example #11
0
 static RelativeOperand DecodeRelativeOperand(InstructionReader reader, CpuSize size)
 {
     return new RelativeOperand(reader.ReadImmediate(size));
 }
Example #12
0
 static ImmediateOperand DecodeImmediateOperand(InstructionReader reader, CpuSize size)
 {
     return new ImmediateOperand(reader.ReadImmediate(size), size);
 }
Example #13
0
        // 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;
        }
Example #14
0
        /// <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));
        }