private MachineOperand Mem32(RegisterStorage baseReg, int off)
 {
     var mem = new MemoryOperand(PrimitiveType.Word32);
     mem.Base = baseReg;
     mem.Offset = Constant.Word32(off);
     return mem;
 }
Exemplo n.º 2
0
 public void X86Orw16_RewriteSegConst()
 {
     var m = new MemoryOperand(
         PrimitiveType.Byte,
         Registers.bx,
         Constant.Int32(32));
     var e = orw.CreateMemoryAccess(instr, m, state);
     Assert.AreEqual("Mem0[ds:bx + 0x0020:byte]", e.ToString());
 }
Exemplo n.º 3
0
		private Constant EmitDirectAddress(int reg, MemoryOperand memOp)
		{
			Debug.Assert(memOp.Offset.IsValid);
			if (defaultWordSize == PrimitiveType.Word16)
			{
				reg |= 0x6;
				emitter.EmitByte(reg);
				return Constant.Create(PrimitiveType.Word16, memOp.Offset.ToUInt32());
			}
			else
			{
				reg |= 0x5;
				emitter.EmitByte(reg);
				return Constant.Word32(memOp.Offset.ToUInt32());
			}
		}
Exemplo n.º 4
0
        private void RewriteLxs(RegisterStorage seg)
        {
            var           reg = (RegisterOperand)instrCur.Operands[0];
            MemoryOperand mem = (MemoryOperand)instrCur.Operands[1];

            if (!mem.Offset !.IsValid)
            {
                mem = new MemoryOperand(mem.Width, mem.Base, mem.Index, mem.Scale, Constant.Create(instrCur.addrWidth, 0));
            }

            var ptr    = PrimitiveType.Create(Domain.Pointer, seg.DataType.BitSize + reg.Width.BitSize);
            var segptr = PrimitiveType.Create(Domain.SegPointer, seg.DataType.BitSize + reg.Width.BitSize);

            m.Assign(
                binder.EnsureSequence(ptr, seg, reg.Register),
                orw.Transform(instrCur, mem, segptr));
        }
Exemplo n.º 5
0
        private TWord GetEffectiveAddress(MemoryOperand m)
        {
            TWord ea = 0;

            if (m.Offset.IsValid)
            {
                ea += m.Offset.ToUInt32();
            }
            if (m.Index != RegisterStorage.None)
            {
                ea += ReadRegister(m.Index) * m.Scale;
            }
            if (m.Base != null && m.Base != RegisterStorage.None)
            {
                ea += ReadRegister(m.Base);
            }
            return(ea);
        }
Exemplo n.º 6
0
        public Expression CreateMemoryAccess(X86Instruction instr, MemoryOperand mem, DataType dt)
        {
            Expression expr = EffectiveAddressExpression(instr, mem);

            //$REVIEW: perhaps the code below could be moved to Scanner since it is arch-independent?
            if (expr is Address addrThunk)
            {
                var exg = host.GetImport(addrThunk, instr.Address);
                if (exg is ProcedureConstant)
                {
                    return(exg);
                }
                else if (exg != null)
                {
                    return(new UnaryExpression(Operator.AddrOf, dt, exg));
                }
                var exp = host.GetImportedProcedure(arch, addrThunk, instr.Address);
                if (exp != null)
                {
                    return(new ProcedureConstant(arch.PointerType, exp));
                }
            }
            if (IsSegmentedAccessRequired ||
                (mem.DefaultSegment != Registers.cs &&
                 mem.DefaultSegment != Registers.ds &&
                 mem.DefaultSegment != Registers.ss))
            {
                Expression seg;
                if (mem.DefaultSegment == Registers.cs)
                {
                    seg = Constant.Create(PrimitiveType.SegmentSelector, instr.Address.Selector !.Value);
                }
                else
                {
                    seg = AluRegister(mem.DefaultSegment);
                }
                return(new SegmentedAccess(MemoryIdentifier.GlobalMemory, seg, expr, dt));
            }
            else
            {
                return(new MemoryAccess(MemoryIdentifier.GlobalMemory, expr, dt));
            }
        }
Exemplo n.º 7
0
        public Expression CreateMemoryAccess(X86Instruction instr, MemoryOperand mem, DataType dt, X86State state)
        {
            var exg = ImportedGlobal(instr.Address, mem.Width, mem);

            if (exg is ProcedureConstant)
            {
                return(exg);
            }
            else if (exg != null)
            {
                return(new UnaryExpression(Operator.AddrOf, dt, exg));
            }
            var exp = ImportedProcedure(instr.Address, mem.Width, mem);

            if (exp != null)
            {
                return(new ProcedureConstant(arch.PointerType, exp));
            }
            Expression expr = EffectiveAddressExpression(instr, mem, state);

            if (IsSegmentedAccessRequired ||
                (mem.DefaultSegment != Registers.cs &&
                 mem.DefaultSegment != Registers.ds &&
                 mem.DefaultSegment != Registers.ss))
            {
                Expression seg;
                if (mem.DefaultSegment == Registers.cs)
                {
                    seg = Constant.Create(PrimitiveType.SegmentSelector, instr.Address.Selector.Value);
                }
                else
                {
                    seg = AluRegister(mem.DefaultSegment);
                }
                return(new SegmentedAccess(MemoryIdentifier.GlobalMemory, seg, expr, dt));
            }
            else
            {
                return(new MemoryAccess(MemoryIdentifier.GlobalMemory, expr, dt));
            }
        }
