C#中CLR(公共语言运行时)与IL(中间代码)

.net平台中的CLR

首先要说明的是,.NET平台与C#不是一回事 它是C#,VB.net等程序运行的平台。

CLR是公共语言运行时,是 .NET Framework的重要组成部分。它提供了内存管理、线程管理和异常处理等服务,而且还负责对代码实施严格的类型安全检查,保证了代码的正确性。

事实上,类型安全(Type Checker)、垃圾回收(Garbage Collector)、异常处理(Exception Manager)、向下兼容(COM Marshaler)等很多C#中的特性都是由CLR来提供的。

什么是IL

.NET Framework是架构在Windows平台上的一个虚拟的运行平台,你可以想象将最下层Windows换做其他的操作系统,例如说Linux,一样可以实现使用符合CLS(Common Language Specification,通用语言规范)的.NET语言,这其实就是Mono计划要实现的功能。因而,理论上,C#是一种可以跨平台的语言。

C#另一个比较象Java的地方是,它也是一种(特殊意义上的)语言,同Java一样,C#编写的程序代码也是先通过C#编译器编译为一种特殊的字节代码, (Microsoft Intermediate Language,MSIL,微软)中间语言,运行时再经由特定的编译器(JIT编译器,Just In tIME, JITer)编译为机器代码,以供操作系统执行。(关于JIT的介绍。可以看这篇博客,请点这里

IL是一门中间语言 ,.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的文字表述方式转化为IL。各种不同的文字形式最终被统一到了IL的表述方式

CLR加载了IL之后,当每个方法第一次被执行时,就会使用JIT将IL代码进行编译为机器码,机器码和汇编其实也是一一对应的,可以这样理解:汇编是机器码的文字表现形式,提供了一些方便人们记忆的“助记符”。

对于同样的IL,JIT会把它为不同的CPU架构(如x86/IA64等等)生成不同的机器码。

C#代码及其对应的IL中间代码

?

//hidebysig指令表示如果当前类为父类,用该指令标记的方法将不会被子类继承
//cil managed表明方法体中的代码是IL代码,且是托管代码,即运行在CLR运行库上的代码
.method private hidebysig static void Main(string[] args)cil managed
{
    .entrypoint //该指令代表该函数程序的入口函数。每一个托管应用程序都有且只有一个入口函数,CLR加载程序时,首先从.entrypoint函数开始执行。
    .maxstack 2 //执行构造函数时,评估堆栈可容纳数据项的最大个数。评估堆栈是保存方法中所需要变量的值的一个内存区域,该区域在方法执行结束时会被清空,或者存储一个返回值。
    .locals init (
        [0] int32 num,
        [1] int32 num2,
        [2] int32 num3) //表示定义int类型的变量,变量名分别为num,num2,num3。存储在调用栈。
    L_0000: nop  //No operation的意思,即没有任何操作。
    L_0001: ldc.i4.1  //将“1”压入评估栈,此时“1”处于评估栈的栈顶。
    L_0002: stloc.0  //此指令表示把值从评估栈中弹出,并赋值给调用栈的第0个变量num。
    L_0003: ldc.i4.2
    L_0004: stloc.1
    L_0005: ldc.i4.3
    L_0006: stloc.2 //从.locals init到L_0006,相当于C#代码的为i,j,k赋值。
    L_0007: ldloc.0  //取调用栈中位置为0的元素压入评估栈(取i的值)。
    L_0008: ldloc.1  //取调用栈中位置为1的元素压入评估栈(取j的值)。
    L_0009: add  //做加法操作
    L_000a: ldloc.2 //取调用栈中位置为2的元素压入评估栈(取k的值)。
    L_000b: add  //做加法操作
    L_000c: call void [mscorlib]System.Console::WriteLine(int32) //调用输出方法
    L_0011: nop  //No Operation
    L_0012: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() //调用ReadKey方法
    L_0017: pop //把评估栈的内容清空
    L_0018: ret  //return 标记返回值
} //Main方法结束

通过上面的代码,我们可以总结一下: .maxstack:代码中变量需要在调用栈(Call Stack)中占用几个位置; .locals int(……):定义变量初始化并放入调用栈中(Call Stack); nop:No Operation,没有任何操作; ldstr:Load String,把字符串压入评估栈(Evaluation Stack)中; ldc.i4.1:把数值2以4字节长度整数的形式压入评估栈; stloc:把评估栈(Evaluation)中的值弹出赋值到调用栈中(Call Stack); ldloc:把调用栈(Call Stack)中指定位置的值取出(Copy)压入评估栈(Evaluation Stack)中; call:调用指定的方法,这个指令一般用于调用静态方法;而callvir则一般用于调用实例方法; ret:return ,标记返回。

下面再看一个例子


 namespace TestConsole
{
    class Program
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void SomeMethod()
        {
            Console.WriteLine("Hello World!");
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Before JITed.");
            Console.ReadLine();

            SomeMethod();

            Console.WriteLine("After JITed");
            Console.ReadLine();
        }
    }
}

与之相对应的main方法IL代码:

