通过MSIL了解CLR的运行原理

转载 2006年06月10日 11:07:00
通过MSIL了解CLR的运行原理

作者:
Wednesday, April 17 2002 2:12 PM

 

作为.NET最低层次的公共基础,微软中介语言(MSIL或IL)对一般开发者具有非常重要的意义。除了好奇心以外,仔细研究应用程序的IL能让你更为清楚地了解到公共语言运行时(CLR)执行高级C#或VB.NET代码的基本原理,从而有助于你发现和解决一些比较细微的问题。

在这篇文章里,我将引领读者了解IL,学习有关的一些关键指令,同时对CLR的操作机理做一点基础性解释。我不打算教你用IL编程,而是分析一些IL语法和语句使你对IL有更多了解。

ILDASM简介

微软的IL拆卸实用程序Ildasm.exe(通常位于/Program Files/Microsoft.Net/FrameworkSDK/Bin目录下)可以析构.NET assembly(装配)、根据你的要求从程序中抽取IL代码。对某一assembly调用该使用程序后,ILDASM会给出该assembly中所有类和名称空间的一个视图,如图A所示:

图A

ILDASM浏览assembly

当你进到某个类的成员或其方法,ILDASM就会为你显示该成员的IL代码。如果之前你曾经到过汇编器或J++字节码,那么IL可能在你来会觉得有点眼熟。在另一方面,如果你仅对抽象的高级程序语言有所了解,那么IL起来更像是胡言乱语。

好,现在你知道如何窥视assembly的IL代码了,但这些代码都意味着什么呢?在回答这个问题之前,首先让我们先来了解下CLR的有关知识。

虚拟CPU

对.NET程序来说,.NET CLR在功能上就如同一块虚拟的CPU,它执行IL代码、操作数据。CLR和真实的CPU类似之处在于它们都不直接操作内存中的变量而是使用程序变量的临时拷贝,CLR把这些程序变量存放在堆栈上。从内存拷贝某个变量到堆栈的行为称做装载(loading),而从堆栈拷回某个变量到内存的行为则被称做存储(storing)。

所以把两个数字相加的过程应该是这样的:

1.装载第1个数字并把它推入堆栈。

2.装载第2个数字并把它推入堆栈。

3.从堆栈中取出这两个数字并把它们相加。

4.把结果存储到内存。

什么是堆栈?

理解IL的关键是知道堆栈的工作原理。堆栈是一种抽象数据结构,其操作机理是后进先出。当你把新条目推进堆栈时,已经在堆栈内的任何条目都会压到堆栈的深处。同样的,把一个条目从堆栈移出则会让堆栈内的其他条目都向堆栈的顶部移动。只有堆栈最顶端的条目能从堆栈中取出,条目离开堆栈的顺序和它们被推进堆栈的顺序一样。你不妨回想下自动售货机的装货和取货过程就明白了。

重要的IL语句

既然你已经明白了CLR操作的基础知识,下面我们就接着讨论你面前的那些代码怎么?没有到什么代码?那么请你这里列出的IL代码

你首先见的是对当前方法的IL声明,其中包括方法的名字,返回类型、参数列表以及附着于该方法的其他修饰关键词(static/sharedpublicvirtual等等)。对象构造器则被赋给一个特殊的名字:.ctor。

IL中,方法参数按照它们在参数列表中的位置依次被引用。如果方法是静态或共享方法,那么参数0则是参数列表中的第1个参数。而对实例方法来说,参数0则是指向该方法所在类的实例的指针(Me或者this)。方法中的所有局部变量都在.locals标记的段落中以同样的方式声明。

在声明所有的局部变量以后,程序的实际正文才开始。每条IL指令,或opcode都可以根据你的喜好以一个IL_ 标记作为代码行开头。我们接下来再了解些更重要的IL指令。

变量用法

以LD开头的指令把变量从内存装载到堆栈供其操作。装载指令有若干条,每一条装载指令都操作特定类型的变量。以下就是其中的一些装载指令:

  • LDC把一个数字常数装入堆栈。这条指令有两个修饰词。第一个是类型标识符,第二个是实际的数值。
  • LDLOC把一个局部变量装入堆栈。另外还有一条LDLOCA指令把一个局部变量的地址(而非变量的内容)装入堆栈。变量由它们在.locals节的位置标识。这些指令装载位置4及以后位置使用不同的语法,但是索引号会出现在指令中。
  • LDARG装载成员的一个参数,而LDARGA指令则装载参数的地址。变量由它们在.locals节中的位置标识。这些指令装载位置4及以后位置使用不同的语法,但是索引号仍然出现在指令中。
  • LDELEM把数组元素装入堆栈而且通常先于表示这个索引的其他装载语句之前使用。
  • LDLEN把一个数组的长度装入堆栈。
  • LDFLD和LDSFLD把类域(成员变量)和静态类域装入堆栈。域由一个全名识别。

每一条装载指令都有对应的一条存储指令,后者以ST开头,负责把一个条目存入内存。例如,STLOC就负责把堆栈最顶端的条目存入一个局部变量。存储指令指定变量的句法规则通常和它们对应的装载指令类似。

比较操作

