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()); } }
public ExternalProcedure ImportedProcedureName(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); }
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()); }
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()); }
private ParsedOperand Mem( PrimitiveType width, SegmentRegister 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); }
/// <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); }
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 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"); } }
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 = ImportedProcedureName(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); } }
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)); }
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 ParsedOperand MemW(SegmentRegister 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); }