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对照表

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

 


相关文章推荐

IL93XX系列TFT屏驱动代码(STM32)

  • 2014年07月22日 10:10
  • 3.37MB
  • 下载

解决ilasm.exe无法编译 IL代码一例

众所周知,ildasm.exe和ilasm.exe是破解DONET常用工具之一,但是有时候我们会发现有的程序可以用ildasm反编译,却无法用ilasm编译回去。其中部分是由于包含非托管代码而引起的,...

C# 构造函数避免IL(反编译)代码膨胀的方法--C#编译有点狂啊

C# 构造函数避免IL代码膨胀的方法--C#编译有点狂啊

详解.NET IL代码

一、前言 IL是什么?  Intermediate Language (IL)微软中间语言 C#代码编译过程? C#源代码通过LC转为IL代码,IL主要包含一些元数据和中间语言...

C# IL代码、JIT编译器、MSIL、Ildasm.exe

《CLR via C#》 “虽然这样说很难让人信服,但许多人(包括我)都认为托管应用程序的性能实际上超过了非托管应用程序。有许多原因使我们对此深信不疑---例如,当JIT编译器在运行时将IL代码编译成...

操作步骤:用ildasm/ilasm修改IL代码

转:http://www.cnblogs.com/dudu/archive/2011/05/17/ildasm_ilasm_il.html 在开发中遇到这样一个场景,需要修改一个dll文件(...

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

1、打开microsoft  visual  studio  2008  /  visual  studio  tools /  visual  studio  2008 命令提示  ,并输入ilda...

IL代码底层运行机制

  • 2013年03月09日 13:21
  • 84KB
  • 下载

IL .net中间代码查看器

  • 2011年09月21日 08:57
  • 377KB
  • 下载

unity3D:IL2CPP 内部构建 – 生成代码的调试技巧

转自:http://www.manew.com/thread-40379-1-1.html 在本文中,我们将探究一些代码调试技巧,一些可以使IL2CPP生成的C++代码调试更加容易的技巧。我...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IL代码的分析
举报原因:
原因补充:

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