您的位置:知识库 »

[你必须知道的.NET] 第十三回:从Hello, world开始认识IL

作者: Anytao  来源: 博客园  发布时间: 2008-09-12 13:43  阅读: 4502 次  推荐: 0   原文链接   [收藏]  
[1] [你必须知道的.NET] 第十三回:从Hello, world开始认识IL
[2] [你必须知道的.NET] 第十三回:从Hello, world开始认识IL

系列文章导航:

[你必须知道的.NET] 开篇有益

[你必须知道的.NET] 第一回:恩怨情仇:is和as

[你必须知道的.NET] 第二回:对抽象编程:接口和抽象类

[你必须知道的.NET] 第三回:历史纠葛:特性和属性

[你必须知道的.NET] 第四回:后来居上:class和struct

[你必须知道的.NET] 第五回:深入浅出关键字---把new说透

[你必须知道的.NET] 第六回:深入浅出关键字---base和this

[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始

[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理

[你必须知道的.NET] 第九回:品味类型---值类型与引用类型(中)-规则无边

[你必须知道的.NET] 第十回:品味类型---值类型与引用类型(下)-应用征途

[你必须知道的.NET] 第十一回:参数之惑---传递的艺术(上)

[你必须知道的.NET] 第十二回:参数之惑---传递的艺术(下)

[你必须知道的.NET] 第十三回:从Hello, world开始认识IL

[你必须知道的.NET] 第十四回:认识IL代码---从开始到现在

[你必须知道的.NET] 第十五回:继承本质论

[你必须知道的.NET] 第十六回:深入浅出关键字---using全接触

[你必须知道的.NET] 第十七回:貌合神离:覆写和重载

[你必须知道的.NET] 第十八回:对象创建始末(上)

[你必须知道的.NET] 第十九回:对象创建始末(下)

[你必须知道的.NET]第二十回:学习方法论

[你必须知道的.NET]第二十一回:认识全面的null

[你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考

[你必须知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二


  3.2 HelloWorld类分析

 

  首先是HelloWorld类,代码为:

 

Code

  • .class表明了HelloWorld是一个public类,该类继承自外部程序集mscorlib的System.Object类。

 

  • public为访问控制权限,这点很容易理解。

  • auto表明程序加载时内存的布局是由CLR决定的,而不是程序本身

  • ansi属性则为了在没有被管理和被管理代码间实现无缝转换。没有被管理的代码,指的是没有运行在CLR运行库之上的代码,例如原来的C,C++代码等。

  • beforefieldinit属性为HelloWorld提供了一个附加信息,用于标记运行库可以在任何时候执行类型构造函数方法,只要该方法在第一次访问其静态字段之前执行即可。如果没有beforefieldinit则运行库必须在某个精确时间执行类型构造函数方法,从而影响性能优化,详细的情况可以参与MSDN相关内容。

  然后是.ctor方法,代码为:

Code

  • cil managed 说明方法体中为IL代码,指示编译器编译为托管代码。

 

  • .maxstack表明执行构造函数.ctor期间的评估堆栈(Evaluation Stack)可容纳数据项的最大个数。关于评估堆栈,其用于保存方法所需变量的值,并在方法执行结束时清空,或者存储一个返回值。

  • IL_0000,是一个标记代码行开头,一般来说,IL_之前的部分为变量的声明和初始化。

  • ldarg.0 表示装载第一个成员参数,在实例方法中指的是当前实例的引用,该引用将用于在基类构造函数中调用。

  • call指令一般用于调用静态方法,因为静态方法是在编译期指定的,而在此调用的是构造函数.ctor()也是在编译期指定的;而另一个指令callvirt则表示调用实例方法,它的调用过程有异于call,函数的调用是在运行时确定的,首先会检查被调用函数是否为虚函数,如果不是就直接调用,如果是则向下检查子类是否有重写,如果有就调用重写实现,如果没有还调用原来的函数,依次类推直到找到最新的重写实现。

  • ret表示执行完毕,返回。

  最后是Main方法,代码为:

Code

  • .entrypoint指令表明了CLR加载程序HelloWorld.exe时,是首先从.entrypoint方法开始执行的,也就是表明Main方法将作为程序的入口函数。每个托管程序必须有并且只有一个入口点。这区别于将Main函数作为程序入口标志。

 

  • ldstr指令表示将字符串压栈,"Hello, world."字符串将被移到stack顶部。CLR通过从元数据表中获得文字常量来构造string对象,值得注意的是,在此构造string对象并未出现在《第五回:深入浅出关键字---把new说透》中提到的newobj指令,对于这一点的解释我们将在下一回中做简要分析。

  • hidebysig属性用于表示如果当前类作为父类时,类中的方法不会被子类继承,因此HelloWorld子类中不会看到Main方法。
  接下来的一点补充:

  • 关于注释,IL代码中的注释和C#等高级语言的注释相同,其实编译器在编译IL代码时已经将所有的注释去掉,所以任何对程序的注释在IL代码中是看不见的。

  3.3 回归简洁

  去粗取精,我们的IL代码可以简化,下面的代码是基于上面的分析,并去处不重要的信息,以更简洁的方式来展现的HelloWorld版IL代码,详细的分析就以注释来展开吧。

 

  4. 结论

  结束本文,我们从一个点的角度和IL来了一次接触,除了了解几个重要的指令含义,更重要的是已经走进了IL的世界。通过一站式的扫描HelloWorld的IL编码,我们还不足以从全局来了解IL,不过第一次的亲密接触至少让我们太陌生,而且随着系列文章的深入我们将逐渐建立起这种认知,从而提高我们掌握了解.NET底层的有效工具。本系列也将在后续的文章中,逐渐建立起这种使用工具的方法,敬请关注。

                              ©2007 Anytao.com

[第1页][第2页]
0
0

热门文章

    最新文章

      最新新闻

        热门新闻