.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 8
    // 分配字符串"Before JITed"
    L_0000: ldstr "Before JITed."
    // 调用Console.WriteLine方法
    L_0005: call void [mscorlib]System.Console::WriteLine(string)
    // 调用Console.ReadLine方法
    L_000a: call string [mscorlib]System.Console::ReadLine()
    L_000f: pop
    // 调用Program.SomeMethod方法
    L_0010: call void TestConsole.Program::SomeMethod()
    // 分配字符串"After JITed"
    L_0015: ldstr "After JITed"
    // 调用Console.WriteLine方法
    L_001a: call void [mscorlib]System.Console::WriteLine(string)
    // 调用Console.ReadLine方法
    L_001f: call string [mscorlib]System.Console::ReadLine()
    L_0024: pop
    L_0025: ret
}
?
时间: 2024-10-18 08:11:41

C#中CLR(公共语言运行时)与IL(中间代码)的相关文章

解决异常:公共语言运行时检测到无效的程序

我碰到这个问题比较奇怪,在开发OrayTalk的组织结构功能时,其中的一个方法(基于.NET 2.0)在win7.win2003下运行没有问题,在winxp下运行就抛异常:“公共语言运行时检测到无效的程序”,对应英文为:common language runtime detected an invalid program. 抛异常的方法代码摘抄如下: private Control control = ...; public void ActionOnUI<T1>(bool showMessa

CLR 公共语言运行库

1..支持多语言..只是语言是面向CLR的..均可以在此基础上运行. 2..程序集加载..程序打包之后的Dll文件由CLR(公共语言运行库)来编译并加载到可以执行状态..由CLR(公共语言运行库)加载出来的程序是被监视的状态的..会跟踪程序执行的每一个节点..监视报错..监视每一个变量等等..这样的监视会损耗 10% 的性能..但是这的确是物有所值的..因为只有处于监视的状态下..CLR(公共语言运行库)才能做到以下的几点.. 3..内存分配..本来该由程序员来照顾到..并去处理的内存占用大小等

对公共语言运行时的学习笔记

图文讲解.NET CLR是什么 - 51CTO.COMhttp://developer.51cto.com/art/200910/158022.htm 通用语言运行时(CommonLanguageRuntiome,CLR)最早被称为下一代Windows服务运行时(NGWS Runtime).它是直接建立在操作系统上的一个虚拟环境,主要的任务是管理代码的运行.CLR现在支持几十种现代的编程语言为它编写代码,然后以一种中间语言(Intermediate Langeoage,IL)代码的形成被执行.并

java中检测-在运行时指定对象是否是特定类的一个实例---关键字 instanceof

java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. if(request instanceof HttpServletRequest){ System.out.println("-------------"); } 原文地址:https://www.cnblogs.com/czlovezmt/p/9728353.html

【Python】读取命令行参数、在PyDev中设置Python运行时的参数

有时候,我们写的命令行程序需要批次执行,这里可以让Python程序读取命令行参数,再编写一个命令行批次执行脚本.bat,实际上就是一个充满命令的.改了后缀名的文本文件,在多个测试用例扔进Python程序中是非常有用的. 例如,如下图,有一个cmdArgs.py程序,当在python cmdArgs.py 后面带上-h -i,程序则输出-h与-i参数,后面所带内容: 如果输入其它参数,比如这里多出来的-u参数,程序是自动报错的. 这个cmdArgs.py的代码如下,十分简单: #-*-coding

安装Visual Studio2015后,使用VS2013开发的项目,在IIS访问都提示“公共语言运行时检测到无效的程序”的解决办法

1.安装VS2015后,.NET Framework4.6会替换掉 C:\Windows\Microsoft.NET\Framework64\v4.0.30319 (如果使用的是windows7 64位版本)的文件,导致VS2013开发的项目在IIS中浏览都会出现如下错误: 2.折腾了很久,翻阅大量的搜索资料也无法解决,最后在IIS中设置应用池的“启用32位应用程序” 为true后,再打开站点,一切恢复正常了 留个几号,以备查阅!

(二十九)unity4.6学习Ugui中文文档-------运行时创建Scroll-lists

?? 孙广东 2015.5.10 首先要滚动和list形式存储内容.  使用Scroll Rect组件.就可以滚动了,但是有时候我们不希望,item超过区域还显示:就要使用Mask组件,说明一下,Mask组件组好配合Image一起使用. 下面的图:显示了的情况[头像是子对象Image].1.父对象只有Mask组件:2.有Mask和Image组件[图片为none]:3.有Mask和Image组件[图片有Alpha透明区域]     在list容器中的item 我们怎么管理呢?VerticalLay

微软公共语言运行时的小细节

1. 实际上,当我们使用字符串拼接时,是String调用了他的静态方法Concat,Concat接受object参数也就是说如果本来就是引用类型就可以直接传进去了,千万不要转为值类型.比如 Int a =0; Object b =a; Console.WriteLine(a+","+(int)b); 这样多进行了一次拆箱和装箱操作,会降低效率. 正确的代码应该是: Console.WriteLine(a.ToString()+","+b); 这样不会引起任何装箱,拆

深入探索.NET内部了解CLR如何创建运行时对象

前言 SystemDomain, SharedDomain, and DefaultDomain. 对象布局和内存细节. 方法表布局. 方法分派(Method dispatching). 因为公共语言运行时(CLR)即将成为在Windows上创建应用程序的主角级基础架构, 多掌握点关于CLR的深度认识会帮助你构建高效的, 工业级健壮的应用程序. 在这篇文章中, 我们会浏览,调查CLR的内在本质, 包括对象实例布局, 方法表的布局, 方法分派, 基于接口的分派, 和各种各样的数据结构. 我们会使用