前几天群里有位水友提问:”C#中,当一个要领所传入的参数是一个静态字段的时候,措施是直接到静态字段拿数据还是从复制的函数栈中拿数据“。其实很明显,这和要领参数的通报方法有关,如果是引用通报的话,必定是会去静态字段直接拿值的;如果要领是以传值的方法使用参数的话,必然是从复制的栈中拿值的。
但是这位水友就是不相信这个结论(后来发明,这货整一个杠精啊!天天在群里跟人抬杠~),这个时候我忽然想到了可以反向看一下C#的IL代码,来了解一下措施运行的过程。简直,当我们对运行功效有贰言的时候,可以通过IL代码透过外貌看素质。
二、IL简介在我们分析检察IL之前首先要了解下什么是IL?IL的全称是Intermediate Language (IL)即将.NET代码转化为机器语言的一其中间语言的缩写。在必然水平上,我们可以将其理解为伪汇编语言。我们在使用.NET框架中的C#、VB.NET、F#等语言的时候,编译过程并不是像C/C++一样直接编译出原生代码,而是编译成IL中间语言。通过IL中间语言这种方法,可以实现跨平台、提高措施灵活性等多种长处。
下面我们以C#语言为例,大抵了解了解一下我们的源代码是如何编译成IL语言,继而运行在电脑上面的。
图1:.NET语言编译过程示意图
上图为C#语言的编译运行过程示意图。首先编译器将我们编写好的源代码编译成IL中间语言,这些IL中间语言的主要内容是一些元数据和中间语言指令。然后再由我们的JIT编译器加载这些IL中间语言,JIT编译器会按照系统环境将IL中间语言指令转换为机器码,继而运行在差此外方针平台上,实现跨平台成果。(JIT编译器将IL中间语言即时编译成原生语言的过程和解释性语言的读取一条执行一条又有些差别,JIT会对编译功效进行缓存以便下次调取的时候直接使用)这也是为什么有些ASP.NET网站第一次运行时会较慢,而后面的执行速度则会相对快很多的一个原因。
再总结一下上面所说的编译过程:
首先,编译器要编历源代码,通过大量的计算生成IL中间代码,这些代码并不能直接地被CPU使用,还需要第二步操纵;
接下来,运行时将这些IL代码通过JIT编译器进一步编译成原生的CPU指令。
在上文中我们提到了一个JIT编译器,它的全名叫即时编译器。顾名思义,它是在运行时环境中产生的编译行为。读到这里,相信很多伴侣可能城市像马三一样孕育产生疑问了。对比传统的直接将源代码编译成原生代码,C#将源代码编译成了中间语言不会降低效率嘛?本来直接一步到位的过程,此刻偏要拆成两个部分。这不只要花费更多的时间、占用更多的内存,还有可能降低性能,那用JIT编译器的好处到底有什么呢?
其实,使用JIT编译器的好处多多。如果我们不用JIT即时编译将编译后的措施放在运行时中的话,那就只能生成在在某一种CPU平台上运行的原生代码,如果措施要运行在多种方针平台上的话,就要编译多种方针平台的原生代码,这样C#也就掉去了跨平台能力。其次,JIT即时编译生成原生代码产生在运行时阶段,因此即时编译器会对生成的原生代码进行性能优化。颠末优化的原生代码要比不优化的代码性能好。
在我们的Unity游戏开发中就存在着AOT编译和JIT编译两种编译方法,以后我们会单独开篇博客来详细探讨一下这两种编译方法的异同,这里就不再赘述了。
三、如何使用ILDasm工具检察IL代码上面说了一大堆观点和理论,相信大家早已经技痒,别急,下面,马三就和大家一起使用ILDasm工具反编译并检察IL代码。ILDasm工具一般在我们安置Visual Studio的时候就已经默认安置好了,检察IL代码凡是只需下面的几步操纵:
1.首先,需要打开ILDasm工具,点击电脑桌面的开始,然后在措施中找到对应版本的Visual Studio的目录,接着在里面找到VS开发人员命令提示,英文版的名称是:Developer Command Prompt 。点击打开它,然后在命令行里面输入ILDasm并回车,就会打开ILDasm工具了。
图2:VS开发人员命令提示示意图
2.然后,在ILDasm工具的界面,点击文件-->打开,然后选择我们预先编译出来的.exe文件,ILDasm工具就会自动的帮我们分析出IL代码及其代码组织布局,如下图所示: