C# 学习笔记(二)——IL初探

继续学习IL代码,现在我们看下常用的属性器到底是怎么执行的:
C#代码如下:

using System;
namespace ConsoleApp1
{
    
    
    public class MyClass
    {
    
    
        public MyClass(int v)
        {
    
    
            val = v;
        }
        private int val {
    
     get; set; }
        public int GetVal()
        {
    
    
            return val++;
        }
    }
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
            MyClass myClass = new MyClass(12);
            Console.WriteLine(myClass.GetVal());
        }
    }
}

运行结果:
在这里插入图片描述
反编译后拿到IL代码如下:

 .namespace ConsoleApp1 // .namespace:命名空间
{
    
    
    .class public auto ansi beforefieldinit ConsoleApp1.MyClass     //.class 类标识 auto 类的布局方式 ansi 指定类中的字符串必须转换成ANSI字符
        extends [System.Runtime]System.Object                       //.NET Core中beforfieldinit特性时当有一个静态变量被使用时就初始化所有静态变量-  //所有对象继承自基类object
    {
    
    
        // Fields
        .field private int32 '<val>k__BackingField'                 //.field声明字段
        //字段自动生成的两个属性 .custom 自定义方法 .ctor()构造方法  .cctor静态构造方法
        .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        .custom instance void [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Diagnostics.Debug]System.Diagnostics.DebuggerBrowsableState) = (
            01 00 00 00 00 00 00 00
        )
        // Methods
        .method public hidebysig specialname rtspecialname //.method 方法标识 hidebysig 隐藏签名 specialname 特定方法标识
            instance void .ctor (
                int32 v
            ) cil managed //cil managed 标识IL中实现的方法 
        {
    
    
            // Method begins at RVA 0x2050
            // Code size 17 (0x11)
            .maxstack 8 //.maxstack标识JIT它需要保留该方法的最大堆栈大小--just In Time Complier 将中间语言编译成计算机可以理解的机器码

            IL_0000: ldarg.0    //将参数0位加载到堆栈 this
            IL_0001: call instance void [System.Runtime]System.Object::.ctor()    //调用构造方法初始化类
            IL_0006: nop    //nothing to do 
            IL_0007: nop    //nothing to do
            IL_0008: ldarg.0    //将参数0位加载到堆栈 this
            IL_0009: ldarg.1    //将参数1位加载到堆栈(1位为真正的参数)
            IL_000a: call instance void ConsoleApp1.MyClass::set_val(int32)    //执行类myclass中 val 属性器的set方法
            IL_000f: nop    //nothing to do 
            IL_0010: ret    //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
        } // end of method MyClass::.ctor


        .method private hidebysig specialname    //.method 方法标识 hidebysig 隐藏签名 specialname 特定方法标识
            instance int32 get_val () cil managed    //cil managed 标识IL中实现的方法
{
    
    
            .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
                01 00 00 00
            )
            // Method begins at RVA 0x2062
            // Code size 7 (0x7)
            .maxstack 8    //.maxstack标识JIT它需要保留该方法的最大堆栈大小--just In Time Complier 将中间语言编译成计算机可以理解的机器码
            IL_0000: ldarg.0    //将参数0位加载到堆栈 this
            IL_0001: ldfld int32 ConsoleApp1.MyClass::'<val>k__BackingField' /从堆栈0位读取值
            IL_0006: ret    //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
        } // end of method MyClass::get_val

        .method private hidebysig specialname
            instance void set_val (
                int32 'value'
            ) cil managed
{
    
    
            .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
                01 00 00 00
            )
            // Method begins at RVA 0x206a
            // Code size 8 (0x8)
            .maxstack 8 //.maxstack标识JIT它需要保留该方法的最大堆栈大小--just In Time Complier 将中间语言编译成计算机可以理解的机器码
            IL_0000: ldarg.0    //将参数0位加载到堆栈 this
            IL_0001: ldarg.1    //将参数1位加载到堆栈
            IL_0002: stfld int32 ConsoleApp1.MyClass::'<val>k__BackingField'  //替换在对象引用或指针的字段中存储的值
            IL_0007: ret   //从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
        } // end of method MyClass::set_val
        .method public hidebysig
            instance int32 GetVal () cil managed
{
    
    
            // Method begins at RVA 0x2074
            // Code size 24 (0x18)
            .maxstack 2
            .locals init (
                [0] int32,
                [1] int32
            ) //初始化局部变量


            IL_0000: nop    //nothing todo 
            IL_0001: ldarg.0  //将索引为 0 的参数加载到计算堆栈上
            IL_0002: call instance int32 ConsoleApp1.MyClass::get_val() //调用get_val() 获取到val 的值
            IL_0007: ldc.i4.1  //将整数值 1 作为 int32 推送到计算堆栈上
            IL_0008: add    //执行相加命令
            IL_0009: stloc.0 //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中
            IL_000a: ldarg.0 // 将索引为 0 的参数加载到计算堆栈上
            IL_000b: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上
            IL_000c: call instance void ConsoleApp1.MyClass::set_val(int32) //调用set_val 设置val 值
            IL_0011: nop //nothing todo
            IL_0012: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上
            IL_0013: stloc.1 //从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中
            IL_0014: br.s IL_0016 //跳转IL_0016
            IL_0016: ldloc.1 //将索引 1 处的局部变量加载到计算堆栈上
            IL_0017: ret //返回
        } // end of method MyClass::GetVal

        // Properties
        .property instance int32 val()
{
    
    
            .get instance int32 ConsoleApp1.MyClass::get_val()
            .set instance void ConsoleApp1.MyClass::set_val(int32)
        }
    } // end of class ConsoleApp1.MyClass
    .class private auto ansi beforefieldinit ConsoleApp1.Program
        extends [System.Runtime]System.Object
    {
    
    
        // Methods
        .method private hidebysig static
            void Main (
                string[] args
            ) cil managed
{
    
    
            // Method begins at RVA 0x2098
            // Code size 22 (0x16)
            .maxstack 1
            .entrypoint
            .locals init (
                [0] class ConsoleApp1.MyClass myClass
            ) //局部变量 初始化

            IL_0000: nop
            IL_0001: ldc.i4.s 12 // ldc.i4.s 命令 将提供的 int8 值作为 int32 推送到计算堆栈上 --初始化
            IL_0003: newobj instance void ConsoleApp1.MyClass::.ctor(int32) //调用构造方法初始化 newobj
            IL_0008: stloc.0 //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中
            IL_0009: ldloc.0 //将索引 0 处的局部变量加载到计算堆栈上
            IL_000a: callvirt instance int32 ConsoleApp1.MyClass::GetVal() //调用方法 getval() 计算
            IL_000f: call void [System.Console]System.Console::WriteLine(int32) //调用输出方法
            IL_0014: nop
            IL_0015: ret //return
        } // end of method Program::Main
        .method public hidebysig specialname rtspecialname
            instance void .ctor () cil managed //构造函数
{
    
    
            // Method begins at RVA 0x20ba
            // Code size 8 (0x8)
            .maxstack 8
            
            IL_0000: ldarg.0 //this
            IL_0001: call instance void [System.Runtime]System.Object::.ctor() //调用基类的构造函数
            IL_0006: nop
            IL_0007: ret
        } // end of method Program::.ctor
    } // end of class ConsoleApp1.Program
}

几乎每行每个关键字与功能都做了注解,不另外做解释。


每天学一点,总会有收获。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xuetian0546/article/details/107374813