如何找到.NET内部调用方法的实现

如何找到.NET内部调用方法的实现,.net,debugging,64-bit,disassembly,.net,Debugging,64 Bit,Disassembly,出于好奇,我想看看一些内部方法实现的汇编代码。在本例中,我尝试从Interlocked.Increment方法开始 通过在源代码上设置断点,然后显示反汇编窗口,我得到以下显示 29: Interlocked.Increment(ref xx); 00007FFDBC110279 lea rcx,[rbp+1FCh] 00007FFDBC110280 call 00007FFE1AD90020 00007FFDBC11028

出于好奇,我想看看一些内部方法实现的汇编代码。在本例中,我尝试从Interlocked.Increment方法开始

通过在源代码上设置断点,然后显示反汇编窗口,我得到以下显示

    29:             Interlocked.Increment(ref xx);
00007FFDBC110279  lea         rcx,[rbp+1FCh]  
00007FFDBC110280  call        00007FFE1AD90020  
00007FFDBC110285  mov         dword ptr [rbp+68h],eax  
00007FFDBC110288  nop 
实施位置似乎位于00007FFE1AD90020。但是我怎么能在这个地址看到反汇编呢?将其输入到反汇编窗口的地址字段中会出现以下错误

The specified address cannot be displayed. End of expression expected.
即使我输入断点位置(00007FFE1AD90020)的地址,我们知道这是一个有效的地址,因为这里我们是断点位置,我也会得到相同的错误

你知道我怎样才能对目标方法进行反汇编吗

注意:我正在64位计算机上使用Windows 8.1 Pro、Visual Studio 2013 Update 2。如果这有什么区别。

您可以使用查看任何(?.NET语言)中.NET函数的源代码,但不能查看相关代码,因为汇编代码是在运行时(JIT)生成的,并且只有在使用某些调试器调试程序时才可见。(如果在Visual Studio中进行调试,其调试器将不允许您单步执行.NET内部调用,因为这些方法具有以下属性:)


在您的情况下,InterlockedIncrement不是.NET内部调用。InterlockedIncrement是kernel32.dll中的Windows API函数(其源代码可能不可见,因为该函数可能包含syscall/sysenter指令,除非您可以运行rdmsr assembly命令以获取syscall/sysenter地址)

您有一个非常好的起点。您使用的是x64调试器,它是VS2012中首次提供的新调试引擎。因此,您可以看到实际的代码地址,而不是从0开始编号的伪代码地址。换句话说,调试器显示的调用地址是准确的,您不必经历痛苦旧的调试器上必须进行完整的地址计算

您还需要做两件非常不直观的事情:

  • 实际上,调试器正在托管模式下运行,将拒绝显示它认为包含本机代码的地址。首先需要启用非托管调试、项目+属性、调试,勾选“启用本机代码调试”选项。然后您必须强制调试器将模式从托管调试引擎切换到非托管调试引擎。使用Debug+Windows+调用堆栈,双击非托管堆栈帧以强制切换模式。显示
    ntdll.dll!RtlUserThreadStart
    的是一个很好的模式切换

  • 您已将显示值中的地址复制到地址框中。不够好,您需要告诉调试器您指的是十六进制值。这需要将
    0x
    放在它前面。换句话说,要键入的正确地址是
    0x00007FFE1AD90020

现在调试器将反编译您要查找的代码。在我的计算机上(与您的地址不同),它如下所示:

00007FFDE1C863B0  mov         eax,1  
00007FFDE1C863B5  lock xadd   dword ptr [rcx],eax  
00007FFDE1C863B9  inc         eax  
00007FFDE1C863BB  ret  

还有一个令人痛苦的细节,您正在查看在抖动优化器关闭的情况下生成的机器代码。这并没有告诉您多少,优化器可以极大地修改代码。非常重要的是,您需要查看将在用户机器上实际运行的代码。这里的CAL也有很大的不同L被优化掉,抖动会生成该方法的内联版本

切换到发布版本并更改一个设置:工具+选项、调试、常规,取消选中“抑制JIT优化”选项。现在您将看到不再需要跳转到上面列出的环和联锁。Increment()方法调用变为

00007FFD82F03AC4  mov         eax,1  
00007FFD82F03AC9  lock xadd   dword ptr [rsp+20h],eax