zoukankan      html  css  js  c++  java
  • ILSpy和ILDasm的使用

    一.工具介绍

    1. ILSpy.exe(点击下载):用来查看IL代码;

    2. ILDasm(点击下载):看.net Framework中的程序集中方法的源码(通过反编译),即BCL中的代码; 

    工具在开发工具中有,也可以从上面的连接链接中下载。

    二.C#程序的编译过程

    1. 预编译:从C#代码编译为MSIL中间语言代码的过程;

    2. 即时编译(JIT):从MSIL中间语言代码编译为机器代码的过程;

    三.简单的实践

    1. 从"+"号看预编译本质

    (1)C#源代码

    string result = "Hello" + "World!";
    Console.Write(result);

    (2)将工程Debug中EXE用ILDasm打开

    打开后如下图一:


    图一

    <1> 条目与原项目的对应关系

    说明:对应关系如下图二:

    图二

    (3)逐条讲解

    <1> 程序集清单(MANIFEST)

    说明:程序集清单,说明了项目的一些情况,里面有版本信息和共钥信息等等,只需做了解。如下图三:

    图三

    <2> 类(Class)的声明

    说明:如下图四,其中红色方框圈出的条目.class开头的为program类的声明。点击打开后可以看到,这个类是继承自System.Object。

    图四

    <3> 构造函数(默认构造函数)

    说明:如下图五可以看到一个构造函数。虽然我们在program里面并有写任何有关构造函数的代码,但是编译器在编译的时候,自动给我们加了一个默认的构造函数。从打开后的界面可以看到"call instace void [mscorlib]System.Object::ctor()",也就是说这个构造函数调用父类的构造函数。

    图五

    <4> Main函数

    说明:可以看到在右边的条目中,这个函数的左边方框里面有一个“s”的符号,这说明这个函数是静态的函数。打开后里面的内容如图六:

     

    图六

    (4)Main函数中的方法讲解

    <1> 查看IL指令

    说明一:在图六中红色方框内部,有很多IL的指令,我们可以通过上网查找来找到这些指令对应的含义。    

    点击进入指令查看网站

    说明二:下面列出图六中红色框内的指令含义。

     

    IL指令

    说明

    Ldstr

    推送对元数据中存储的字符串的新对象引用。

    Stloc.0

    从计算堆栈的顶部弹出当前值并将其存储到索引 处的局部变量列表中。

    Ldloc.0 

    将索引 处的局部变量加载到计算堆栈上。

    Call

    调用由传递的方法说明符指示的方法。

    Ret

    从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

    <2> 程序IL代码分析

    说明:图六中红框内的代码的作用如下表格解释:

    代码

    解释

    Ldstr "HelloWorld!"

    将一个"HelloWorld!"字符串进行压栈

    Stloc.0  

    将栈顶的"HelloWorld!"字符串方法局部的0号变量中

    Ldloc.0 

    0号变量进行压栈,此时栈顶为0号变量,即为"HelloWorld!"字符串

    Call void [mscorlib]System.Console::Write(string)

    调用Console.Write函数,并且将栈顶的"HelloWorld!"字符串进行传入,执行完函数之后将栈顶的"HelloWorld!"字符串弹出栈(堆栈平衡,即进栈出栈数保持一致)

    (3)论一

    在预编译的时候”+“在程序中被认为是直接拼接。编译器将”"Hello" + "World!"”优化为了”"HelloWorld!"”,而不是在IL中进行拼接处理。

    (4)修改代码实验

    说明:我们对原来的代码进行修改。如下:

     

    string value1 = "Hello";
    string value2 = "World!";
    string ruselt = value1 + value2;
    Console.Write(ruselt);

     

     

    (5)重新编译后用ILDasm打开新生成的EXE

    说明:打开后找到Main函数。查看IL代码,如图七:


    图七

    (6)分析

    <1>代码功能

    说明:不难通过上面类似的分析得到如下表格功能。这个请读者尝试自己分析。

     

    代码块

    完成的功能

    第一个红框

    将两个字符串进行拼装,用的是string string.Concat(string,string)方法

    第二个红框

    将字符串显示了

    <2>问

    说明一:我们发现同样的“+”号在不同的用发下出现不同的编译后IL指令。

    说明二:我们还可以直到,这个代码等同于:

    string value1 = "Hello";
    string value2 = "World!";
    string ruselt = string.Concat(value1, value2);
    Console.Write(ruselt);

    (7)结论二

     

    <1> 两个字符串的相加,被预编译器优化成了字符串的拼接;

    <2> 两个字符串变量的相加,被预编译器编译成了对“string.Concat(string,string)”函数的调用;

    2. 用ILSpy查看刚才的string.Concat函数

    (1)打开ILDasm

    说明:打开如下图八如所示:

    图八

    (2) 找到string类中的Cocat(string,string)方法

    说明:如下图九如所示。可以看到传入的string如果为null,在方法内部会转换成string.Empty,所以不用担心如果传入Concat的参数为null的时候会报错的问题。


    图九

     

    四.不能算总结的总结

    (1) 用ILDasm查看了在不同情况下编译器对“+”的编译。通过对MSIL分析,我们初识了这个神奇的中间语言;

    (2) 用ILSpy看了string.Concat函数的源代码(反编译代码),这样就可以查看C#一些函数的内部写法。 

     

    五.写在最后

    (1) 项目的工程代码

    下载上面的工程代码(环境:vs2010)

    (2) 作者想说的话

    本文的目标读者是1年以上的C#开发人员。可能本文写的比较水,但在之后的章节中,难度会增加的很大。写这个文章的目标也是记录自己的学习过程,同时也是对大家的分享,如果有什么不足之处可以反馈给我。这样我也能写出更好的文章,也可以从交流中提高。之后会有IOC,AOP等等,或者是动态代码生成的实现的章节。也会有比较好玩的,例如C#语法糖等等在IL中的解释。希望自己和大家可以抱着一种虚心的态度一起提高,一起学习。最后,本文写于2018年5月6日星期日。

    (3) 下一篇

    预告:初探IL:从IL看C#语法(二)IL在表达式生成树中的运用技巧

     

    ******************转摘:https://blog.csdn.net/ZslLoveMiwa/article/details/80217969?utm_source=blogxgwz4

     
  • 相关阅读:
    PDF文件中的Form保存问题
    Understanding IP Fragmentation
    tcp ip guide IPsec IKE
    Windows安全事件日志中的事件编号与描述
    Cisco PIX fix up and Juniper firewall FTP ALG
    很好的IPSec介绍,详细解释了IKE协商的2个阶段的作用
    virtualbox 下运行Ubuntu 8.10的分辨率和guest additions的问题。
    Fixing the ‘Do you want to display nonsecure items’ message
    windows xp 开始菜单里面所有项目右键不起作用。
    HP backup and recovery manager
  • 原文地址:https://www.cnblogs.com/linybo/p/13360430.html
Copyright © 2011-2022 走看看