Exemplo n.º 8
0
        public void RewriteLea()
        {
            Expression    src;
            MemoryOperand mem = (MemoryOperand)instrCur.Operands[1];

            if (mem.Base == RegisterStorage.None && mem.Index == RegisterStorage.None)
            {
                src = mem.Offset;
            }
            else
            {
                src = SrcOp(instrCur.Operands[1]);
                if (src is MemoryAccess load)
                {
                    src = load.EffectiveAddress;
                }
                else
                {
                    src = orw.AddrOf(src);
                }
            }
            m.Assign(SrcOp(instrCur.Operands[0]), src);
        }
Exemplo n.º 9
0
        public void RewriteLea()
        {
            Expression    src;
            MemoryOperand mem = (MemoryOperand)instrCur.op2;

            if (mem.Base == RegisterStorage.None && mem.Index == RegisterStorage.None)
            {
                src = mem.Offset;
            }
            else
            {
                src = SrcOp(instrCur.op2);
                MemoryAccess load = src as MemoryAccess;
                if (load != null)
                {
                    src = load.EffectiveAddress;
                }
                else
                {
                    src = orw.AddrOf(src);
                }
            }
            emitter.Assign(SrcOp(instrCur.op1), src);
        }
Exemplo n.º 10
0
        private void RewriteLxs(RegisterStorage seg)
        {
            var reg = (RegisterOperand)instrCur.op1;
            MemoryOperand mem = (MemoryOperand)instrCur.op2;
            if (!mem.Offset.IsValid)
            {
                mem = new MemoryOperand(mem.Width, mem.Base, mem.Index, mem.Scale, Constant.Create(instrCur.addrWidth, 0));
            }

            var ass = emitter.Assign(
                frame.EnsureSequence(orw.AluRegister(seg), orw.AluRegister(reg.Register),
                PrimitiveType.Pointer32),
                SrcOp(mem, PrimitiveType.SegPtr32));
        }
Exemplo n.º 11
0
 public int Get16AddressingModeMask(MemoryOperand memOp)
 {
     int mask = (1 << memOp.Base.Number);
     if (memOp.Index != RegisterStorage.None)
     {
         mask |= (1 << memOp.Index.Number);
     }
     if (mask == ((1<<Registers.bx.Number)|(1<<Registers.si.Number)))
         return 0;
     if (mask == ((1<<Registers.bx.Number)|(1<<Registers.di.Number)))
         return 1;
     if (mask == ((1<<Registers.bp.Number)|(1<<Registers.si.Number)))
         return 2;
     if (mask == ((1<<Registers.bp.Number)|(1<<Registers.di.Number)))
         return 3;
     if (mask == 1<<Registers.si.Number)
         return 4;
     if (mask == 1<<Registers.di.Number)
         return 5;
     if (mask == 1<<Registers.bp.Number)
     {
         mask = 6;
         if (memOp.Offset == null || !memOp.Offset.IsValid)
         {
             mask |= 0x40;
             offset = Constant.Byte(0);
         }
         return mask;
     }
     if (mask == 1<<(int) Registers.bx.Number)
         return 7;
     OnError(string.Format("Illegal 16-bit addressing mode: {0} ", memOp.ToString()));
     return 0;
 }
Exemplo n.º 12
0
        private void ParseMemoryFactor(MemoryOperand memOp)
        {
            Token token = lexer.GetToken();
            RegisterStorage reg = RegisterStorage.None;
            switch (token)
            {
            default:
                OnError("unexpected token: " + token);
                return;
            case Token.INTEGER:
                totalInt += lexer.Integer;
                break;
            case Token.REGISTER:
            {
                reg = lexer.Register;
             				PrimitiveType width = reg.DataType;
             				if (addrWidth == null)
             					addrWidth = width;
             				else if (addrWidth != width)
             					throw new ApplicationException("Conflicting address widths");
             				break;
            }
            case Token.ID:
            {
                int v;
                if (symtab.Equates.TryGetValue(lexer.StringLiteral.ToLower(), out v))
                {
                    totalInt += v;
                }
                else
                {
                    sym = symtab.CreateSymbol(lexer.StringLiteral);
                    totalInt += unchecked((int) addrBase.Offset);
                }
                break;
            }
            }

            if (lexer.PeekToken() == Token.TIMES)
            {
                if (reg == RegisterStorage.None)
                    throw new ApplicationException("Scale factor must be preceded by a register");
                lexer.GetToken();
                if (memOp.Index != RegisterStorage.None)
                    throw new ApplicationException("Scale can only be used once in an addressing form");
                Expect(Token.INTEGER, "Expected an integer scale");
                if (lexer.Integer != 1 && lexer.Integer != 2 && lexer.Integer != 4 && lexer.Integer != 8)
                    throw new ApplicationException("Only scales 1, 2, 4, and 8 are supported");
                memOp.Scale = (byte) lexer.Integer;
                memOp.Index = reg;
            }
            else if (reg != RegisterStorage.None)
            {
                if (memOp.Base == RegisterStorage.None)
                    memOp.Base = reg;
                else if (memOp.Index == RegisterStorage.None)
                {
                    memOp.Index = reg;
                    memOp.Scale = 1;
                }
                else
                    throw new ApplicationException("Can't have more than two registers in an addressing form");
            }
        }
