/// <summary> /// Prints an operand cast. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> public void OperandCast(ref Ud u, ref UdOperand op) { if (u.BrFar > 0) { Syn.UdAsmPrintf(ref u, "far "); } switch (op.Size) { case 8: Syn.UdAsmPrintf(ref u, "byte "); break; case 16: Syn.UdAsmPrintf(ref u, "word "); break; case 32: Syn.UdAsmPrintf(ref u, "dword "); break; case 64: Syn.UdAsmPrintf(ref u, "qword "); break; case 80: Syn.UdAsmPrintf(ref u, "tword "); break; default: break; } }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> public void UdSynPrintImm(ref Ud u, ref UdOperand op) { UInt64 v; if (op.OperandCode == UdOperandCode.OP_sI && op.Size != u.OprMode) { if (op.Size == 8) { v = (UInt64)op.Lval.SByte; } else { Debug.Assert(op.Size == 32, "TODO: REASON"); v = (UInt64)op.Lval.SdWord; } if (u.OprMode < 64) { v = v & ((1ul << u.OprMode) - 1ul); } } else { switch (op.Size) { case 8: v = op.Lval.UByte; break; case 16: v = op.Lval.UWord; break; case 32: v = op.Lval.UdWord; break; case 64: v = op.Lval.UqWord; break; default: Debug.Assert(false, "invalid offset"); v = 0; // keep cc happy break; } } UdAsmPrintf(ref u, "0x{0:x}", v); }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="opr">TODO opr.</param> /// <returns>TODO TODO.</returns> public UInt64 UdSynRelTarget(ref Ud u, ref UdOperand opr) { UInt64 trunc_mask = 0xffffffffffffffff >> (64 - u.OprMode); switch (opr.Size) { case 8: return((u.Pc + (UInt64)opr.Lval.SByte) & trunc_mask); case 16: return((u.Pc + (UInt64)opr.Lval.SWord) & trunc_mask); case 32: return((u.Pc + (UInt64)opr.Lval.SdWord) & trunc_mask); default: Debug.Assert(false, "invalid relative offset size."); return(0); } }
/// <summary> /// Returns true if the given operand is of a general purpose register type. /// </summary> /// <param name="opr">TODO opr.</param> /// <returns>TODO TODO.</returns> private static Boolean UdOprIsGpr(ref UdOperand opr) { return(opr.UdType == UdType.UD_OP_REG && opr.Base >= UdType.UD_R_AL && opr.Base <= UdType.UD_R_R15); }
/// <summary> /// Returns true if the given operand is of a segment register type. /// </summary> /// <param name="opr">TODO opr.</param> /// <returns>TODO TODO.</returns> public static bool UdOprIsSeg(UdOperand opr) { return(opr.UdType == UdType.UD_OP_REG && opr.Base >= UdType.UD_R_ES && opr.Base <= UdType.UD_R_GS); }
/// <summary> /// Generates assembly output for each operand. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> /// <param name="synCast">TODO synCast.</param> private void GenOperand(ref Ud u, ref UdOperand op, Int32 synCast) { switch (op.UdType) { case UdType.UD_OP_REG: Syn.UdAsmPrintf(ref u, "{0}", Syn.UdRegTab[op.Base - UdType.UD_R_AL]); break; case UdType.UD_OP_MEM: if (synCast > 0) { this.OperandCast(ref u, ref op); } Syn.UdAsmPrintf(ref u, "["); if (u.PfxSeg > 0) { Syn.UdAsmPrintf(ref u, "{0}:", Syn.UdRegTab[u.PfxSeg - (int)UdType.UD_R_AL]); } if (op.Base > 0) { Syn.UdAsmPrintf(ref u, "{0}", Syn.UdRegTab[op.Base - UdType.UD_R_AL]); } if (op.Index > 0) { Syn.UdAsmPrintf(ref u, "{0}{1}", op.Base != UdType.UD_NONE ? "+" : String.Empty, Syn.UdRegTab[op.Index - UdType.UD_R_AL]); if (op.Scale > 0) { Syn.UdAsmPrintf(ref u, "*{0}", op.Scale); } } if (op.Offset != 0) { this.UdSynPrintMemDisp(ref u, ref op, (op.Base != UdType.UD_NONE || op.Index != UdType.UD_NONE) ? 1 : 0); } Syn.UdAsmPrintf(ref u, "]"); break; case UdType.UD_OP_IMM: this.UdSynPrintImm(ref u, ref op); break; case UdType.UD_OP_JIMM: this.UdSynPrintAddr(ref u, (Int64)this.UdSynRelTarget(ref u, ref op)); break; case UdType.UD_OP_PTR: switch (op.Size) { case 32: Syn.UdAsmPrintf(ref u, "word 0x{0:x}:0x{1:x}", op.Lval.PtrSeg, op.Lval.PtrOff & 0xFFFF); break; case 48: Syn.UdAsmPrintf(ref u, "dword 0x{0:x}:0x{0:x}", op.Lval.PtrSeg, op.Lval.PtrOff); break; } break; case UdType.UD_OP_CONST: if (synCast > 0) { this.OperandCast(ref u, ref op); } Syn.UdAsmPrintf(ref u, "{0}", op.Lval.UdWord); break; default: return; } }
/// <summary> /// TODO summary. /// </summary> /// <param name="u">TODO u.</param> /// <param name="op">TODO op.</param> /// <param name="sign">TODO sign.</param> public void UdSynPrintMemDisp(ref Ud u, ref UdOperand op, Int32 sign) { Debug.Assert(op.Offset != 0, "TODO: REASON"); if (op.Base == UdType.UD_NONE && op.Index == UdType.UD_NONE) { UInt64 v; Debug.Assert(op.Scale == 0 && op.Offset != 8, "TODO: REASON"); // unsigned mem-offset switch (op.Offset) { case 16: v = op.Lval.UWord; break; case 32: v = op.Lval.UdWord; break; case 64: v = op.Lval.UqWord; break; default: Debug.Assert(false, "invalid offset"); v = 0; // keep cc happy break; } UdAsmPrintf(ref u, "0x{0:x}", v); } else { Int64 v; Debug.Assert(op.Offset != 64, "TODO: REASON"); switch (op.Offset) { case 8: v = op.Lval.SByte; break; case 16: v = op.Lval.SWord; break; case 32: v = op.Lval.SdWord; break; default: Debug.Assert(false, "invalid offset"); v = 0; // keep cc happy break; } if (v < 0) { UdAsmPrintf(ref u, "-0x{0:x}", -v); } else if (v > 0) { UdAsmPrintf(ref u, "{0}0x{1:x}", sign > 0 ? "+" : String.Empty, v); } } }