上海公司聚餐好去处:1.5.2 CIL的作用

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 10:36:48
《C#与.NET3.5高级程序设计》第1章.NET之道,本章的目的在于为本书其余部分建立起一个概念性的框架,由.NET之前各种技术的局限性和复杂性开始,然后综述了.NET和C#是如何试图简化这种状况的。本节为大家介绍CIL的作用。
AD:
1.5.2  CIL的作用
现在我们来深入地探讨CIL(公共中间语言)代码、类型元数据和程序集清单。CIL是一种和平台无关的语言。不管使用何种支持.NET的语言,相关编译器都生成CIL指令。例如,下列的C#代码构成一个简单的计算器。现在不必在意具体的语法,只要注意Calc类中的Add()方法的格式:
// Calc.cs
using System;
namespace CalculatorExample
{
// 这个类包含应用程序的入口点。
class Program
{
static void Main()
{
Calc c = new Calc();
int ans = c.Add(10, 84);
Console.WriteLine("10 + 84 is {0}.", ans);
// 等待用户按回车键来结束程序。
Console.ReadLine();
}
}
// C#计算器。
class Calc
{
public int Add(int x, int y)
{ return x + y; }
}
}
C#编译器(csc.exe)编译这段代码后,就会得到一个单文件*.exe程序集,其中包含一个程序集清单、CIL指令和描述Calc与Program类的各方面信息的元数据。
说明 第2章讲述了使用C#编译器编译代码的细节和图形IDE的使用,如Visual Studio、Visual C# Express和SharpDevelop。
例如,如果用ildasm.exe(本章稍后会说明)打开该程序集,会发现Add()方法被CIL表示为:
.method public hidebysig instance int32 Add(int32 x,
int32 y) cil managed
{
// 代码长度        9(0x9)
.maxstack 2
.locals init (int32 V_0)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: add
IL_0004: stloc.0
IL_0005: br.s  IL_0007
IL_0007: ldloc.0
IL_0008: ret
} // Calc::Add方法结束
如果看不懂这段CIL代码,也不必担心,第19章会讲述CIL编程语言的基础。需要注意一点,C#编译器生成的是CIL,并不是平台相关的指令。
这一点适用于所有支持.NET的编译器。为了便于说明,我们假设用VB.NET创建一个和上面C#相同的程序:
' Calc.vb
Imports SystemNamespace CalculatorExample
' VB.NET"模块"是一个只包含静态成员的类。
Module Program
Sub Main()
Dim c As New Calc
Dim ans As Integer = c.Add(10, 84)
Console.WriteLine("10 + 84 is {0}.", ans)
Console.ReadLine()
End Sub
End Module Class Calc
Public Function Add(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
End Class
End Namespace
如果查看Add()方法的CIL指令,你会觉得它与VB.NET编译器vbc.exe生成的代码非常相似(只有很少的差别):
.method public instance int32  Add(int32 x,
int32 y) cil managed
{
// 代码长度    8(0x8)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add.ovf
IL_0003: stloc.0
IL_0004: br.s   IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // Calc::Add方法结束
源代码 Calc.cs和Calc.vb代码文件位于Chapter 1子目录下。
1. CIL的好处
到此,你可能很想弄清楚,不直接把源代码编译为特定的指令集而是编译为CIL的好处到底在哪里。有一点好处就是语言的集成性。如前面讲过的,每种支持.NET的编译器生成的是几乎完全相同的CIL指令。因此,所有语言都能很好地在定义明确的二进制文件间相互交互。
此外,CIL是平台无关的,.NET Framework本身也是平台无关的。Java程序员早已体会到了这一点好处(例如,一个代码库就可以在多种操作系统上运行)。实际上,已经存在C#语言的国际标准和大量的.NET平台和实现的子集,它们可以供许多非Windows的操作系统使用(本章1.13节会详细说明)。与Java相比不同的是,.NET还允许用户使用自己选择的语言构建应用程序。
2. 将CIL编译成特定平台的指令
由于程序集包含的是CIL指令而不是某一特定平台的指令,CIL代码必须在使用之前进行即时编译。将CIL代码编译成有意义的CPU指令的工具称为即时(JIT)编译器,有时也昵称为Jitter。.NET运行库环境将使用针对各种不同CPU的JIT编译器,每个编译器都会针对底层平台进行优化。
比如,在手持设备(如Pocket PC)上部署一个.NET应用程序,就可以配备相应的JIT以在低内存环境下运行。如果为后台服务器部署程序集(通常内存不是问题),那么JIT又能进行优化,使代码在高内存环境下运行。这样,开发人员只需编写一套代码,就能在不同体系结构的设备上通过JIT编译器高效地编译和执行。
另外,当给定的JIT编译器将CIL指令编译为相应的机器代码时,它会用适合目标操作系统的方式将结果缓存在内存中。这样,如果PrintDocument()方法被调用,则它对应的CIL指令将在第一次调用中被编译成特定平台的指令并被保留在内存中以备以后使用。因此,在下一次调用PrintDocument()时,就不需要编译CIL了。
说明 同样可以使用.NET Framework 3.5 SDK附带的ngen.exe命令行工具在安装程序时执行"预JIT"。这样做可以改善图形密集的应用程序的启动时间。