详解.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 条评论
登录 后参与评论

相关文章

来自专栏Hongten

JavaScript

872
来自专栏光变

Redis持久化文件RDB的格式解析

Redis的RDB文件是对内存存储的一种表示。这个二进制文件足以完全恢复Redis当时的运行状态。 RDB文件格式针对快速读写进行了优化。LZF压缩被用于减小文...

1261
来自专栏GreenLeaves

C#多线程学习一

一、概述:C#支持多线程并行执行程序,一个线程有他单独的执行路径,能够与其他线程同时执行,一个程序是由一个单线程开始,该单线程由CLR(公共语言运行时)和操作系...

2577
来自专栏伪君子的梦呓

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

1074
来自专栏Java技术栈

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

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

1682
来自专栏熊二哥

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

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

2005
来自专栏SDNLAB

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

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

2212
来自专栏java一日一条

Stackoverflow上人气最旺的10个Java问题

我一直认为Java是引用传递;然而,我看了一堆博客(例如这篇)声称不是这样的。我认为我没有理解它们之间的区别。

732
来自专栏大内老A

ModelBinder——ASP.NET MVC Model绑定的核心

Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数。通过前面的介绍我们知道Action方法的参数通过ParameterDescrip...

2179
来自专栏java一日一条

Stackoverflow上人气最旺的10个Java问题

我一直认为Java是引用传递;然而,我看了一堆博客(例如这篇)声称不是这样的。我认为我没有理解它们之间的区别。

1063

扫码关注云+社区