Exemplo n.º 13
0
        private X86Instruction DecodeOperands(Opcode opcode, byte op, string strFormat, InstrClass iclass)
        {
            if (strFormat == null)
            {
                return(null);
            }
            MachineOperand        pOperand;
            PrimitiveType         width  = null;
            PrimitiveType         iWidth = dataWidth;
            byte                  modRm;
            List <MachineOperand> ops = new List <MachineOperand>();
            int i = 0;

            while (i != strFormat.Length)
            {
                if (strFormat[i] == ',')
                {
                    ++i;
                }

                pOperand = null;
                MemoryOperand memOp;
                char          chFmt = strFormat[i++];
                switch (chFmt)
                {
                case '1':
                    pOperand = new ImmediateOperand(Constant.Byte(1));
                    break;

                case '3':
                    pOperand = new ImmediateOperand(Constant.Byte(3));
                    break;

                case 'A':               // Absolute memory address.
                    ++i;
                    if (!rdr.TryReadLeUInt16(out ushort off))
                    {
                        return(null);
                    }
                    if (!rdr.TryReadLeUInt16(out ushort seg))
                    {
                        return(null);
                    }
                    var addr = mode.CreateSegmentedAddress(seg, off);
                    if (addr == null)
                    {
                        return(null);
                    }
                    pOperand = new X86AddressOperand(addr);
                    break;

                case 'C':       // control register encoded in the reg field.
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    var creg = mode.GetControlRegister((modRm >> 3) & 7);
                    if (creg == null)
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(creg);
                    break;

                case 'D':       // debug register encoded in the reg field.
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    var dreg = mode.GetDebugRegister((modRm >> 3) & 7);
                    if (dreg == null)
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(dreg);
                    break;

                case 'E':               // memory or register operand specified by mod & r/m fields.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, GpRegFromBits);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'Q':               // memory or register MMX operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, MmxRegFromBits);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'G':               // register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits));
                    break;

                case 'H':       // If VEX encoding, use vvvv register.
                    if (currentDecodingContext.IsVex)
                    {
                        width    = SseOperandWidth(strFormat, ref i);
                        pOperand = new RegisterOperand(XmmRegFromBits(currentDecodingContext.VexRegister, width));
                    }
                    else
                    {
                        i = strFormat.IndexOf(',', i);
                    }
                    break;

                case 'N':       // MMX register operand specified by the r/m field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, MmxRegFromBits));
                    break;

                case 'P':               // MMX register operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits));
                    break;

                case 'I':               // Immediate operand.
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat, ref i); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = CreateImmediateOperand(width, dataWidth);
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'L': // The upper 4 bits of the 8-bit immediate selects a 128-bit XMM register or a 256-bit YMM register, determined
                          // by operand type.
                    if (!rdr.TryReadByte(out var lReg))
                    {
                        return(null);
                    }
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat, ref i); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = new RegisterOperand(XmmRegFromBits((lReg >> 4) & 0xF, width));
                    break;

                case 'J':               // Relative ("near") jump.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    Constant cOffset;
                    if (!rdr.TryRead(width, out cOffset))
                    {
                        return(null);
                    }
                    long  jOffset = cOffset.ToInt64();
                    ulong uAddr   = (ulong)((long)rdr.Address.Offset + jOffset);
                    if (defaultAddressWidth.BitSize == 64)      //$REVIEW: not too keen on the switch statement here.
                    {
                        pOperand = AddressOperand.Ptr64(uAddr);
                    }
                    else if (defaultAddressWidth.BitSize == 32)
                    {
                        pOperand = AddressOperand.Ptr32((uint)uAddr);
                    }
                    else
                    {
                        pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr));
                    }
                    break;

                case 'M':               // modRM may only refer to memory.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    if ((modRm & 0xC0) == 0xC0)
                    {
                        return(null);
                    }
                    pOperand = DecodeModRM(dataWidth, this.currentDecodingContext.SegmentOverride, GpRegFromBits) as MemoryOperand;
                    if (pOperand == null)
                    {
                        return(null);
                    }
                    break;

                case 'O':               // Offset of the operand is encoded directly after the opcode.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!rdr.TryReadLe(addressWidth, out var offset))
                    {
                        return(null);
                    }
                    pOperand          = memOp = new MemoryOperand(width, offset);
                    memOp.SegOverride = this.currentDecodingContext.SegmentOverride;
                    break;

                case 'R':       // register operand specified by the mod field of the modRM byte.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, GpRegFromBits));
                    break;

                case 'S':       // Segment register encoded by reg field of modRM byte.
                    ++i;        // Skip over the 'w'.
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(SegFromBits(modRm >> 3));
                    break;

                case 'U':               // XMM operand specified by the modRm field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, XmmRegFromBits));
                    break;

                case 'V':               // XMM operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits));
                    break;

                case 'W':               // memory or XMM operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, XmmRegFromBits);
                    break;

                case 'a':               // Implicit use of accumulator.
                    pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat, ref i)));
                    ++i;
                    break;

                case 'b':
                    iWidth   = PrimitiveType.Byte;
                    pOperand = null;
                    break;

                case 'c':               // Implicit use of CL.
                    pOperand = new RegisterOperand(Registers.cl);
                    break;

                case 'd':               // Implicit use of DX or EDX.
                    width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = new RegisterOperand(RegFromBitsRexW(2, width));
                    break;

                case 'r':               // Register encoded as last 3 bits of instruction.
                    iWidth = width = OperandWidth(strFormat, ref i);
                    ++i;
                    pOperand = new RegisterOperand(RegFromBitsRexB(op, width));
                    break;

                case 's':               // Segment encoded as next byte of the format string.
                    pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0'));
                    break;

                case 'F':               // Floating-point ST(x)
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new FpuOperand(modRm & 0x07);
                    break;

                case 'f':               // ST(0)
                    pOperand = new FpuOperand(0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat));
                }
                if (pOperand != null)
                {
                    ops.Add(pOperand);
                }
            }
            return(new X86Instruction(opcode, iclass, iWidth, addressWidth, ops.ToArray())
            {
                repPrefix = this.currentDecodingContext.F2Prefix ? 2 :
                            this.currentDecodingContext.F3Prefix ? 3 : 0
            });
        }
