• 读懂IL代码(三)


    由于要写毕业论文的缘故,最近比较没有时间写,总是要抽出时间抽出时间。诶,这样的生活比较烦躁。

    这一篇主要写委托、类、方法的IL代码,一一来说明。

    委托:搞过C#的都应该清楚,委托实际上是一个类。编译器会把它编译成一个类,继承自MulticastDelegate的类,里面有三个方法,BeginInvoke,EndInvoke和Invoke,当我们使用委托方法名进行调用方法时,编译器内部实际上是调用了Invoke方法(语法糖)。

    以下就用简单的代码来掩饰一下委托的IL代码

    先来看看编译器把委托编译成什么样子:

    好啦,下面就是重要的IL代码啦,其实大家可以先自己去尝试解析一下,我觉得当自己去尝试某些东西的话,会记得更牢一些。

    看到上面的代码,是否有的指令非常熟悉,我觉得大部分的指令我们在前面两篇都有讲过了,不过在这里我还是一句一句的解释

    .method private hidebysig static void Main(string[] args)cilmanaged
    {
        .entrypoint //入口啦,这个说过很多次了。
        .maxstack 2 //评估堆栈可能容纳数据项的最大个数。
        .locals init (
            [0] class TestDemo4.Program/MyDele dele) //上面已经讲过了,委托最终是编译成类的,所以这里是一个类类型的变量dele,存储在调用栈。
        L_0000: nop //No Operation。
        L_0001: ldnull //将空引用推送到计算堆栈上。
        L_0002: ldftn void TestDemo4.Program/UserInfo::PrintName(string) //将指向实现特定方法的本机代码的非托管指针(native int类型)推送到计算堆栈上,也就是指将方法指针压入评估栈中。
        L_0008: newobj instance void TestDemo4.Program/MyDele::.ctor(object, native int)//创建委托实例并压入评估栈中。这一步会调用委托的构造函数(.ctor),这个构造函数需要两个参数,一个是对象引用,这里就是L_0001:ldnull:空对象,第二个参数是方法的地址L_0002中的动作。
        L_000d: stloc.0 //将评估栈中的委托实例保存到调用栈的第0个位置上。
        L_000e: ldloc.0 //获取调用栈中第0位置的值(委托实例),并压入评估栈中。
        L_000f: ldstr "Helius" //加载字符串,在托管堆中创建Helius对象,并把引用存放在评估栈上。
        L_0014: callvirt instance void TestDemo4.Program/MyDele::Invoke(string) //Invoke,看到没,委托实例调用了Invoke的的方法来执行。callvirt只能调用实例方法和虚方法,不能调用静态方法
        L_0019: nop //No Operation
        L_001a: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() //调用ReadKey方法。
        L_001f: pop //清空评估栈。
        L_0020: ret //return。
    }
    

    --------------------------------------------------------------------------------分割线------------------------------------------------------------------------------------------------

    类与方法的常规代码:

    这里先从Person类开始解析,这里我使用到了自动属性,大家应该也都很明了,编译器把自动属性编译成了一个私有字段和两个方法。

     OK啦,又到了看Main函数的IL代码时间了

    上面的IL代码中,只有一个指令在之前没有出现过,那就是newobj这个指令,这个指令的意思是创建一个实例对象,并将实例对象的引用推送到计算堆栈上,也就是评估栈上。

    我不想一句一句的解析了,我现在就用画图的形式来解释一下实例化一个类的过程:

    其实我这里也只是泛泛之谈而已,我觉得大家完全有必要自己写一个小Demo,编译完之后使用Reflector看一下IL代码,这样子会更清晰一些。而且有不懂的地方,我觉得大家完全可以自行百度或者拿出来让大家讨论一下。

    下一章再讲一下流程控制的IL代码后,我想应该就可以结束掉这部分内容了。

    
    
    
  • 相关阅读:
    UNIX:处理SIGCHLD信号
    多维数组,指针数组使用,指向指针的指针
    bit field
    链表操作,获得泛型效果
    简明 Vim 练级攻略
    指针3,指向链表对象指针的指针
    大端模式,指针数组
    C宏设置掩码
    springboot 启动报错: Multiple Dockets with the same group name are not supported. The following duplicat
    HTML5学习笔记三
  • 原文地址:https://www.cnblogs.com/Helius/p/5299217.html
Copyright © 2020-2023  润新知