zoukankan      html  css  js  c++  java
  • 开放源码的.NET 反编译工具 .NET IL调试工具 学习微软中间语言(MSIL)的绝佳工具 Dotnet IL Editor 推荐

    Dotnet IL Editor是一款.NET平台反编译工具,可以反编译.NET程序集文件为IL代码,并且可以执行,调试反编译后生成的IL代码。它的设计出发点比较直观,新建一个项目,添加程序集文件,设置断点(F9),然后就可以调试反编译后的程序集文件,Step Into,Step Out均可,以此原理,可以找到系统的瓶颈代码,也可以深入的学习MSIL微软中间语言。

    先建立一个C#控制台项目,设计一个数字相加的方法,并在Main方法中调用它

    image

    程序总共不到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, 新建一个项目,在项目浏览器中点右键添加程序集,一层层的展开该程序集,如下图所示

    image

    与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代码

    image

    果然如此,生成的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代码,它显示的结果如下

    image

    反编译后的结果与我们曾看到过的知识点一样,验证所学无误。

    在源代码中,控制台主方法中,它调用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堆栈窗口

    image

    IL参数窗口,可显示当前被调用的方法的传入参数

    image

    IL Watch窗口

    image

    表达式可以支持自定义的表达式,这个功能与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会对表达式求值,返回结果显示到右边。

    最后看到执行结果

    image

    控制上显示输出值,与在VS中调试C#源代码的体验完全相同。

    学习IL指令集

    IL Editor的作者肯定想到IL语言不容易记住和熟悉,当你在IL Editor中移动鼠标时,随着鼠标当前行显示的IL代码的不同,在IL Instructions窗口中,会及时的显示它的方法注释,并显示MSDN地址,可以直接点击进入该IL方法的文档。

    设计的非常贴心周到。

    image

    Click here直接挑到MSDN网页中。

    http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.Nop.aspx

    对于我们习惯的语言来说,还没有看到有相关的设置,可以用来设置跳转到中文版的MSDN上。

    image

    命令行调用

    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

  • 相关阅读:
    5-互评-OO之接口-DAO模式代码阅读及应用
    3.1-互评-OO设计-有理数类的设计
    机器学习(3)
    SpringBoot拦截器注入 Service 为空问题
    阿里强制要求的21条Java开发规范【转载】
    动态规划入门
    图神经网络第一章笔记
    PC端工业应用开发宝典3-数据持久化
    PC端工业应用开发宝典2-兼容性问题
    VUE登陆界面监听回车键响应登陆按钮
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/3092233.html
Copyright © 2011-2022 走看看