Exemplo n.º 14
0
 public void ModRm16Memop()
 {
     MemoryOperand m;
     PrimitiveType w = PrimitiveType.Word16;
     ModRmBuilder mrm = new ModRmBuilder(w, null);
     m = new MemoryOperand(w, Registers.bx, Registers.si, 1, Constant.Invalid);
     Assert.AreEqual(0, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.bx, Registers.di, 1, Constant.Invalid);
     Assert.AreEqual(1, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.bp, Registers.si, 1, Constant.Invalid);
     Assert.AreEqual(2, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.bp, Registers.di, 1, Constant.Invalid);
     Assert.AreEqual(3, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.si, Constant.Invalid);
     Assert.AreEqual(4, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.di, Constant.Invalid);
     Assert.AreEqual(5, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.bp, Constant.Invalid);
     Assert.AreEqual(0x46, mrm.Get16AddressingModeMask(m));
     m = new MemoryOperand(w, Registers.bx, Constant.Invalid);
     Assert.AreEqual(7, mrm.Get16AddressingModeMask(m));
 }
Exemplo n.º 15
0
 internal void EmitModRM(int reg, MemoryOperand memOp, byte b, Symbol sym)
 {
     Constant offset = modRm.EmitModRMPrefix(reg, memOp);
     emitter.EmitByte(b);
     int offsetPosition = emitter.Position;
     EmitOffset(offset);
     if (sym != null)
         ReferToSymbol(sym, emitter.Position, offset.DataType);
 }
Exemplo n.º 16
0
        public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand mem, DataType dt, X86State state)
        {
            var exp = ImportedProcedure(instr.Address, mem.Width, mem);
            if (exp != null)
                return new ProcedureConstant(arch.PointerType, exp);

            Expression expr = EffectiveAddressExpression(instr, mem, state);
            if (IsSegmentedAccessRequired ||
                (mem.DefaultSegment != Registers.ds && mem.DefaultSegment != Registers.ss))
            {
                Expression seg = ReplaceCodeSegment(mem.DefaultSegment, state);
                if (seg == null)
                    seg = AluRegister(mem.DefaultSegment);
                return new SegmentedAccess(MemoryIdentifier.GlobalMemory, seg, expr, dt);
            }
            else
            {
                return new MemoryAccess(MemoryIdentifier.GlobalMemory, expr, dt);
            }
        }
Exemplo n.º 17
0
 public ExternalProcedure ImportedProcedure(Address addrInstruction, PrimitiveType addrWidth, MemoryOperand mem)
 {
     if (mem != null && addrWidth == PrimitiveType.Word32 && mem.Base == RegisterStorage.None &&
         mem.Index == RegisterStorage.None)
     {
         return host.GetImportedProcedure(Address.Ptr32(mem.Offset.ToUInt32()), addrInstruction);
     }
     return null;
 }
Exemplo n.º 18
0
        /// <summary>
        /// Memory accesses are translated into expressions.
        /// </summary>
        /// <param name="mem"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public Expression EffectiveAddressExpression(IntelInstruction instr, MemoryOperand mem, X86State state)
        {
            Expression eIndex = null;
            Expression eBase = null;
            Expression expr = null;
            PrimitiveType type = PrimitiveType.CreateWord(mem.Width.Size);
            bool ripRelative = false;

            if (mem.Base != RegisterStorage.None)
            {
                if (mem.Base == Registers.rip)
                {
                    ripRelative = true;
                }
                else
                {
                    eBase = AluRegister(mem.Base);
                    if (expr != null)
                    {
                        expr = new BinaryExpression(Operator.IAdd, eBase.DataType, eBase, expr);
                    }
                    else
                    {
                        expr = eBase;
                    }
                }
            }

            if (mem.Offset.IsValid)
            {
                if (ripRelative)
                {
                    expr = instr.Address + (instr.Length + mem.Offset.ToInt64());
                }
                else if (expr != null)
                {
                    BinaryOperator op = Operator.IAdd;
                    long l = mem.Offset.ToInt64();
                    if (l < 0 && l > -0x800)
                    {
                        l = -l;
                        op = Operator.ISub;
                    }

                    DataType dt = (eBase != null) ? eBase.DataType : eIndex.DataType;
                    Constant cOffset = Constant.Create(dt, l);
                    expr = new BinaryExpression(op, dt, expr, cOffset);
                }
                else
                {
                    expr = mem.Offset;
                }
            }

            if (mem.Index != RegisterStorage.None)
            {
                eIndex = AluRegister(mem.Index);
                if (mem.Scale != 0 && mem.Scale != 1)
                {
                    eIndex = new BinaryExpression(
                        Operator.IMul, eIndex.DataType, eIndex, Constant.Create(mem.Width, mem.Scale));
                }
                expr = new BinaryExpression(Operator.IAdd, expr.DataType, expr, eIndex);
            }
            return expr;
        }
Exemplo n.º 19
0
 public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand memoryOperand, X86State state)
 {
     return CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state);
 }
