详解.net中IL语言

什么是IL语言

中间语言,又称(IL语言)。充当Clr与.net 平台的中间语言,比如用C#编写程序,编译器首先是把C#代码转译成IL语言,最终由Clr解释执行,下面我们学习下IL语言。

如何读懂IL语言

  • 写一个helloworld的.net 程序,编译运行完成。
      static void Main(string[] args)
      {
          Console.WriteLine("hello world");
      }
  • 使用ildasm.exe(C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools)反编译代码,得到IL代码如下:
     .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // 代码大小       13 (0xd)
        .maxstack  8
        IL_0000:  nop
        IL_0001:  ldstr      "hello world"
        IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
        IL_000b:  nop
        IL_000c:  ret
      } // end of method Program::Main
  • 查找对应的指令表,来确定对应的含义

指令名称

说明

Ldstr

推送对元数据中存储的字符串的新对象引用。

Nop

如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。

Call

调用由传递的方法说明符指示的方法。

Ret

从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

  • 其它几个名词的的解释 hidebysig: 与之对就的是hidebyname,这个是确定使用方法的签名还是使用方法的名称来确定调用哪个方法.
  • 整个的IL语言解释
   .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint //代码入口 
        // 代码大小       13 (0xd)
        .maxstack  8  //整个程序的堆栈大小
        IL_0000:  nop  //无实在意义
        IL_0001:  ldstr      "hello world"  //定义字符
        IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)   //调用WriteLine变量
        IL_000b:  nop
        IL_000c:  ret  //返回
      } // end of method Program::Main

更复杂的Demo

  • 添加编写如下C#代码
 class Program
  {
      static void Main(string[] args)
      {
          var a = 0;
          var b = 1;
          var c = Add(a, b);
          Console.WriteLine(c.ToString());
      }

      public static int Add(int x,int y)
      {
          return x + y;
      }
  }
  • 生成相关的IL代码及解释
	.method private hidebysig static void  Main(string[] args) cil managed
	{
	.entrypoint
	// 代码大小       27 (0x1b)
	.maxstack  2
	.locals init ([0] int32 a,
			[1] int32 b,
			[2] int32 c) //定义3个变量
	IL_0000:  nop
	IL_0001:  ldc.i4.0 //将整数值 0 作为 int32 推送到计算堆栈上。
	IL_0002:  stloc.0  //从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。
	IL_0003:  ldc.i4.1 //将整数值 1 作为 int32 推送到计算堆栈上。
	IL_0004:  stloc.1  //从计算堆栈的顶部弹出当前值并将其存储到索引 1 处的局部变量列表中。
	IL_0005:  ldloc.0  //将索引 0 处的局部变量加载到计算堆栈上,这里指a。
	IL_0006:  ldloc.1  //将索引 1 处的局部变量加载到计算堆栈上,这里指b。
	IL_0007:  call       int32 ILTest.Program::Add(int32,
													int32)  //调用Add方法
	IL_000c:  stloc.2 //将索引 2 处的局部变量加载到计算堆栈上,这里指c。 
	IL_000d:  ldloca.s   c  //将位于特定索引处的局部变量的地址加载到计算堆栈上(短格式)。
	IL_000f:  call       instance string [mscorlib]System.Int32::ToString() 
	IL_0014:  call       void [mscorlib]System.Console::WriteLine(string)
	IL_0019:  nop
	IL_001a:  ret
	} // end of method Program::Main

Add方法:

	.method public hidebysig static int32  Add(int32 x,int32 y) cil managed
	{
	// 代码大小       9 (0x9)
	.maxstack  2
	.locals init ([0] int32 V_0) //创建一个V_0的局部变量
	IL_0000:  nop
	IL_0001:  ldarg.0 //将索引为 0 的参数加载到计算堆栈上。
	IL_0002:  ldarg.1 //将索引为 1 的参数加载到计算堆栈上。
	IL_0003:  add     //将两个值相加并将结果推送到计算堆栈上。
	IL_0004:  stloc.0
	IL_0005:  br.s       IL_0007   //无条件地将控制转移到目标指令(短格式)
	IL_0007:  ldloc.0    //将索引 0 处的局部变量加载到计算堆栈上。
	IL_0008:  ret
	} // end of method Program::Add

(本文完)

作者:老付 如果觉得对您有帮助,可以下方的订阅,或者选择右侧捐赠作者,如果有问题,请在捐赠后咨询,谢谢合作 如有任何知识产权、版权问题或理论错误,还请指正。 自由转载-非商用-非衍生-保持署名,请遵循:创意共享3.0许可证 交流请加群113249828: 点击加群 或发我邮件 laofu_online@163.com

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏SDNLAB

【一课专栏】解构2 - 明察YangInstanceIdentifier

屈原《离骚》中云:“路漫漫其修远兮,吾将上下而求索”,其实,学习软件编程,学习SDN技术也是一个路漫漫,上下求索的过程。

29620
来自专栏熊二哥

快速入门系列--深入理解C#

C#语言在近些年得到了长足的方法,代码风格越来越简洁美观,例如常用的泛型及其约束、可空类型、隐式类型、匿名类型和委托等,通过下面的表格可以对这部分相对简单的特性...

21150
来自专栏金朝麟的专栏

Module.exports和exports的区别

学习Seajs时,看到了exports.doSomething和module.exports,想对这两者的区别一探究竟。官方解释因为SeaJs和Nodejs都是...

20800
来自专栏Kiba518

C#语法——元组类型

  我们现在使用的C#语法已经可以满足日常的开发需求,但C#语法还在进行版本的更新,在创造更多更优秀的语义来让我们使用。这里介绍一下C#5.0里的提供的语法——...

12130
来自专栏GuZhenYin

C#7.0之ref locals and returns (局部变量和引用返回,之前欠大家的,现在补上)

没看过原文的请移步:[干货来袭]C#7.0新特性(VS2017可用) 废话不多说,直接进入正题. 首先我们知道 ref关键字是将值传递变为引用传递 那么我们先来...

20990
来自专栏编码小白

tomcat源码解读三(2) tomcat中JMX的源码分析

     在这里我是将tomcat中的jmx给拆分出来进行单独分析,希望通过此种方式能够尽可能的出现更多的问题,以便对其有更多的了解,首先需要声明的是tomca...

54550
来自专栏Java技术栈

深度历险:Redis 内存模型详解

Redis 是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说 Redis 是实现网站高并发不可或缺的一部分。

20820
来自专栏一枝花算不算浪漫

[C#反射]C#中的反射解析及使用.

444140
来自专栏ShaoYL

Objective-C中的@property和@synthesize用法

415110
来自专栏伪君子的梦呓

题解 ~ 简单的a+b ~ C++ 做法

13140

扫码关注云+社区

领取腾讯云代金券