IL代码的分析

原创 2015年05月26日 13:59:13

C#代码

    class Program
    {
        static void Main(string[] args)
        {
            string b = GetAge();

            Console.ReadKey();
        }

        private static string GetAge()
        {
            var a = "a";
            var b = "a";
            var c = a;
            return c;
        }
    }




使用Reflector 反编译 IL代码

.class private auto ansi beforefieldinit Program
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: call instance void [mscorlib]System.Object::.ctor()
        L_0006: ret 
    }

    .method private hidebysig static string GetAge() cil managed
    {
        .maxstack 1
        .locals init (
            [0] string str,
            [1] string str2,
            [2] string str3,
            [3] string str4)
        L_0000: nop 
        L_0001: ldstr "a"
        L_0006: stloc.0 
        L_0007: ldstr "a"
        L_000c: stloc.1 
        L_000d: ldloc.0 
        L_000e: stloc.2 
        L_000f: ldloc.2 
        L_0010: stloc.3 
        L_0011: br.s L_0013
        L_0013: ldloc.3 
        L_0014: ret 
    }

    .method private hidebysig static void Main(string[] args) cil managed
    {
        .entrypoint
        .maxstack 1
        .locals init (
            [0] string str)
        L_0000: nop 
        L_0001: call string ILSample.Program::GetAge()
        L_0006: stloc.0 
        L_0007: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
        L_000c: pop 
        L_000d: ret 
    }

}



关键字解释

1.  .class中 auto 关键字什么意思?

StructLayout特性》《.net托管环境下struct实例字段的内存布局(Layout)和大小(Size)



2.  .class中 beforefieldinit 关键字什么意思?

这个关键字表示让运行时决定什么时候调用静态构造函数,也可能在调用函数的开始处,也可能恰恰在第一次访问静态成员或者第一次实例化之前。

总之是运行时决定的,只要在你用到这个类之前搞定就好了

如果没有这个关键字,则运行时恰恰在第一次访问静态成员或者第一次实例化之前调用静态构造函数。

至于C#编译的IL什么情况下有这个关键字什么时候没有关键字,判断起来也很容易,如果有显式的静态构造函数,就没有这个关键字,如果没有显式的构造函数,就有这个关键字。


关于beforefieldinit还有很多有意思的内容,可以参考下面这些园子里高手的文章

关于Type Initializer和 BeforeFieldInit的问题,看看大家能否给出正确的解释

[你必须知道的.NET]第二十三回:品味细节,深入.NET的类型构造器

对beforefieldinit的理解

静态构造函数的执行时机



3.  .method中 .entrypoint 关键字什么意思?

.entrypoint这个比较简单,就是程序的入口点,如果是.EXE的程序集有且只能有一个,如果是.DLL的程序集,当然可以没有入口点。

C#的Main()函数,就被编译器加上了.entrypoint,IL编译器是不认Main()的,只认.entrypoint,所以在IL中,你可以随便让一个函数当作入口。没必要非是Main()。


4.  .method中 hidebysig 关键字什么意思?

 基本相当于C#中的new关键字


5.  每个指令前边的 IL_00XX: 是神马东西

IL_XXXX:其实就是语句的标号,这里的这些标号是ILDASM生成的,就程序执行来说并没有意义。

我们也可以根据自己的情况来写标号,比如"BEGIN: END:"等等

也可以通过标号让程序来跳转,C#不也是有这个功能的么?

接下来的问题就是IL_XXXX后便XXXX这几个数字了,是按什么编号的?其实很明显感觉是相对于方法入口的地址偏移。

为了证实这一点,我也没想到什么好办法,随便写了一个C#程序,反编译后为