Exemplo n.º 20
0
        /// <summary>
        /// Memory accesses are translated into expressions, performing simplifications
        /// where possible.
        /// </summary>
        public Expression EffectiveAddressExpression(X86Instruction instr, MemoryOperand mem)
        {
            Expression?eIndex      = null;
            Expression?eBase       = null;
            Expression?expr        = null;
            bool       ripRelative = false;

            if (mem.Base != RegisterStorage.None)
            {
                if (mem.Base == Registers.rip)
                {
                    ripRelative = true;
                }
                else
                {
                    eBase = AluRegister(mem.Base);
                    if (expr != null)
                    {
                        expr = m.IAdd(eBase, expr);
                    }
                    else
                    {
                        expr = eBase;
                    }
                }
            }

            if (mem.Offset != null)
            {
                if (ripRelative)
                {
                    expr = instr.Address + (instr.Length + mem.Offset.ToInt64());
                }
                else if (expr != null)
                {
                    BinaryOperator op = Operator.IAdd;
                    long           l  = mem.Offset.ToInt64();
                    if (l < 0 && l > -0x800)
                    {
                        l  = -l;
                        op = Operator.ISub;
                    }

                    DataType dt      = (eBase != null) ? eBase.DataType : eIndex !.DataType;
                    Constant cOffset = Constant.Create(dt, l);
                    expr = new BinaryExpression(op, dt, expr, cOffset);
                }
                else
                {
                    // expr is null, so there was no base register. But was there
                    // an index register? If so extend the offset to the samesize.
                    if (mem.Index != RegisterStorage.None && (int)mem.Index.BitSize != mem.Offset.DataType.BitSize)
                    {
                        var dt = PrimitiveType.Create(Domain.SignedInt, (int)mem.Index.BitSize);
                        expr = Constant.Create(dt, mem.Offset.ToInt64());
                    }
                    else
                    {
                        // There was no base or index.
                        expr = mem.Offset;
                    }
                }
            }

            if (mem.Index != RegisterStorage.None)
            {
                eIndex = AluRegister(mem.Index);
                if (mem.Scale != 0 && mem.Scale != 1)
                {
                    eIndex = m.IMul(eIndex, Constant.Create(mem.Index.DataType, mem.Scale));
                }
                expr = m.IAdd(expr !, eIndex);
            }
            if (!IsSegmentedAccessRequired && expr is Constant c && mem.SegOverride == RegisterStorage.None)
            {
                return(arch.MakeAddressFromConstant(c, false) !);
            }
            return(expr !);
        }
Exemplo n.º 21
0
        /// <summary>
        /// Memory accesses are translated into expressions, performing simplifications
        /// where possible.
        /// </summary>
        public Expression EffectiveAddressExpression(X86Instruction instr, MemoryOperand mem)
        {
            Expression?eIndex      = null;
            Expression?eBase       = null;
            Expression?expr        = null;
            bool       ripRelative = false;

            if (mem.Base != RegisterStorage.None)
            {
                if (mem.Base == Registers.rip)
                {
                    ripRelative = true;
                }
                else
                {
                    eBase = AluRegister(mem.Base);
                    if (expr != null)
                    {
                        expr = m.IAdd(eBase, expr);
                    }
                    else
                    {
                        expr = eBase;
                    }
                }
            }

            if (mem.Offset != null)
            {
                if (ripRelative)
                {
                    expr = instr.Address + (instr.Length + mem.Offset.ToInt64());
                }
                else if (expr != null)
                {
                    BinaryOperator op = Operator.IAdd;
                    long           l  = mem.Offset.ToInt64();
                    if (l < 0 && l > -0x800)
                    {
                        l  = -l;
                        op = Operator.ISub;
                    }

                    DataType dt      = (eBase != null) ? eBase.DataType : eIndex !.DataType;
                    Constant cOffset = Constant.Create(dt, l);
                    expr = new BinaryExpression(op, dt, expr, cOffset);
                }
                else
                {
                    expr = mem.Offset;
                }
            }

            if (mem.Index != RegisterStorage.None)
            {
                eIndex = AluRegister(mem.Index);
                if (mem.Scale != 0 && mem.Scale != 1)
                {
                    eIndex = m.IMul(eIndex, Constant.Create(mem.Index.DataType, mem.Scale));
                }
                expr = m.IAdd(expr !, eIndex);
            }
            if (!IsSegmentedAccessRequired && expr is Constant c && mem.SegOverride == RegisterStorage.None)
            {
                return(arch.MakeAddressFromConstant(c, false) !);
            }
            return(expr !);
        }
Exemplo n.º 22
0
 public ParsedOperand MemW(RegisterStorage seg, RegisterStorage @base, int offset)
 {
     var mem = new MemoryOperand(PrimitiveType.Word16);
     mem.Base = @base;
     mem.Offset = IntegralConstant(offset);
     mem.SegOverride = seg;
     return new ParsedOperand(mem);
 }
Exemplo n.º 23
0
 private ParsedOperand Mem(
     PrimitiveType width, 
     RegisterStorage seg, 
     RegisterStorage @base,  
     RegisterStorage index, 
     int scale, 
     string offset)
 {
     int val;
     MemoryOperand mem;
     Symbol sym = null;
     if (offset != null)
     {
         if (symtab.Equates.TryGetValue(offset, out val))
         {
             mem = new MemoryOperand(width, @base, IntegralConstant(val, @base.DataType));
             sym = null;
         }
         else
         {
             sym = symtab.CreateSymbol(offset);
             val = (int)this.addrBase.Offset;
             Constant off = Constant.Create(@base == null
                 ? seg != null ? PrimitiveType.Word16 : PrimitiveType.Word32
                 : @base.DataType,
                 val);
             mem = new MemoryOperand(width, @base ?? RegisterStorage.None, off);
         }
     }
     else
     {
         mem = new MemoryOperand(width)
         {
         };
     }
     if (seg != null)
     {
         mem.SegOverride = seg;
         this.SegmentOverride = seg;
     }
     mem.Scale = (byte)scale;
     if (scale > 1)
     {
         if (index == null)
         {
             mem.Index = mem.Base;
             mem.Base = RegisterStorage.None;
         }
         else
         {
             mem.Index = index;
             mem.Base = @base;
         }
     }
     return new ParsedOperand(mem, sym);
 }
Exemplo n.º 24
0
 public Expression CreateMemoryAccess(X86Instruction instr, MemoryOperand memoryOperand, X86State state)
 {
     return(CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state));
 }
