MSIL 初级读本 第一部分:Hello World


   
声明:    本文译自 Kenny Kerr  的 blog,共有8篇。如果大家有更好的 MSIL 入门文章也欢迎推荐,谢谢。


作者废话ing:
    在描述 C++/CLI 或是拿它和 C# 作比较的时候,我经常自然而然地想去讨论 Visual C++ 和 Visual C# 编译器生成的 MSIL ( Microsoft intermediate language ) 代码。但问题是很多程序员并不怎么熟悉 MSIL,而 ILDASM 之类的程序对这些新手并没有太大帮助——虽然它显示的代码正确得要命,但是其可读性却令人不敢恭维。为此我决定发一些介绍 MSIL 的初级文章。因为我想读者不大可能真的需要使用 MSIL 来写代码,所以我会跳过一些乏味的细节而更关注于某些特定的主题,比如定义某个类型、撰写某个方法、调用指令以及异常处理等等。如果你觉得本文对你还算有所帮助,请不吝声明:)

进入正题:
    让我们从一个简单的 main 函数开始,它负责显示一条非常“个性独具”的信息——“Hello World!”。和 C# 不同, CLI 并不要求一个方法必须属于某个类;入口点函数也不一定要命名为 main。不过直观起见,本文中我们还是要使用这个名字。

   
.method static void main()
{
     .entrypoint
     .maxstack 1
     ldstr "Hello world!"
     call void [mscorlib]System.Console::WriteLine(string)
     ret
}


    上面的 main 方法被称为一个方法的定义,因为方法的签名和方法体是在一起呈现的。相反,单独提供一个方法的签名被称为方法声明。方法的声明通常被用作指明调用目标(在调用方法时提供),而方法的定义则真正给出了方法的实现部分。一个方法的定义开始于 .method 指示符,方法可以定义于全局作用域或是某个类当中。程序入口点方法必须是静态的,即调用方法时不需要指明某个对象实例,静态方法由 static 关键字来指明。将全局方法声明为静态的似乎有些多余,但是在某些情况下如果忽略了 static 关键字,ILASM 编译器将会报错。“void main()” 是方法的签名部分,如你所想,它代表方法没有返回值并且不接收任何参数。
    .entrypoint 指示符 通知运行时该方法是应用程序的入口点。应用程序中仅有一个方法可以具有该指示符。
    .maxstack 指示符 指出该方法需要一个多大的栈。例如,要将两个数值相加需要将两数压栈,然后调用 add 指令,该指令将两数弹栈并将其相加的结果压栈。在这个例子中栈的大小应当是2。
    ldstr 指令将字符串压栈。call 指令从 mscorlib 程序集中调用System.Console 类的静态方法 WriteLine。这是一个使用方法声明的例子,代码中提供了 WriteLine 方法的完整签名 ( 包括指定了一个 string 类型的形参 ) 使得运行时能够确定应该调用该方法的哪一个重载版本。
最后,通过 ret 指令返回到本方法的调用者,在本例中,这将结束应用程序的运行。
posted on 2005-02-04 22:39  勇者之心  阅读(1047)  评论(6编辑  收藏  举报