private MachineOperand Mem32(RegisterStorage baseReg, int off) { var mem = new MemoryOperand(PrimitiveType.Word32); mem.Base = baseReg; mem.Offset = Constant.Word32(off); return mem; }
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()); }
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()); } }
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)); }
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); }
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)); } }
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)); } }
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); }
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); }
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)); }
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; }
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"); } }
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 }); }
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)); }
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); }
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); } }
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; }
/// <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; }
public Expression CreateMemoryAccess(IntelInstruction instr, MemoryOperand memoryOperand, X86State state) { return CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state); }
/// <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 !); }
/// <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 !); }
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); }
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); }
public Expression CreateMemoryAccess(X86Instruction instr, MemoryOperand memoryOperand, X86State state) { return(CreateMemoryAccess(instr, memoryOperand, memoryOperand.Width, state)); }
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("]"); }
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); }
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); } }
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()); }
/// <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); }
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; }
/// <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; }
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; }
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()); }
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; }
//$TODO: fs:[...] and gs:[...] protected override ulong GetEffectiveAddress(MemoryOperand m) { return(GetEffectiveOffset(m)); }
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())); }