通用中间语言(Common Intermediate Language,简称CIL)(亦被称作MSIL或IL)是一种属于通用语言基础架构和.NET框架的低阶(lowest-level)的人类可读的编程语言,它是一种代码指令集。CIL可以在任何支持CLI(Common Language Infrastructure,通用语言基础架构)的环境中运行,.NET是微软对CLI的实现,Mono是Xamarin对CLI的又一实现,所以CIL能在.NET运行时以及Mono运行时中运行,跟具体的平台或者CPU无关,这样就无需为不同的平台部署不同的内容了。
如果想让一份代码在不同的平台中运行,只需要把代码的编译分为两部分即可:
1、把源代码编译成CIL的预编译过程(其实之后CIL还会被编译成一种位元码,生成一个CLI Assembly)
2、运行时把CIL(其实是CLI Assembly)编译成本地指令的即时编译过程

初始CIL代码

C#代码:

namespace ConsoleTest
{class Program{// Methodsprivate static void Main(string[] args){Console.WriteLine("Hello World");Console.ReadKey();}}
}

CIL代码:

.class private auto ansi beforefieldinit ConsoleTest.Programextends [mscorlib]System.Object
{.method public hidebysig specialname rtspecialname instance void  .ctor() cil managed{// 代码大小       7 (0x7).maxstack  8IL_0000:  ldarg.0IL_0001:  call       instance void [mscorlib]System.Object::.ctor()IL_0006:  ret} // end of method Program::.ctor.method private hidebysig static void  Main(string[] args) cil managed{.entrypoint// 代码大小       19 (0x13).maxstack  8IL_0000:  nopIL_0001:  ldstr      "Hello World"IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)IL_000b:  nopIL_000c:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()IL_0011:  popIL_0012:  ret} // end of method Program::Main} // end of class ConsoleTest.Program

代码虽然简单,但也足够说明一些问题,下面让我们了解一下CIL代码:
1、以”.”一个点号开头的,例如上面这份代码中的.class、.method以及本例中未出现的.namespace,我们称之为CIL指令,用于描述.NET程序集总体结构的标记。为啥需要它呢?因为你总得告诉编译器你处理的是啥吧。
2、CIL代码中还出现了private、public,我们称之为CIL特性(attribute)。通过CIL指令并不能完全说明.NET成员和类,CIL特性的作用就是针对CIL指令进行补充说明成员或者类的特性。市面上常见的还有:extends、implements等等。
3、每一行CIL代码都使用了CIL操作码,例如:ldarg.0、ldstr、call、nop、ret等。
然后比较C#代码与对应的CIL 代码的不同之处:
1、C#代码Program类中没有构造方法,CIL代码中却有,说明编译器自动为类生成了无参构造方法。
2、为什么程序运行后总是执行Main()方法呢?因为Main()方法中设置了程序入口点(即.entrypoint),并不是因为它的名字是Main就得先执行……
3、经过对比发现:CIL代码比C#代码更接近程序的本质

基于堆栈

CIL是基于堆栈的,也就是说CIL 的VM(mono运行时)是一个栈式机。这就意味着数据是先推入堆栈,然后通过堆栈来操作的,而不是通过CPU寄存器来操作,这更加验证了其和具体CPU架构没有关系。
CIL之所以是基于堆栈而非CPU的一个原因是相比较于CPU的寄存器,操作堆栈实在太简单了,只需要简单的压栈和弹出,这对于虚拟机的实现来说再合适不过了。如果想要更具体地了解CIL基于堆栈这一点,各位可以去看一下堆栈这方面的内容,这里就不拓展了。

面向对象

就像C#一样,CIL同样是面向对象的。这就意味着在CIL中你可以创建对象,调用对象的方法,访问对象的成员。而这里需要注意的就是对方法的调用,调用静态方法和调用实例方法是不一样的。

  • 静态方法:ldarg.0没有被占用,所以参数从ldarg.0开始
  • 实例方法:ldarg.0被this占用,所以参数从ldarg.1开始

举例说明,假设类Guo中有一个静态方法和一个实例方法,代码如下:

namespace ConsoleTest
{public class Guo{public static int Subtract(int num1, int num2){return num1 - num2;}public void Show(string message){Console.WriteLine(message);}}
}

a. 静态方法Subtract的CIL代码如下:

.method public hidebysig static int32  Subtract(int32 num1,int32 num2) cil managed
{// 代码大小       9 (0x9).maxstack  2.locals init ([0] int32 CS$1$0000)//初始化局部变量。由于本方法的返回值为int型,所以声明了一个int32类型的局部变量,用以保存返回值。IL_0000:  nopIL_0001:  ldarg.0  //将索引为0的参数加载到计算堆栈上IL_0002:  ldarg.1  //将索引为1的参数加载到计算堆栈上IL_0003:  sub      //计算IL_0004:  stloc.0  //弹出当前计算堆栈顶弹部的值并将其存储到索引为0的局部变量中IL_0005:  br.s       IL_0007IL_0007:  ldloc.0  //将索引为0的局部变量加载到计算堆栈上IL_0008:  ret      //弹出当前计算堆栈顶弹部的值并返回
} // end of method Guo::Subtract

我们可以直接通过类名来调用这个静态方法:

Guo.Subtract(5,6);

对应的CIL代码为:

.method private hidebysig static void  Main(string[] args) cil managed
{.entrypoint// 代码大小       10 (0xa).maxstack  8IL_0000:  nopIL_0001:  ldc.i4.5IL_0002:  ldc.i4.6IL_0003:  call       int32 ConsoleTest.Guo::Subtract(int32,int32)IL_0008:  popIL_0009:  ret
} // end of method Program::Main

可见CIL直接call了类ConsoleTest.Guo的Subtract方法,不需要加载类ConsoleTest.Guo的实例。

b. 实例方法Show的CIL代码如下

.method public hidebysig instance void  Show(string message) cil managed
{// 代码大小       9 (0x9).maxstack  8IL_0000:  nopIL_0001:  ldarg.1  //将索引为1的参数加载到计算堆栈上,静态方法中第一个参数的索引是0IL_0002:  call       void [mscorlib]System.Console::WriteLine(string)IL_0007:  nopIL_0008:  ret
} // end of method Guo::Show

实例方法不能直接通过类名来调用,需要通过类的实例来调用:

Guo objGuo = new Guo();
objGuo.Show("Hello");

对应的CIL代码为:

.method private hidebysig static void  Main(string[] args) cil managed
{.entrypoint// 代码大小       20 (0x14).maxstack  2.locals init ([0] class ConsoleTest.Guo objGuo)//声明一个ConsoleTest.Guo类型的局部变量,用以保存类的对象IL_0000:  nopIL_0001:  newobj     instance void ConsoleTest.Guo::.ctor()IL_0006:  stloc.0IL_0007:  ldloc.0IL_0008:  ldstr      "Hello"IL_000d:  callvirt   instance void ConsoleTest.Guo::Show(string)IL_0012:  nopIL_0013:  ret
} // end of method Program::Main

CIL调用类ConsoleTest.Guo的Show方法时,需要先把类ConsoleTest.Guo的实例加载到计算堆栈(ldloc.0),然后再callvirt调用。由此也验证了:实例方法不能直接通过类名来调用,需要通过类的实例来调用。

CIL之——初识CIL相关推荐

  1. 由浅入深CIL系列:2.CIL的基本构成+CIL操作码速记表+CIL操作码大全速查

    一.CIL的基本构成  CIL由CIL指令(directive).CIL特性(attribute).CIL操作码(opcode)组成.           CIL指令 CIL指令是用于描述.NET程序 ...

  2. 由浅入深CIL系列【目录索引】+ PostSharp AOP编程【目录索引】

    CIL简介:CIL(Common Intermediate Language)中文名为通用中间语言,注意它曾经被称为微软中间语言或MSIL,它是一种类似于JAVA字节码的语言.在微软语言平台中,不管程 ...

  3. Unity3D为何能跨平台?聊聊CIL(MSIL)

    前言 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力感 ...

  4. 从游戏脚本语言说起,剖析Mono所搭建的脚本基础

    0x00 前言 在日常的工作中,我偶尔能遇到这样的问题:"为何游戏脚本在现在的游戏开发中变得不可或缺?".那么这周我就写篇文章从游戏脚本聊起,分析一下游戏脚本因何出现,而mono又 ...

  5. Understanding JVM Internals---不得不转载呀

    http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/ http://architects.dzone.com/art ...

  6. 魅力 .NET:从 Mono、.NET Core 说起

    转自:http://kb.cnblogs.com/page/514268/ 前段时间,被问了这样一个问题:.NET 应用程序是怎么运行的? 当时大概愣了好久,好像也没说出个所以然,得到的回复是:这是 ...

  7. Unity3d--跨平台(一)

    转自:https://www.cnblogs.com/murongxiaopifu/p/4211964.html 前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U ...

  8. 缓冲区溢出还是问题吗?C++/CLI安全编码

    C++/CLI是对C++的一个扩展,其对所有类型,包括标准C++类,都添加了对属性.事件.垃圾回收.及泛型的支持. Visual C++ 2005扩展了对使用C++/CLI(通用语言基础结构)开发运行 ...

  9. sprd camera 帧率设置_UnityPlayerSetting-Android 打包设置介绍

    Resolution And Presentation Start in fullscreen mode 以全屏模式启动 在启用的情况下,在第一次启动时隐藏导航栏(拦窗),如果未设置,则在第一次启动时 ...

最新文章

  1. spring WebServiceTemplate 调用 axis1.4 发布的webservice
  2. js、jquery相关的操作
  3. 《ArcGIS Runtime SDK for Android开发笔记》——(2)、Android Studio基本配置与使用
  4. centos安装g++
  5. 深入Python(2): __init__.py 用法
  6. python面向对象编程的三大特性_Python面向对象总结及类与正则表达式详解
  7. Django之model补充:一对多、跨表操作
  8. 那些年踩过的坑之:first-child伪类选择器
  9. Java中NLP的学习
  10. C#复习笔记(2)--C#1所搭建的核心基础
  11. 机器学习模型之集成算法
  12. web页面移动端键盘弹出后对页面布局的影响
  13. CUDA的旋转R ROI Align的OPENCL实现1(原理理解)
  14. 2022年草根互联网圈较流行的副业汇总
  15. 叶俊|从人类基因本能谈到赞美的力量|麻辣总裁幽默SHOW嗨翻全场
  16. 笔记本cmd重启计算机的代码,怎么让电脑不断重启(用cmd实现)
  17. Python常用开发软件有哪些?
  18. 阿里技术风险与效能部负责人张瓅玶:阿里集团深度用云实践
  19. Python中flask_sqlalchemy的使用
  20. 视频H.263与H.264的比较

热门文章

  1. 中国商用显示行业“十四五”前景规划及发展方向分析报告2022-2027年版
  2. PAT L3-011 直捣黄龙
  3. 电子商务网站的建设及发展趋势
  4. 亚马逊FBA卖家最赚钱的产品是什么?
  5. [洛谷]P1914小书童——凯撒密码
  6. css中 vertical-align 属性的应用和案例
  7. Android微信代码
  8. Vue9.2天气案例_监视属性
  9. 我胡汉三又回来了!也许是杨白劳吧。。。。。。
  10. 100部电影,100种人生,你看过几部?