如果你不能比较两个值而且根据其比较结果做出决定,那么许多问题都无法用任何程序语言来解决。IL有一套比较操作符,它们都以C字母开头,比较堆栈中的值。通常,如果比较结果为真则会把1推入堆栈否则就推入0。

大多数这类指令都很容易由它们的名字区分出来。例如,CEQ比较两个值是否相等,而CGT则确定堆栈最顶端的值是否比第二个最顶端值更大。 CLT类同于CGT,不过执行的是小于比较操作。

Goto

通常,在对两个值进行比较之后会根据比较的结果结果实施一些操作。IL分支指令(以BR开头)根据堆栈最顶端的条目中的内容跳到其他指令。BRTRUE 和BRFALSE弹出堆栈最顶端的条目,然后根据该项为真(1)还是为假(0)而分别跳到指定的代码行。如果没有执行指令跳跃则继续执行下一条指令。另外还有一个无条件分支操作符BR,它总是跳到指定的代码行。

你会发现分支操作就好像源代码中的if语句以及显式执行的Goto操作。IL中的分支命令同样具有高级流程控制结构的对等体,比如:if, case, while, for等等。

创造新对象和调用其他代码

CALL和CALLVIRT指令调用其他方法和函数。CALL通常表示被调用的方法是静态的或共享的,而CALLVIRT则用于实例方法。就两种指令来说,方法的名字都会在指令中包括。被送到方法的任何参数都会被弹出堆栈而且要在方法被调用之前装载。

因为创建一个新对象需要调用构造器,所以IL的对象创建也类似于其他的方法调用。参数首先被装载到堆栈,然后执行NEWOBJ指令,它调用对象的构造器同时把对象的索引放回堆栈。指令中得有对象的名字。

以上就是大致的IL语法操作。除了满足你内心的求知欲望以外,我希望你能从我的阐述中得到足够的信息来理解IL代码的真实含义。

通过MSIL了解CLR的运行原理

作为.NET最低层次的公共基础,微软中介语言(MSIL或IL)对一般开发者具有非常重要的意义。除了好奇心以外,仔细研究应用程序的IL能让你更为清楚地了解到公共语言运行时(CLR)执行高级C#或VB.N...
  • zohong
  • zohong
  • 2008年04月03日 09:47
  • 613

转 通过MSIL了解CLR

作为.NET最低层次的公共基础,微软中介语言(MSIL或IL)对一般开发者具有非常重要的意义。除了好奇心以外,仔细研究应用程序的IL能让你更为清楚地了解到公共语言运行时(CLR)执行高级C#或代码的基...
  • tmoonlight
  • tmoonlight
  • 2009年02月26日 02:01
  • 643

C++,CLR,C#的DLL和EXE的32位程序,如何在64位系统上使用

要升级到64位系统,遇到的问题肯定很多,不过大部分应该还好解决。 如果CLR的程序,使用了C++的指针,那你可能编译要麻烦了。 属性——常规——公共语言运行库支持公共语言运行库支持(/clr)纯 MS...
  • forestcell
  • forestcell
  • 2008年10月09日 13:10
  • 1934

[翻译]MSIL 教程

在网上发现了一个非常好的MSIL教程,可惜是英文版的,于是就翻译了一下,与大家共享, 原文http://www.codeguru.com/Csharp/.NET/net_general/il/art...
  • mohan90118
  • mohan90118
  • 2015年08月18日 09:50
  • 350

CLR如何执行程序集的代码

CLR如何执行程序集的代码
  • sfw_123817
  • sfw_123817
  • 2016年11月10日 11:25
  • 167

CLR运行原理

clr是公共语言运行:在代码执行过程中,clr提供内存管理的垃圾回收,增强了安全性与受控代码的互操作性。1首先把源代码编译成Microsoft承认的中间语言(MSIL)2在中间语言编译成机器可以识别的...
  • hi2008111
  • hi2008111
  • 2009年03月13日 10:21
  • 126

什么是android运行原理

在了解android运行原理,我们必须先知道Java虚拟机的原理和内存分配机制。Java编译过的代码是一些class文件,通过Java VM的类解析器分析、效验后执行。 执行代码的时候,首先解析Cl...
  • songyan_love
  • songyan_love
  • 2017年05月10日 14:26
  • 747

.NET框架基本原理

1.1  将源代码编译为托管模块    在.NET框架里,正如前言里说的“编译器编译面向.NET框架的源代码产生CIL,只有到了运行时,CLR才将CIL翻译为CPU指令”。1、程序员先用任何支持CLR...
  • doong
  • doong
  • 2006年02月16日 16:40
  • 1623

深入理解操作系统原理之操作系统概述

一、概述 从计算机系统组成观点来看,操作系统就是一系列系统软件组成的。 软件:应用软件、系统软件(操作系统、语言处理系统和常用的例行服务程序)...
  • xiaokang123456kao
  • xiaokang123456kao
  • 2017年06月27日 16:55
  • 410

MSIL - the language of the CLR (Part 3)

IntroductionIn this the 3rd and final part of the MSIL series we will look at the various high level...
  • Anglewing_nwpu
  • Anglewing_nwpu
  • 2008年02月07日 10:31
  • 576
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过MSIL了解CLR的运行原理
举报原因:
原因补充:

(最多只允许输入30个字)