复制代码
IL_0000:  ldstr      "dddddddddddddddd" //72 
IL_0005: call void [mscorlib]System.Console::WriteLine(string) //28
IL_000a: ldstr "ffffffffffffffff" //72
IL_000f: call void [mscorlib]System.Console::WriteLine(string) //28
IL_0014: ldstr "dddddddddddddddd" //72
IL_0019: call void [mscorlib]System.Console::WriteLine(string) //28
IL_001e: ldc.i4.3 //19
IL_001f: stloc.0 //0A
IL_0020: ldc.i4.4 //1A
IL_0021: stloc.1 //0B
IL_0022: ldloc.0 //06
IL_0023: ldloc.1 //07
IL_0024: add //58
IL_0025: stloc.2 //0C
IL_0026: ldloc.2 //08
IL_0027: call void [mscorlib]System.Console::WriteLine(int32) //28
IL_002c: ret //2A
复制代码

用UltraEdit打开了.EXE文件。

找到这段IL代码表示二进制代码(OpCode),查找的方法当然要找到每条指令对应的OpCode,

比如0x72代表ldstr;0x28代表call;0x19代表ldc.i4.3  更多需要参考《MSIL指令\操作\Opcode对照表

按照内存的顺序将列下来,就很容易看出来代码地址偏移的关系。

 


读懂IL代码就这么简单 (一)

转自 http://www.lupaworld.com/article-229958-1.html 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道...
  • cp790621656
  • cp790621656
  • 2015年06月20日 14:01
  • 1673

轻松读懂IL

学习一下IL指令,把有用的东西分享给大家。
  • xiaouncle
  • xiaouncle
  • 2016年10月10日 10:40
  • 1071

.NET程序集及其执行(IL、元数据、托管模块、JIT)

从源代码文件到托管模块再到程序集 不管选择了哪种.NET语言编程,需要明白的是,尽管.NET二进制文件与非托管Windows二进制文件(*.dll或*.exe)具有相同的文件扩展名,但它们的内部却是完...
  • Krypton_Lee
  • Krypton_Lee
  • 2016年06月12日 16:09
  • 911

快速启动ILDasm查看当前项目的IL代码

最近在研究IL代码,所以经常在VS中写了C#代码,需要用ILDasm查看下它的IL代码,但每次手工打开实在麻烦,所以这里推荐下使用外部程序:依次打开菜单“工具”-“外部工具”,在“外部工具”对话框中点...
  • bclz_vs
  • bclz_vs
  • 2011年06月15日 16:26
  • 1314

C# 如何查看源程序的IL代码

1、打开microsoft  visual  studio  2008  /  visual  studio  tools /  visual  studio  2008 命令提示  ,并输入ilda...
  • susan19890313
  • susan19890313
  • 2011年11月08日 20:02
  • 9574

【Unity优化】我所理解的IL指令

我所理解的IL指令,这里目前只列举了一些常见指令,box、unbox、newobj、ldc、stloc等等,我认为比较重要的指令,学习Unity最好是要深刻了解C#较为底层的IL实现。...
  • AndrewFan
  • AndrewFan
  • 2017年03月02日 21:39
  • 1793

IL文件修改提高篇

IL文件修改提高篇 ================================== Object:    熟悉强名字签名之后的代码处理 =============================...
  • buguyiqie
  • buguyiqie
  • 2009年05月08日 22:45
  • 1973

IL(中间语言)

http://blog.csdn.net/dodream/article/details/4726421 一、IL与汇编语言 IL是微软.NET平台上衍生出的一门中间语言,.NET平台上的各种高级语言...
  • u014605728
  • u014605728
  • 2016年03月09日 10:42
  • 1189

中间语言(IL)

http://blog.csdn.net/dodream/article/details/4726421 一、IL与汇编语言 IL是微软.NET平台上衍生出的一门中间语言,.NET平台...
  • CNHK1225
  • CNHK1225
  • 2014年09月17日 14:01
  • 1826

认识元数据和IL(中)

书接上回[第二十四回:认识元数据和IL(上)],我们对PE文件、程序集、托管模块,这些概念与元数据、IL的关系进行了必要的铺垫,同时顺便熟悉了以ILDASM工具进行反编译的基本方法认知,下面是时候来了...
  • zhongjiekangping
  • zhongjiekangping
  • 2009年12月28日 11:05
  • 1053
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IL代码的分析
举报原因:
原因补充:

(最多只允许输入30个字)