2011-08-03 69 views
7

我有興趣查看C#程序(不是CLR字節碼指令)的實際x86彙編輸出。有沒有一個好的方法來做到這一點?檢索JIT輸出

回答

4

您應該在SOS/SOSEX中使用WinDbg,確保您希望查看x86代碼的方法在方法表中被打亂,然後使用u命令查看實際的拆卸。因此你會看到實際的代碼。

正如其他人在此提到的那樣,使用ngen可以看到與實際JIT編譯結果不完全匹配的代碼。使用Visual Studio也是可能的,因爲JIT的編譯在很大程度上取決於調試器是否存在的事實。

UPD:一些澄清。 WinDbg也是一個調試器,但它是本地之一。

Here您可以詳細瞭解該技術。

7

在Visual Studio中調試應用程序時,可以右鍵單擊已停止的代碼(使用斷點)並單擊「轉到反彙編」。您可以通過本機指令進行調試。

至於用磁盤上的* .exe文件做這件事,也許你可以使用NGen來生成原生輸出,然後反彙編它(儘管我從來沒有嘗試過,所以我不能保證它會起作用)。

下面是簡單的算術運算的一些示例操作碼這是寫在C#:

 
      int x = 5; 
mov   dword ptr [ebp-40h],5 
      int y = 6; 
mov   dword ptr [ebp-44h],6 
      int z = x + y; 
mov   eax,dword ptr [ebp-40h] 
add   eax,dword ptr [ebp-44h] 
mov   dword ptr [ebp-48h],eax 
+0

請注意,如果您想查看實際優化代碼,則需要按照[此處](此處)(https://stackoverflow.com/a/4678883/238419)中的步驟操作 –

2

你可以通過放置一個斷點,然後查看Dissassembly窗口(Alt + Ctrl + d使用Visual Studio調試器)或嘗試Native Image Generator Tool(ngen.exe)。

1

您可以執行內存轉儲。但是請注意,內存代碼不一定包含每種方法。

ngen做AOT或提前生成代碼,它可以與JIT代碼不同。

4

由於@IvanDanilov answered,您可以使用WinDbg和SOS。我正在單獨回答,以提供一個步驟。

在本例中,我想從查看AreEqual()方法的拆卸:

using System; 

namespace TestArrayCompare 
{ 
    class Program 
    { 
     static bool AreEqual(byte[] a1, byte[] a2) 
     { 
      bool result = true; 
      for (int i = 0; i < a1.Length; ++i) 
      { 
       if (a1[i] != a2[i]) 
        result = false; 
      } 
      return result; 
     } 

     static void Main(string[] args) 
     { 
      byte[] a1 = new byte[100]; 
      byte[] a2 = new byte[100]; 
      if (AreEqual(a1, a2)) 
      { 
       Console.WriteLine("`a1' equals `a2'."); 
      } 
      else 
      { 
       Console.WriteLine("`a1' does not equal `a2'."); 
      } 
     } 
    } 
} 

步驟:

  1. 打開WinDbg的。從文件菜單中,選擇「打開可執行文件...」。瀏覽到EXE的位置(在我的情況下,C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release\TestArrayCompare.exe)。
  2. 將包含PDB文件的目錄添加到符號路徑中。例如:g

  3. clr.dll

     
    sxe ld:clr 
    
  4. 通過運行 '開始' 命令繼續:

     
    .sympath "C:\Users\Daniel\Documents\Visual Studio 2013\Projects\TestArrayCompare\TestArrayCompare\bin\Release" 
    
  5. 在WinDbg中的命令窗口中,當clr.dll通過加載設置斷點ModLoad,加載SOS:.loadby sos clr

  6. 運行BPMD以斷開您無線的方法噓看到拆卸。例如:

     
    0:000> !BPMD TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Adding pending breakpoints... 
    
  7. 通過運行 '開始' 命令,再繼續:g

  8. 運行Name2EE看方法描述符。例如:

     
    0:000> !Name2EE TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Module:  00a62edc 
    Assembly: TestArrayCompare.exe 
    Token:  06000001 
    MethodDesc: 00a637a4 
    Name:  TestArrayCompare.Program.AreEqual(Byte[], Byte[]) 
    Not JITTED yet. Use !bpmd -md 00a637a4 to break on run. 
    
  9. 在「Not JITTED yet」行中運行BPMD命令。例如:

     
    0:000> !bpmd -md 00a637a4 
    MethodDesc = 00a637a4 
    Adding pending breakpoints... 
    
  10. 再繼續:g

  11. 您應該看到 「實時編譯......」 在命令窗口中。重新運行Name2EE命令以查看JIT代碼的地址。例如:

     
    0:000> !Name2EE TestArrayCompare.exe TestArrayCompare.Program.AreEqual 
    Module:  00a62edc 
    Assembly: TestArrayCompare.exe 
    Token:  06000001 
    MethodDesc: 00a637a4 
    Name:  TestArrayCompare.Program.AreEqual(Byte[], Byte[]) 
    JITTED Code Address: 00b500c8 
    
  12. 使用u命令拆卸,起始於列出的代碼的地址。例如:

     
    0:000> u 00b500c8 L20 
    00b500c8 55    push ebp 
    00b500c9 8bec   mov  ebp,esp 
    00b500cb 57    push edi 
    00b500cc 56    push esi 
    ... 
    

(針對上述情況,我使用的WinDbg 6.3.9600.17200 X86從Windows 8.1 SDK。)

一個簡便的參考是SOS.dll (SOS Debugging Extension) reference page on MSDN