C# 有没有办法查看DynamicMethod生成的x86汇编代码?
我正在构建一种动态方法,使用ILGenerator动态插入操作码。我正在使用VisualStudio插件以DynamicMethod查看IL代码,所以这不是问题 不过,我希望看到JITer发出的最终x86代码。Visual Studio 2017不允许我使用x86汇编代码,无论我如何尝试。它在堆栈中显示为轻量级函数,VS将跳过它C# 有没有办法查看DynamicMethod生成的x86汇编代码?,c#,.net,.net-assembly,cil,C#,.net,.net Assembly,Cil,我正在构建一种动态方法,使用ILGenerator动态插入操作码。我正在使用VisualStudio插件以DynamicMethod查看IL代码,所以这不是问题 不过,我希望看到JITer发出的最终x86代码。Visual Studio 2017不允许我使用x86汇编代码,无论我如何尝试。它在堆栈中显示为轻量级函数,VS将跳过它 是否有办法查看通过编译DynamicMethod生成的x86汇编代码?至少在Visual Studio VS2017中,似乎没有办法这样做。因此,使用WinDbg作为W
是否有办法查看通过编译DynamicMethod生成的x86汇编代码?至少在Visual Studio VS2017中,似乎没有办法这样做。因此,使用WinDbg作为Windows SDK的一部分可能会更幸运 为了让事情变得更简单,我建议让您的应用程序输出一些有用的数据,这将有助于使用WinDbg在内存中查找代码。具体地说,如果您可以在从动态方法创建的委托上输出调用Marshal.GetFunctionPointerForDelegate的结果,这将使您非常接近该方法的代码。您需要为此使用非泛型委托,因此,如果您正在使用动态方法创建Func委托,则需要临时将其替换为非泛型委托 例如:
private delegate int AddDelegate(int a, int b);
public static void DynamicMethodTest()
{
// Create a DynamicMethod that adds its two int parameters
// Passing "true" as the final (restrictedSkipVisibility) parameter causes the method to be JITted immediately when you call .CreateDelegate()
var dynamicAdd = new DynamicMethod("Add", typeof(int), new[] { typeof(int), typeof(int) }, true);
var il = dynamicAdd.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Add);
il.Emit(OpCodes.Ret);
// Use the non-generic AddDelegate defined above, rather than a generic one like Func<int, int, int> so that Marshal.GetFunctionPointerForDelegate() works
var addDelegate = (AddDelegate)dynamicAdd.CreateDelegate(typeof(AddDelegate));
Console.WriteLine("Function Pointer: 0x{0:x16}", Marshal.GetFunctionPointerForDelegate(addDelegate).ToInt64());
Debugger.Break();
}
从这里可以看到动态方法的代码
首先对上面的函数指针输出使用u unassemble命令:
0:000> u 0x0000000012345678 L1
00000000`12345678 49ba2143658700000000 mov r10,87654321h
这里,第一条指令将指向实际动态方法代码的指针地址加载到r10中,因此我们使用dp Display memory-pointer命令来获取指针的目标:
0:000> dp 0x87654321 L1
00000000`87654321 000007fe`9abcdef0
在此地址上运行u unassemble,或在“反汇编”窗口视图->反汇编中输入地址以获取动态方法的代码:
0:000> u 000007fe`9abcdef0
000007fe`9abcdef0 8d0411 lea eax,[rcx+rdx]
000007fe`9abcdef3 c3 ret
...
默认情况下,unassemble命令输出8条指令,您可以向该命令添加长度说明符来更改此设置,例如,添加L20将输出32条0x20指令-由您确定函数的完整范围
或者,您可能会发现使用WinDbg的.NET调试扩展来执行转储动态方法代码的最后一步更容易,在这种情况下,您首先需要使用.loadby sos clr在每个调试会话中只加载一次所需的扩展,然后使用!改为在代码地址上使用u:
0:000> !u 000007fe`9abcdef0
Normal JIT generated code
DynamicClass.Add(Int32, Int32)
Begin 000007fe9abcdef0, size 4
>>> 000007fe`9abcdef0 8d0411 lea eax,[rcx+rdx]
000007fe`9abcdef3 c3 ret
上述所有示例均为64位模式,但在32位模式下,方法基本相同。。
0:000> !u 000007fe`9abcdef0
Normal JIT generated code
DynamicClass.Add(Int32, Int32)
Begin 000007fe9abcdef0, size 4
>>> 000007fe`9abcdef0 8d0411 lea eax,[rcx+rdx]
000007fe`9abcdef3 c3 ret