Dotnet IL Editor是一款.NET平台反編譯工具,可以反編譯.NET程序集文件為IL代碼,並且可以執行,調試反編譯后生成的IL代碼。它的設計出發點比較直觀,新建一個項目,添加程序集文件,設置斷點(F9),然后就可以調試反編譯后的程序集文件,Step Into,Step Out均可,以此原理,可以找到系統的瓶頸代碼,也可以深入的學習MSIL微軟中間語言。
先建立一個C#控制台項目,設計一個數字相加的方法,並在Main方法中調用它
程序總共不到10行,把數字1和2相加,輸出到控制台。
public class TestEditor { public static int Sum(int a, int b) { return a + b; } public static void Main(string [] args) { Console.WriteLine(Sum(1,2)); Console.ReadLine(); } }
執行程序Dile.exe, 新建一個項目,在項目瀏覽器中點右鍵添加程序集,一層層的展開該程序集,如下圖所示
與Visual Studio的解決方案瀏覽器相似,它按照命名空間展開,列出了程序集中的方法,雙擊該方法,可以在編輯器中打開IL源代碼,IL編輯器窗口是只讀的。
探索.NET代碼的奧秘
記得.NET教材中有一條原理知識,類型默認繼承自object類,當沒有為類型定義構造方法(ctor)時,.NET編譯器會為它生成一個默認的構造方法,該方法不帶參數。如果在阻止默認生成的構造方法,只需要為類型定義一個方法,即可阻止編譯器的這個行為。
為什么不現在就試一下這條原理是否正缺,或是有什么遺漏的地方。於是修改類型定義的方法,給它加上一個帶參數的構造方法,該方法為一個空方法,帶參數以區別是.NET生成還是我們手動添加的。源代碼是這樣的
public class TestEditor { public TestEditor(string str) { } public static int Sum(int a, int b) { return a + b; } public static void Main(string [] args) { Console.WriteLine(Sum(1,2)); Console.ReadLine(); } }
TestEditor類型現在有一個自定義的構造方法,帶一個字符串參數。再次到IL Editor中打開,看看它生成的IL代碼
果然如此,生成的IL代碼中,沒有默認的構造方法,取而代之的是我們定義的構造方法。
再來驗證一條知識點,const常量會被以常量的形式編譯到程序集中,因而它的效率很高。再修改C#源代碼,編譯,IL Editor中打開,C#的源代碼現在看起來是這樣的
public class TestEditor { public const string ProductName="Enterprise Solution"; public TestEditor(string str) { } public static int Sum(int a, int b) { return a + b; } public static void Main(string [] args) { string productionName = ProductName; Console.WriteLine(productionName); Console.WriteLine(Sum(1,2)); Console.ReadLine(); } }
再來看生成的IL代碼,它顯示的結果如下
反編譯后的結果與我們曾看到過的知識點一樣,驗證所學無誤。
在源代碼中,控制台主方法中,它調用1+2求和的方法,也是以常量的形式編譯進程序集。
Console.WriteLine(Sum(1,2));
對應的.NET IL代碼是
ldc.i4.1
ldc.i4.2
call int32 ILEditorLibrary.TestEditor::Sum(int32, int32)
call void [mscorlib]System.Console::WriteLine(int32)
IL是基於堆棧的語言,先壓入值1,再壓入值2,再對二者求和,最后調用方法顯示到控制台上。
調試IL代碼
IL Editor的調試功能是它的亮點之一,可以在打開的IL代碼中直接設置斷點(F9, Toogle breakpoint),然后點擊工具欄中的Run,啟動調試。調試程序的幾個要點,看堆棧Stack, 看變量值Watch,IL Editor都可以做到。
IL堆棧窗口
IL參數窗口,可顯示當前被調用的方法的傳入參數
IL Watch窗口
表達式可以支持自定義的表達式,這個功能與VS中的即時窗口類似,輸入表量或表達式,右邊計算出結果。
IL Editor的作者列舉出了一些經過測試,演示的表達式代碼,他們是
5 * -6 1 + 2 * 3 - 10 / 5 * 5 (1 + 2 * 3 - 10 / 5 * 5).ToString() (-5).ToString() new object() + "a" "abc".Length.ToString() System.Type.GetType("System.String").GUID.ToByteArray() TestApplication.DebugTest.CreateOperatorTest4("op1") | true TestApplication.DebugTest.ParamsTest2() TestApplication.DebugTest.ParamsTest2(5, 6) System.String.Format("{0}{1}{2}{3}{4}", "a", "b", "c", "d", "e") new object[] {4, "a", 5} ((System.Exception){exception}).Message TestApplication.GenericClass<int, System.DateTime>.StaticMethod<string>("test") new TestApplication.TestClass<int, string>[] {new TestApplication.TestClass<int, string>(1, "one")} TestApplication.GenericClass<int, string>.NestedGenericClass<System.Type>.StaticMixedMethod<System.DateTime>(System.DateTime.Now, 5, null)
是的,你可以直接在窗口中輸入,IL會對表達式求值,返回結果顯示到右邊。
最后看到執行結果
控制上顯示輸出值,與在VS中調試C#源代碼的體驗完全相同。
學習IL指令集
IL Editor的作者肯定想到IL語言不容易記住和熟悉,當你在IL Editor中移動鼠標時,隨着鼠標當前行顯示的IL代碼的不同,在IL Instructions窗口中,會及時的顯示它的方法注釋,並顯示MSDN地址,可以直接點擊進入該IL方法的文檔。
設計的非常貼心周到。
Click here直接挑到MSDN網頁中。
http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Nop.aspx
對於我們習慣的語言來說,還沒有看到有相關的設置,可以用來設置跳轉到中文版的MSDN上。
命令行調用
IL Editor支持命令行方式的調用,命令行的參數列表如下所示
dile [/p "Project name"] [/a "assembly path"] [/l "project name.dileproj"]
/p Optional. When DILE is loaded, a new project will be created with the given name.
/a Optional, can be repeated. When DILE is loaded, a new project will be created and the given assemblies will be added to it.
/l Optional. DILE will load the given dileproj file. If this parameter is given then /p and /a will be ignored. If a parameter is followed by a name/path which contains spaces then it should be written between quotes
創建一個Test project的項目
dile /p "Test project"
創建一個Test project的項目,並給它添加程序集
dile /p "Test project" /a TestAssembly.exe
創建一個新項目,並從兩個不同的地方加載程序集
dile /a TestAssembly.exe /a "c:\assemblies\My test.dll"
加載一個現有的項目
dile /l TestProject.dileproj
最后,附上項目主頁地址
項目主頁: http://dile.sourceforge.net/
作者博客地址:http://pzsolt.blogspot.com










