C#从编译到运行
IL(字节码)和汇编两种截然不同的东西,IL之后还有个JIT,JIT之后才得到的是我们传统上的汇编(机器码),JIT生成机器码,而汇编是机器码进行简单替换后,方便给人看的结果。汇编语言与机器指令是一一对应的(这里的汇编是指汇编“指令”,由机器码简单一一替换成助记符给人看)。
C# 源代码到机器码过程:
源代码——2、编译器(vs自带的csc.exe,还有mono的mcs.exe,【java编译器javac.exe】)——3、IL中间语言字节码——4、CLR启动JIT即时编译——5、将IL编译为可以真正在CPU上运行的机器码。
编译时【工具:编译器】:步骤1 到 步骤3,编译源代码
运行时【工具:CLR】:步骤3到步骤5。编译IL
运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).
Java 源代码到机器码过程:
java源代码 - - - 编译器 - - - jvm可执行的字节码 - - - jvm中的解释器 - - - 机器可执行的二进制机器码 - - - 程序运行
机器码
机器码:机器码就是cpu能够直接读取并运行的代码,用二进制编码表示,也叫做机器指令码。
字节码
java的字节码(即.class文件):字节码是一种中间状态的二进制代码,是由源码编译过来的,可读性没有源码高。而且cpu也不能够直接读取字节码,在java中,字节码需要经过JVM虚拟机转译成机器码之后,cpu才能够读取并运行。
字节码(英语:Bytecode)将虚拟机可以读懂的代码称之为字节码。将源码编译成虚拟机读的懂的代码,需要虚拟机转译后才能成为机器代码的中间代码 叫做字节码。
字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机。编译器将源码编译成字节码,特定平台上的虚拟机将字节码转译为可以直接执行的指令。字节码的典型应用为在.net中也叫做IL中间语言。
作用:解决穿透解释性语言的低效问题。
IL本身是以二进制格式存储的,所以我们不可能阅读。但是和其它二进制代码有汇编语言一样,IL也有一种汇编语言叫作IL汇编语言(ILAsm),IL汇编语言和其它汇编语言一样有许多指令。例如,两个数相加,有相加的指令,两个数相减,有相减的指令,等等。很显然.NET的运行时中的编译器(JIT)不能直接执行IL汇编语言,如果你用IL汇编语言编写了一些代码,那么首先你要把这些代码编译成IL代码,然后JIT才可以运行这些代码。
注意:请注意IL和IL汇编语言是两个不同的概念,当我们说到IL时,是指.NET编译器产生的二进制代码,而IL汇编语言不是二进制格式的。
参考:https://www.cnblogs.com/xiaoxiangfeizi/archive/2011/08/08/2130768.html
中间语言IL
中间语言【IL】有时也称为公共中间语言(CIL:Common Intermediate Language) 或 Microsoft中间语言(MSIL),也可叫做字节码。
之所以叫公共的,可以理解为 就是可以被不同平台【操作系统】上识别,所以才可移植。
IL我们是看不懂的,因为他是二进制的,
我们说的学习并分析IL并不是IL,而是由IL这种汇编语言【相当于.Net平台的汇编语言,类似于Windows平台的汇编语言】编写的代码,我们可以看懂,JIT不能直接运行我们使用IL汇编语言写的代码,JIT运行的是IL汇编语言编译成的IL代码【二进制字节码】,编译器不是编译源码的csc.exe,也不是编译IL为机器码的JIT即时编译器而是,ilasm.exe即IL汇编程序,对应的还有ildasm.exe IL反汇编程序
参考理解:
IL是微软.NET平台上衍生出来的一门中间语言,.NET平台上的各种高级语言(如C#,VB,F#)的编译器会将各自的文字表述方式转化为IL。各种不同的文字形式最终被统一到了IL的表述方式,其中包含了.NET平台上的各种元素,如“范型”,“类”、、“接口”、“模块”、“属性”等等。值得注意的是,各种高级语言本身可能根本没有这些“概念”在里头,如IronScheme是一个在.NET平台上的Scheme语言实现,其中根本没有前面提到的这些IL——亦或说是.NET平台上的名词。IL本身并不知道自己是由哪种高级语言转化而来的,哪种语言中有哪些特性,IL也根本不会关心。
谁来关心这些呢?自然是各语言的编译器了。这就是.NET平台上的高级语言的第一次转化:高级语言 => IL。
而我们平时说的“汇编”则要简单得多,这个简单并不代表“容易掌握,方便使用”,这个“简单”是指它的“定义”。汇编是让CPU直接使用的“语言”,请注意“直接”二字:一条汇编指令便是让CPU作一件事情(如寄存器的复制,从内存中读取数据等等),毫无二义。不同族CPU拥有不同的指令集,但是它们都有一样的特征:指令的数量相对较少,每个指令功能都简单之至。这也是为什么现在几乎没有人直接使用汇编写程序的原因,试想一下给您红、绿、蓝三原色,让您绘制一幅色彩绚丽的图画有多么困难。
由于CPU只认识汇编代码,因此就算是IL也需要再次进行转化,才能被CPU执行。这次转化便由“JIT Compiler”完成。CLR加载了IL之后,当每个方法——请注意这是IL中的概念——第一次被执行时,就会使用JIT将IL代码进行编译为机器码——对了,刚才我忘了提,机器码和汇编其实也是一一对应的,您可以这样理解:汇编是机器码的文字表现形式,提供了一些方便人们记忆的“助记符”。与IL不同的是,CLR,JIT都是真正了解CPU的,对于同样的IL,JIT会把它为不同的CPU架构(如x86/IA64等等)生成不同的机器码。这也是Java/.NET中“Compile Once,Run Everywhere”这一口号的技术基础:它们为不同的CPU架构提供了不同的“IL转化器”,仅此而已。与高级语言到IL的转化类似,CPU也完全不知道自己在执行的指令是从哪里来的,可能是JIT从IL转化而来,可能是JVM从Java Bytecode转化而来,也有可能是C语言编译得来,也有可能是由MIT/GNU Scheme解释而来。
这就是.NET平台上的高级语言在机器上运行的第二次转化:IL => 汇编(机器码)。
原文: http://blog.zhaojie.me/2009/06/my-view-of-il-1-il-and-asm.html#comment_jpwt8_3T00Y0000A
补充: https://www.cnblogs.com/eaglet/archive/2009/06/02/1494290.html
评论:
il是中间代码,介于语言(c#/vb.net等)和机器语言之间,c#代码被编译成这种中间代码,到时再转化为机器语言就非常快了,所以才叫il为类似机器语言,是基于性能提升而产生的语言,好像msdn中对il的作用已经介绍得很清楚了
汇编代码和机器码是一一对应的,一个MOV就对应着一串唯一的0101001(当然不是这个了),汇编就是助记符,如果你用0101001编写代码不要死人了?
其实汇编器就是起一个直接转换的作用,所以可以认为汇编代码和机器码是等价的
tips:
bin是放最终代码的目录
obj就放中间代码的目录
《clr via C#解释》
一、PE文件基本介绍
PE文件是Windows操作系统下使用的一种可执行文件,由COFF(UNIX平台下的通用对象文件格式)格式文件发展而来。32位成为PE32,64位称为PE+或PE32+。
二、PE文件格式
- PE文件种类如下表所示:
种类 | 主扩展名 |
---|---|
可执行系列 | EXE, SCR |
库系列 | DLL, OCX, CPL, DRV |
驱动程序系列 | SYS, VXD |
对象文件系列 | OBJ |
参考 https://www.cnblogs.com/cdaniu/p/15854142.html
http://blog.zhaojie.me/2009/06/my-view-of-il-1-il-and-asm.html