您好,欢迎访问三七文档
MicrosoftIntermediateLanguage(msil)第1頁,共29頁MicrosoftIntermediateLanguage(MSIL)一、HelloWord!Microsoft.NETFramework和C#ProgrammingLanguage自诞生日起,就一直快速进化着。越来越庞大的类库,越来越多的封装,还有那越来越简单的语法糖,所有这些让我们离本质越来越远。尽管用这些优雅的语法并不妨碍我们开发出好而实用的产品,但作为一个资深的程序员,我们还是应该了解编译器背后的秘密。C#并不代表.NETCLR的全部,就好比学习LINQ,如果我们不试图去分析背后的执行流程,就很难理解所谓延迟执行机制。MSIL是一把锋利的手术刀,只有它能剖开层层伪装,带我们深入到.NET的底层世界,去了解和结识许许多多被刻意隐藏起来的精灵。尽管它不是真正意义上的底层汇编语言,不能分析JITComplier编译后的NativeCode,但总算能一窥托管编译器的奥秘。学习MSIL的目的,并不是真的要用它去编码,而是为了更好地交流。暂时离开那无比强大的VisualStudio.NET,让我们用记事本开始MSIL的探索之旅。MyApp.il.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.namespaceMyApp{.classpublicProgramextends[mscorlib]System.Object{.methodstaticprivatevoidMain(string[]args){.entrypointldstrHello,World!callvoid[mscorlib]System.Console::WriteLine(string)nopcallstring[mscorlib]System.Console::ReadLine()popret}}}打开VisualStudioCommandPrompt,使用ILASM开始编译。E:\Develop\MSILilasmMyApp.ilMicrosoft(R).NETFrameworkILAssembler.Version2.0.50727.1378Copyright(c)MicrosoftCorporation.Allrightsreserved.Assembling'MyApp.il'toEXE--'MyApp.exe'SourcefileisUTF-8MicrosoftIntermediateLanguage(msil)第2頁,共29頁AssembledmethodMyApp.Program::MainCreatingPEfileEmittingclasses:Class1:MyApp.ProgramEmittingfieldsandmethods:GlobalClass1Methods:1;Emittingeventsandproperties:GlobalClass1WritingPEfileOperationcompletedsuccessfully执行MyApp.exe,就可看到熟悉的Hello,World!也就意味着我们完成了第一个.NET汇编程序。二、CodeStructure先了解一下MSIL程序代码最简单的结构组成,以便于我们开始后面的细节研究。还是以上节的Hello,World!为例。1、Header.assemblyexternmscorlib{auto}定义一个程序集引用信息。mscorlib.dll包含了.NET的基本类型定义,几乎所有的托管引用程序都会用到它。当然我们还可以写得更具体一点。例如:.assemblyexternmscorlib{.ver2:0:0:0.publickeytoken=(B77A5C561934E089)}.assemblyMyApp{}定义程序集。当然还可以包含更完整的版本信息。.assemblyLearn.CUI{.ver1:0:0:0.custominstancevoid[mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string)={string('MyApp')}.custominstancevoid[mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string)={string('')}MicrosoftIntermediateLanguage(msil)第3頁,共29頁}.moduleMyApp.exe定义托管模块。KingNa注:这个就相当于C#中的Using或VB中的Imports了,只是IL还要指定程序集名称以及Module名,但我在实验中发现,Module可以不予指定,也就是说除了Module不是必须的以外,其它两个都是必须要指定的。2、Code.namespaceMyApp定义命名空间。.classpublicProgramextends[mscorlib]System.Object定义一个继承自System.Object的类,注意语法。我们还可以为其添加更多的关键词,比如:.classpublicautoansiextends[mscorlib]System.Object.methodstaticprivatevoidMain(string[]args)定义一个私有静态方法。这个方法是程序的入口点,在C#中我们必须将其命名为Main,但CLR并没有这个要求,真正起作用的是.entrypoint。所以我们可以将其改成任何有效名称。.methodstaticprivatevoidTest(string[]args)(不要着急研究关键词和指令的具体意义~~~~~)三、Module在C#中,除非我们用Reflection,否则我们不能直接操作Module。但在实际开发中,我们可以利用Module做些不错的应用。(1)为Module添加静态构造,这样第一次调用任何该托管模块成员之前会自动执行一段代码,完成诸如自动初始化或者授权检查等任务。(2)定义不依附于任何Class的全局字段或方法(不建议在实际工程中使用)。我们在第一节中的HelloWord的结尾加入如下代码:.methodprivatehidebysigspecialnamertspecialnamestaticvoid.cctor(){ldstrModule.cctor...callvoid[mscorlib]System.Console::WriteLine(string)ret}编译该代码,执行后输出。Module.cctor...Hello,World!GlobalItems我们可以在Module中定义全局的静态字段和方法。看下面的演示。MicrosoftIntermediateLanguage(msil)第4頁,共29頁(1)定义全局静态字段x。(2)在Module.cctor中初始化x为1234。(3)定义全局静态方法Test()用来显示x。(4)在Program.Main()中使用call指令进行调用Test()。.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.namespaceMyApp{.classpublicProgramextends[mscorlib]System.Object{.methodstaticprivatevoidMain(string[]args){.entrypointcallvoidTest()nopcallstring[mscorlib]System.Console::ReadLine()popret}}}.fieldassemblystaticint32x.methodprivatehidebysigspecialnamertspecialnamestaticvoid.cctor(){ldc.i41234stsfldint32xret}.methodpublicstaticvoidTest(){ldsfldint32xcallvoid[mscorlib]System.Console::WriteLine(int32)ret}四、NamespaceMSIL的Namespace定义要远比C#灵活得多,让我们看看MyApp.CMS.Program的不MicrosoftIntermediateLanguage(msil)第5頁,共29頁同写法。(1).namespaceMyApp.CMS{}.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.namespaceMyApp.CMS{.classpublicProgramextends[mscorlib]System.Object{.methodstaticprivatevoidMain(string[]args){.entrypointret}}}(2).namespaceMyApp{.namespaceCMS{}}.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.namespaceMyApp{.namespaceCMS{.classpublicProgramextends[mscorlib]System.Object{.methodstaticprivatevoidMain(string[]args){.entrypointRet}}}}这种嵌套方式更便于组织代码。.namespaceMyApp{.classA...{}.namespaceCMS{.classB...{}}MicrosoftIntermediateLanguage(msil)第6頁,共29頁}(3).classpublicMyApp.CMS.Program...{}.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.classpublicMyApp.CMS.Programextends[mscorlib]System.Object{.methodstaticprivatevoidMain(string[]args){.entrypointRet}}此方式直接将namespace作为ClassFullName的一部分。但在MSIL编码时,输入类型的完整名称,长长的FullName(namespace+classname)让人感觉太繁琐……此时可以考虑用.typedef定义别名减少输入。.assemblyexternmscorlib{auto}.assemblyMyApp{}.moduleMyApp.exe.typedef[mscorlib]System.ObjectasObject.typedefmethodvoid[mscorlib]System.Console::WriteLine(string)asPrint.namespaceMyApp{//.classpublicProgramextends[mscorlib]System.Object.classpublicProgramextendsObject{.methodstaticprivatevoidMain(string[]args){.entrypointldstrHello,World!//callvoid[mscorlib]System.Console::WriteLine(string)callPrintret}}}我们还可以直接在.typedef中使用已定义的别名。.typedef[mscorlib]System.ConsoleasC
本文标题:MSIL
链接地址:https://www.777doc.com/doc-5858386 .html