C# 编译过程分析及IL等概念梳理

编译过程分析 及 IL等概念梳理

 

首先,我们看下从编辑源代码到可被计算机执行的机器码总的过程

C# 源代码到机器码过程:

1、源代码——2、编译器(vs自带的csc.exe,还有mono的mcs.exe,【java编译器javac.exe】)——3、IL中间语言字节码——4、CLR启动JIT即时编译——5、将IL编译为可以真正在CPU上运行的机器码。

 

编译时【工具:编译器】:步骤1 到 步骤3,编译源代码

运行时【工具:CLR】:步骤3到步骤5。编译IL

 

所谓运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).

 

 ▲即时编译JIT

所谓JIT(Just In Time),是指.Net的JIT编译器并不一下把整个应用程序编译完毕(如果这样的话,应用程序将会有一个很长的启动时间),而是只编译将要执行的那一小段。Jdk1.5出现之后,Java也采用了JIT编译方式

 

例如:

  • 只有修改方法中的内容才不需要重启,因为服务器对于方法的调用是动态【jit即时编译】的,调用方法的时候,方法的内容才会被加载。
  • 新增成员变量,方法,或修改静态方法和静态变量、创建新的类 这些都是需要重启的,因为启动服务器,项目加载完后,这些内容都已经加载到类加载器中了,修改之后在类加载器中这些内容还是原来的,只有重启才能重新加载进去

 中间语言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反汇编程序

ilasm.exe 和 ildasm.exe

ilasm.exe即IL汇编程序

可利用中间语言 (IL) 生成可移植可执行 (PE) 文件。 

ildasm.exe即IL反汇编程序

可利用包含中间语言 (IL) 代码的可移植可执行 (PE) 文件,并创建适合输入到 Ilasm.exe 的文本文件。

PE文件

PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)

 托管代码

托管代码(C#源代码,VB源代码,F#等,C/C++是非托管)

为什么叫托管呢?

是因为可被编译器编译为中间语言,是受管于CLI式的内存管理和线程安全管理的。

那为什么CLR可以管理呢?

是由CLR启动的JIT编译IL为机器码,这样,CLR就 能确切的知道代码的作用,并可以有效的管理代码。

 

 

 

 非托管代码

非托管代码,直接编译成目标计算机码,在公共语言运行库环境的外部,由操作系统直接执行的代码,代码必须自己提供垃圾回收,类型检查,安全支持等服务。如需要内存管理等服务,必须显示调用操作系统的接口,通常调用Windows SDK所提供的API来实现内存管理。

托管代码和非托管代码的区别:

  1、托管代码是一种中间语言,运行在CLR上;非托管代码被编译为机器码,运行在机器上。

  2、托管代码独立于平台和语言,能更好的实现不同语言平台之间的兼容;非托管代码依赖于平台和语言。

  3、托管代码可享受CLR提供的服务(如安全检测、垃圾回收等),不需要自己完成这些操作;非托管代码需要自己提供安全检测、垃圾回收等操作。

字节码和机器码

字节码(Byte-code)是一种包含执行程序,由一序列 op 代码/数据对组成的二进制文件,是一种中间码。字节码文件是一种和任何具体机器环境及操作系统环境无关的中间代码,所以可以移植不同平台执行。

 

例如:java的虚拟机编译的java字节码,以.class结尾的文件。IL,相当于java的字节码,也是一种中间语言。

 

 

机器码

计算机直接使用的程序语言,其语句就是机器指令码,机器指令码是用于指挥计算机应做的操作和操作数地址的一组二进制数。 机器码就是诸如0101010100......的二进制数

1,机器码本质就是一个二进制数位:"0"和“1”。

2,8位单片机如十六制数0x55,机器码:01010101。

3,16位单片机如十六制数0xaaaa,机器码:1010 1010 1010 1010。

4,32位ARM如十六制数0x5555aaaa,机器码:

01010101010101010101010101010101

————————————————

二进制格式【字节码】文件:DB 0F 49 40

机器码】:1010等二进制数。

 

 

 

 CLI

  每种变成语言都有一组内置的类型,用来表示如整数、浮点数和字符等之类的对象。过去,这些类型的特征因变成语言和平台的不同而不同。例如,组成整数的位数对于不同的语言和平台就有很大差别。

  然而,这种同一性的缺乏使我们难以让使用不同语言编写的程序及库一起良好协作。为了有序协作,必须有一组标准。

  CLI(Common Language Infrastructure,公共语言基础结构)就是这样一组标准,它把所有.NET框架的组件连结成一个内聚的、一致的系统。它展示了系统的概念和架构,并详细说明了所有软件都必须坚持的规则和约定。CLI的组成如图1-7所示:

 

 

 

  ▲.NET组成

 

 

 

 

 

 

 

参考链接:https://www.cnblogs.com/xiaoxiangfeizi/archive/2011/08/08/2130768.html

 

posted @ 2020-05-16 14:36  好Wu赖  阅读(1498)  评论(0编辑  收藏  举报