Exemplo n.º 25
0
        protected void RenderMemory(
            MemoryOperand mem,
            MachineInstructionRenderer renderer,
            MachineInstructionRendererFlags flags)
        {
            if ((flags & MachineInstructionRendererFlags.ExplicitOperandSize) != 0)
            {
                var s = ExplicitOperandPrefix(mem.Width);
                renderer.WriteString(s);
            }

            if (mem.SegOverride != RegisterStorage.None)
            {
                RenderRegister(mem.SegOverride.Name, renderer);
                renderer.WriteString(":");
            }
            renderer.WriteString("[");
            if (mem.Base != RegisterStorage.None)
            {
                RenderRegister(mem.Base.Name, renderer);
            }
            else
            {
                var s = FormatUnsignedValue(mem.Offset !.ToUInt64(), "{0:X4}");
                renderer.WriteAddress(s, Address.FromConstant(mem.Offset !));
            }

            if (mem.Index != RegisterStorage.None)
            {
                renderer.WriteString("+");
                RenderRegister(mem.Index.Name, renderer);
                if (mem.Scale > 1)
                {
                    renderer.WriteString("*");
                    renderer.WriteUInt32(mem.Scale);
                }
            }
            if (mem.Base != RegisterStorage.None && mem.Offset != null && mem.Offset.IsValid)
            {
                if (mem.Offset.DataType == PrimitiveType.Byte || mem.Offset.DataType == PrimitiveType.SByte)
                {
                    renderer.WriteString(FormatSignedValue(mem.Offset.ToInt64(), true));
                }
                else
                {
                    var off = mem.Offset.ToInt32();
                    if (off == Int32.MinValue)
                    {
                        renderer.WriteString("-80000000h");
                    }
                    else
                    {
                        var absOff = Math.Abs(off);
                        if (mem.Offset.DataType.Size > 2 && off < 0 && absOff < 0x10000)
                        {
                            // Special case for negative 32-bit offsets whose
                            // absolute value < 0x10000 (GitHub issue #252)
                            renderer.WriteString("-");
                            renderer.WriteFormat(FormatUnsignedValue((ulong)absOff));
                        }
                        else
                        {
                            renderer.WriteString("+");
                            renderer.WriteString(FormatUnsignedValue(mem.Offset.ToUInt64()));
                        }
                    }
                }
            }
            renderer.WriteString("]");
        }
Exemplo n.º 26
0
 public Expression ImportedGlobal(Address addrInstruction, PrimitiveType addrWidth, MemoryOperand mem)
 {
     if (mem != null && addrWidth == PrimitiveType.Word32 && mem.Base == RegisterStorage.None &&
         mem.Index == RegisterStorage.None)
     {
         var id = host.GetImport(Address.Ptr32(mem.Offset.ToUInt32()), addrInstruction);
         return(id);
     }
     return(null);
 }
Exemplo n.º 27
0
        private ParsedOperand ParseMemoryOperand(RegisterStorage segOver)
        {
            MemoryOperand memOp = new MemoryOperand(null);
            memOp.SegOverride = segOver;
            this.segOverride = segOver;

            ParseMemoryFactor(memOp);
            for (;;)
            {
                Token token = lexer.GetToken();
                switch (token)
                {
                default:
                    OnError("Unexpected token: " + token);
                    return null;
                case Token.KET:
                    if (totalInt != 0 || sym != null)
                    {
                        if (addrWidth == null || sym != null)
                            memOp.Offset = Constant.Create(defaultAddressWidth, totalInt);
                        else
                            memOp.Offset = X86Assembler.IntegralConstant(totalInt, addrWidth);
                    }
                    return new ParsedOperand(memOp, sym);
                case Token.PLUS:
                    break;
                case Token.MINUS:
                    Expect(Token.INTEGER);
                    totalInt -= lexer.Integer;
                    continue;
                case Token.ID:
                    break;
                }
                ParseMemoryFactor(memOp);
            }
        }
Exemplo n.º 28
0
        public void X86Orw32_MemAccess()
		{
			MemoryOperand mem = new MemoryOperand(PrimitiveType.Word32);
			mem.Base = Registers.ecx;
			mem.Offset = Constant.Word32(4);
			Expression expr = orw.Transform(instr, mem, PrimitiveType.Word32, state);
			Assert.AreEqual("Mem0[ecx + 0x00000004:word32]", expr.ToString());
		}	
