实例学习 .Net 中间语言指令

实例学习 .Net 中间语言指令
    今天研究了一下 .Net 程序集的中间语言代码,总体上感觉要看懂也不难。因为中间语言常用的指令并不多,看熟了很容易就可以理解程序逻辑。具体的指令说明大家可以看 CLI 中有关 CIL 的文档(可以从本文最后的链接下载),我这里写了两个简单的示例方法,对照 C# 语言和中间语言,用注释的形式说明了中间语言中一些指令的作用。

中间语言代码示例
/**
///
示例一:输出整数的立方值。
private void PrintCube( int i )
{
    int cube = i * i * i;
    Console.WriteLine( cube );
}

/**/// 分析 IL 代码 //
/// 方法签名。
/// hidebysig:MethodAttributes 枚举值之一,指示此方法按名称和签名隐藏,否则只
/// 按名称隐藏。
/// cil managed:未查到具体资料,应是“受中间语言管理”之意。
  .method private hidebysig instance void
          PrintCube(int32 i) cil managed
  {
    // 代码大小       15 (0xf)
    .maxstack  2
    /** 在 .locals 部分声明所有的局部变量。
    .locals init ([0] int32 cube)    /** 第一个名局部变量,int 型,名为 cube。索
                                    /// 引从 0 开始。
    IL_0000:  nop    /** no operation.
    IL_0001:  ldarg.1    /** load argument 第一个方法参数入栈,比如“3”。索引号
                        /// 从 1 开始,而不是从 0 开始。
    IL_0002:  ldarg.1    /** 再次向堆栈压入第一个方法参数,又一个“3”。
    IL_0003:  mul    /** multiply 计算堆栈最顶上两个数的乘积 3×3,并把结果入栈,
                    /// 即堆栈最顶部是 9 了。
    IL_0004:  ldarg.1    /** 再次压入第一个方法参数“3”。
    IL_0005:  mul    /** 堆栈最顶上是“3”,第二是“9”,计算 3×9,此时 27 入栈。
    IL_0006:  stloc.0    /** pop value from stack to local variable 堆栈最顶上的
                        /// 值“27”出栈,并被赋给索引位置“0”处的局部变量 cube,
                        /// 即内存中变量 cube 的值为“27”。
    IL_0007:  ldloc.0    /** 局部变量 cube 的值“27”入栈。
    IL_0008:  call       void [mscorlib]System.Console::WriteLine(int32)
                        /** 控制台输出堆栈最顶上的 32 位整数“27”。
    IL_000d:  nop    /** no operation.
    IL_000e:  ret    /** return from method.
  } // end of method Program::PrintCube

 


/**
///
示例二:把字符串拆分成字符,并按顺序每行输出一个字符
public void SeparateString( string source )
{
    if( source == null )
        return;

    int count = source.Length;

    char c;
    for( int i = 0; i < count; i++ )
    {
        c = source[ i ];
        Console.WriteLine( c );
    }
}

/**/// 分析 IL 代码 //
  .method public hidebysig instance void
          SeparateString(string source) cil managed
  {
    // 代码大小       55 (0x37)
    .maxstack  2
    .locals init ([0] int32 count,
             [1] char c,
             [2] int32 i,
             [3] bool CS$4$0000)    /** 索引为“3”的这个布尔型局部变量在 C# 代
                                    /// 码中并未显式声明,是编译器编译时添加的,
                                    /// 用于保存执行过程中布尔运算的结果,比如比
                                    /// 较 source 是否为空时,以及比较 i<count 时。
    IL_0000:  nop
    IL_0001:  ldarg.1    /** 方法参数 source 的值入栈。
    IL_0002:  ldnull    /** “空引用”null入栈。
    IL_0003:  ceq    /** compare equal 比较栈顶的 null 和第二项的 source 是否相等,并
                    /// 把结果 0(false,source 不为空)或 1(true,source 为空)入栈。
    IL_0005:  ldc.i4.0    /** 32 位整型数“0”入栈。
    IL_0006:  ceq    /** 比较栈顶的“0”和堆栈的第二项,第二项可能是“0”,也可能
                    /// 是“1”。比较的结果“1”或“0”入栈。
    IL_0008:  stloc.3    /** 栈顶的“1”或“0”出栈,被保存到索引为“3”的局部变量中。
    IL_0009:  ldloc.3    /** 执行后,栈顶为“1”(source 不为空)或“0”(source 为空)。
    IL_000a:  brtrue.s   IL_000e    /** branch on non-false or non-null 判断栈顶是否
                                    /// 为“1”,如果是,跳转到第“IL_000e”行;否则
                                    /// 继续往下执行。

    IL_000c:  br.s       IL_0036    /** unconditional branch 当栈顶为“0”时,才会
                                    /// 执行到这一行,这一行的执行结果是程序无条件
                                    /// 跳转到第“IL_0036”行。

    IL_000e:  ldarg.1
    IL_000f:  callvirt   instance int32 [mscorlib]System.String::get_Length()   
                        /** 对堆栈最顶上的字符串调用其获取长度的实例方法,长度值被入栈。
                        /// “get_Length()”实际是字符串 Length 属性的“get”部分。
    IL_0014:  stloc.0    /** 局部变量 count 被赋值为字符串长度。
    IL_0015:  ldc.i4.0
    IL_0016:  stloc.2    /** 局部变量 i 被赋值为 0。
    IL_0017:  br.s       IL_002e    /** 无条件跳转到第“IL_002e”行。

    IL_0019:  nop
    IL_001a:  ldarg.1
    IL_001b:  ldloc.2
    IL_001c:  callvirt   instance char [mscorlib]System.String::get_Chars(int32)   
                        /** source 中索引为 i 处的 char 值入栈。
    IL_0021:  stloc.1
    IL_0022:  ldloc.1
    IL_0023:  call       void [mscorlib]System.Console::WriteLine(char)    /** char 值被输
                                                                        /// 出到控制台。
    IL_0028:  nop
    IL_0029:  nop
    IL_002a:  ldloc.2    /** i 值入栈。
    IL_002b:  ldc.i4.1    /** 32 位整数 1 入栈。
    IL_002c:  add    /** i+1 的结果入栈。
    IL_002d:  stloc.2    /** i=i+1。
    IL_002e:  ldloc.2    /** i 值入栈。
    IL_002f:  ldloc.0    /** count 值入栈。
    IL_0030:  clt    /** compare less than 比较 i<count 是否为真,比较结果入栈。
    IL_0032:  stloc.3
    IL_0033:  ldloc.3
    IL_0034:  brtrue.s   IL_0019    /** 如果 i<count 则跳转到第“IL_0019”行。

    IL_0036:  ret
  } // end of method Program::SeparateString
Common Intermediate Language Instruction Set

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值