Exemplo n.º 29
0
        /// <summary>
        /// Emits the ModRM byte (and SIB byte if applicable)
        /// </summary>
        /// <param name="reg"></param>
        /// <param name="memOp"></param>
        /// <returns>The offset value to be emitted as the last piece of the instructon</returns>
        public Constant EmitModRMPrefix(int reg, MemoryOperand memOp)
        {
            offset = null;
            reg <<= 3;
            if (memOp.Base != RegisterStorage.None || memOp.Index != RegisterStorage.None)
            {
                PrimitiveType baseWidth = memOp.Base.DataType;
                PrimitiveType indexWidth = memOp.Index.DataType;
                if (memOp.Base != RegisterStorage.None && memOp.Index != RegisterStorage.None)
                {
                    if (baseWidth != indexWidth)
                    {
                        OnError("mismatched base and index registers");
                        return null;
                    }
                }

                // Add the 'mod' bits

                if (memOp.Offset != null)
                {
                    Debug.Assert(memOp.Offset.IsValid);
                    if (memOp.Offset.DataType == PrimitiveType.SByte)
                    {
                        reg |= 0x40;
                        offset = memOp.Offset;
                    }
                    else
                    {
                        reg |= 0x80;
                        offset = Constant.Create(defaultWordSize, memOp.Offset.ToInt32());
                    }
                }

                bool fNeedsSib = false;
                int sib = 0;
                if (baseWidth == PrimitiveType.Word16)
                {
                    reg |= Get16AddressingModeMask(memOp);
                }
                else if (baseWidth == PrimitiveType.Word32 || indexWidth == PrimitiveType.Word32)
                {
                    if (memOp.Index == RegisterStorage.None)
                    {
                        if (memOp.Base != Registers.esp)
                        {
                            reg |= X86Assembler.RegisterEncoding(memOp.Base);
                            if (memOp.Offset == null && memOp.Base == Registers.ebp)
                            {
                                reg |= 0x40;
                                offset = Constant.Byte(0);
                            }
                        }
                        else
                        {
                            reg |= 0x04;
                            fNeedsSib = true;
                            sib = 0x24;
                        }
                    }
                    else
                    {
                        reg |= 0x04;
                        fNeedsSib = true;
                        switch (memOp.Scale)
                        {
                        case 1: sib = 0; break;
                        case 2: sib = 0x40; break;
                        case 4: sib = 0x80; break;
                        case 8: sib = 0xC0; break;
                        default: OnError("Scale factor must be 1, 2, 4, or 8"); return Constant.Invalid;
                        }

                        if (memOp.Base == RegisterStorage.None)
                        {
                            sib |= 0x05;
                            reg &= ~0xC0;			// clear mod part of modRM.

                            if (memOp.Offset == null)
                            {
                                offset = Constant.Word32(0);
                            }
                        }
                        else
                        {
                            sib |= X86Assembler.RegisterEncoding(memOp.Base);
                        }

                        if (memOp.Index != Registers.esp)
                        {
                            sib |= X86Assembler.RegisterEncoding(memOp.Index) << 3;
                        }
                        else
                            throw new ApplicationException("ESP register can't be used as an index register");
                    }
                }
                else
                {
                    throw new ApplicationException("unexpected address width");
                }

                emitter.EmitByte(reg);
                if (fNeedsSib)
                    emitter.EmitByte(sib);
                return offset;

            }
            else
                return EmitDirectAddress(reg, memOp);
        }
Exemplo n.º 30
0
 public Identifier ImportedGlobal(Address addrInstruction, PrimitiveType addrWidth, MemoryOperand mem)
 {
     if (mem != null && addrWidth == PrimitiveType.Word32 && mem.Base == RegisterStorage.None &&
         mem.Index == RegisterStorage.None)
     {
         var id = host.GetImportedGlobal(Address.Ptr32(mem.Offset.ToUInt32()), addrInstruction);
         return id;
     }
     return null;
 }
Exemplo n.º 31
0
        /// <summary>
        /// Memory accesses are translated into expressions.
        /// </summary>
        /// <param name="mem"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public Expression EffectiveAddressExpression(X86Instruction instr, MemoryOperand mem, X86State state)
        {
            Expression eIndex      = null;
            Expression eBase       = null;
            Expression expr        = null;
            bool       ripRelative = false;

            if (mem.Base != RegisterStorage.None)
            {
                if (mem.Base == Registers.rip)
                {
                    ripRelative = true;
                }
                else
                {
                    eBase = AluRegister(mem.Base);
                    if (expr != null)
                    {
                        expr = m.IAdd(eBase, expr);
                    }
                    else
                    {
                        expr = eBase;
                    }
                }
            }

            if (mem.Offset.IsValid)
            {
                if (ripRelative)
                {
                    expr = instr.Address + (instr.Length + mem.Offset.ToInt64());
                }
                else if (expr != null)
                {
                    BinaryOperator op = Operator.IAdd;
                    long           l  = mem.Offset.ToInt64();
                    if (l < 0 && l > -0x800)
                    {
                        l  = -l;
                        op = Operator.ISub;
                    }

                    DataType dt      = (eBase != null) ? eBase.DataType : eIndex.DataType;
                    Constant cOffset = Constant.Create(dt, l);
                    expr = new BinaryExpression(op, dt, expr, cOffset);
                }
                else
                {
                    expr = mem.Offset;
                }
            }

            if (mem.Index != RegisterStorage.None)
            {
                eIndex = AluRegister(mem.Index);
                if (mem.Scale != 0 && mem.Scale != 1)
                {
                    eIndex = m.IMul(eIndex, Constant.Create(mem.Index.DataType, mem.Scale));
                }
                expr = m.IAdd(expr, eIndex);
            }
            return(expr);
        }
 private MachineOperand Mem32(RegisterStorage baseReg)
 {
     var mem = new MemoryOperand(PrimitiveType.Word32);
     mem.Base = baseReg;
     return mem;
 }
Exemplo n.º 33
0
 public ExternalProcedure ImportedProcedure(Address addrInstruction, PrimitiveType addrWidth, MemoryOperand mem)
 {
     if (mem != null && addrWidth == PrimitiveType.Word32 && mem.Base == RegisterStorage.None &&
         mem.Index == RegisterStorage.None)
     {
         return(host.GetImportedProcedure(Address.Ptr32(mem.Offset.ToUInt32()), addrInstruction));
     }
     return(null);
 }
 private MachineOperand Mem32(int off)
 {
     var mem = new MemoryOperand(PrimitiveType.Word32);
     mem.Offset = Constant.Word32(off);
     return mem;
 }
Exemplo n.º 35
0
		public void X86Orw32_IndexedAccess()
		{
			MemoryOperand mem = new MemoryOperand(PrimitiveType.Word32, Registers.eax, Registers.edx, 4, Constant.Word32(0x24));
			Expression expr = orw.Transform(instr, mem, PrimitiveType.Word32, state);
			Assert.AreEqual("Mem0[eax + 0x00000024 + edx * 0x00000004:word32]", expr.ToString());
		}
Exemplo n.º 36
0
 private TWord GetEffectiveAddress(MemoryOperand m)
 {
     TWord ea = 0;
     if (m.Offset.IsValid)
         ea += m.Offset.ToUInt32();
     if (m.Index != RegisterStorage.None)
         ea += ReadRegister(m.Index) * m.Scale;
     if (m.Base != null && m.Base != RegisterStorage.None)
     {
         ea += ReadRegister(m.Base);
     }
     return ea;
 }
Exemplo n.º 37
0
 //$TODO: fs:[...] and gs:[...]
 protected override ulong GetEffectiveAddress(MemoryOperand m)
 {
     return(GetEffectiveOffset(m));
 }
Exemplo n.º 38
0
        private IntelInstruction DecodeOperands(Opcode opcode, byte op, string strFormat)
        {
            MachineOperand        pOperand;
            PrimitiveType         width  = null;
            PrimitiveType         iWidth = dataWidth;
            byte                  modRm;
            List <MachineOperand> ops = new List <MachineOperand>();
            int i = 0;

            while (i != strFormat.Length)
            {
                if (strFormat[i] == ',')
                {
                    ++i;
                }

                pOperand = null;
                ImmediateOperand  immOp;
                MemoryOperand     memOp;
                X86AddressOperand addrOp;
                int offset;

                char chFmt = strFormat[i++];
                switch (chFmt)
                {
                case '1':
                    pOperand = immOp = new ImmediateOperand(Constant.Byte(1));
                    break;

                case '3':
                    pOperand = immOp = new ImmediateOperand(Constant.Byte(3));
                    break;

                case 'A':               // Absolute memory address.
                    ++i;
                    ushort off = rdr.ReadLeUInt16();
                    ushort seg = rdr.ReadLeUInt16();
                    pOperand = addrOp = new X86AddressOperand(Address.SegPtr(seg, off));
                    break;

                case 'E':               // memory or register operand specified by mod & r/m fields.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(width, segmentOverride, GpRegFromBits);
                    break;

                case 'Q':               // memory or register MMX operand specified by mod & r/m fields.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(width, segmentOverride, MmxRegFromBits);
                    break;

                case 'G':               // register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat[i++]);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits));
                    break;

                case 'P':               // MMX register operand specified by the reg field of the modRM byte.
                    width = OperandWidth(strFormat[i++]);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits));
                    break;

                case 'I':               // Immediate operand.
                    if (strFormat[i] == 'x')
                    {
                        iWidth = width; // Use width of the previous operand.
                    }
                    else
                    {
                        width = OperandWidth(strFormat[i]); //  Don't use the width of the previous operand.
                    }
                    ++i;
                    pOperand = CreateImmediateOperand(width, dataWidth);
                    break;

                case 'J':               // Relative ("near") jump.
                    width  = OperandWidth(strFormat[i++]);
                    offset = rdr.ReadLeSigned(width);
                    ulong uAddr = (ulong)((long)rdr.Address.Offset + (long)offset);
                    if (defaultAddressWidth.BitSize == 64)      //$REVIEW: not too keen on the switch statement here.
                    {
                        pOperand = AddressOperand.Ptr64(uAddr);
                    }
                    else if (defaultAddressWidth.BitSize == 32)
                    {
                        pOperand = AddressOperand.Ptr32((uint)uAddr);
                    }
                    else
                    {
                        pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr));
                    }
                    break;

                case 'M':               // modRM may only refer to memory.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = DecodeModRM(dataWidth, segmentOverride, GpRegFromBits);
                    break;

                case 'O':               // Offset of the operand is encoded directly after the opcode.
                    width             = OperandWidth(strFormat[i++]);
                    pOperand          = memOp = new MemoryOperand(width, rdr.ReadLe(addressWidth));
                    memOp.SegOverride = segmentOverride;
                    break;

                case 'S':       // Segment register encoded by reg field of modRM byte.
                    ++i;        // Skip over the 'w'.
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(SegFromBits(modRm >> 3));
                    break;

                case 'V':               // XMM operand specified by the reg field of the modRM byte.
                    width = SseOperandWidth(strFormat, ref i);
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits));
                    break;

                case 'W':               // memory or XMM operand specified by mod & r/m fields.
                    width    = SseOperandWidth(strFormat, ref i);
                    pOperand = DecodeModRM(width, segmentOverride, XmmRegFromBits);
                    break;

                case 'a':               // Implicit use of accumulator.
                    pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat[i++])));
                    break;

                case 'b':
                    iWidth   = PrimitiveType.Byte;
                    pOperand = null;
                    break;

                case 'c':               // Implicit use of CL.
                    pOperand = new RegisterOperand(Registers.cl);
                    break;

                case 'd':               // Implicit use of DX or EDX.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = new RegisterOperand(RegFromBitsRexW(2, width));
                    break;

                case 'r':               // Register encoded as last 3 bits of instruction.
                    width    = OperandWidth(strFormat[i++]);
                    pOperand = new RegisterOperand(RegFromBitsRexW(op, width));
                    break;

                case 's':               // Segment encoded as next byte of the format string.
                    pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0'));
                    break;

                case 'F':               // Floating-point ST(x)
                    if (!TryEnsureModRM(out modRm))
                    {
                        return(null);
                    }
                    pOperand = new FpuOperand(modRm & 0x07);
                    break;

                case 'f':               // ST(0)
                    pOperand = new FpuOperand(0);
                    break;

                default:
                    throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat));
                }
                if (pOperand != null)
                {
                    ops.Add(pOperand);
                }
            }
            return(new IntelInstruction(opcode, iWidth, addressWidth, ops.ToArray()));
        }