一、前言

IL是什么?

Intermediate Language (IL)微软中间语言

C#代码编译过程?

C#源代码通过LC转为IL代码,IL主要包含一些元数据和中间语言指令;

JIT编译器把IL代码转为机器识别的机器代码。如下图

语言编译器:无论是VB code还是C# code都会被Language Compiler转换为MSIL

MSIL的作用:MSIL包含一些元数据和中间语言指令

JIT编译器的作用:根据系统环境将MSIL中间语言指令转换为机器码

为什么ASP.NET网站第一次运行时会较慢,而后面的执行速度则会相对快很多?

当你第一次运行.NET开发的站点时,CLR会将MSIL通过JIT进行编译,最终转换为执行速度非常快的Native Code。这可以解释。

为什么要了解IL代码?

如果想学好.NET,IL是必须的基础,IL代码是.NET运行的基础,当我们对运行结果有异议的时候,可以通过IL代码透过表面看本质;

IL也是更好理解、认识CLR的基础;

大量的实例分析是以IL为基础的,所以了解IL,是读懂他人代码的必备基础,同时自己也可以获得潜移默化的提高;

二、如何把ILDasm导入到VS中

想要看IL代码需要使用ILDasm工具,工具一般在电脑的

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\ildasm.exe

也可以下载ILSpy:http://ilspy.net/

把ILDasm导入到VS工具中,使用方便,具体如下:工具 - > 外部工具

  

导入之后,vs工具里面就有ILDasm工具了。以后想看IL代码方便多了。

IL代码通过ILDasm反编译后(左图),ILDasm图标意义(右图)

  

三、分析IL代码

在分析IL代码之前,要先理解几个概念:

图片来源:https://msdn.microsoft.com/zh-tw/library/dd229210.aspx

Managed Heap(托管堆):这就是NET中的托管堆,用来存放引用类型,它是由GC(垃圾回收器自动进行回收)管理;

Call Stack(调用堆栈):调用堆栈:调用堆栈是一个方法列表,按调用顺序保存所有在运行期被调用的方法。

Evaluation Stack(计算堆栈):每个线程都有自己的线程栈,IL 里面的任何计算,都发生在 Evaluation Stack 上,其实就是一个 Stack 结构。可以 Push,也可以 Pop。

可以对照IL指令:指令列表,一步一步来分析IL代码

1、用C#写一个简单控制台应用程序

using System;

namespace ILDemo
{
class Program
{
static void Main(string[] args)
{
int i = ;
int j = ;
int k = ;
int answer = i + j + k;
Console.WriteLine("i+j+k=" + answer);
Console.ReadKey();
}
}
}

2、 用ILDasm打开bin下的.exe文件查看代码,具体IL代码如下:

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// 代码大小 42 (0x2a)
.maxstack
.locals init ([] int32 i,
[] int32 j,
[] int32 k,
[] int32 answer)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: ldc.i4.2
IL_0004: stloc.1
IL_0005: ldc.i4.3
IL_0006: stloc.2
IL_0007: ldloc.0
IL_0008: ldloc.1
IL_0009: add
IL_000a: ldloc.2
IL_000b: add
IL_000c: stloc.3
IL_000d: ldstr "i+j+k="
IL_0012: ldloc.3
IL_0013: box [mscorlib]System.Int32
IL_0018: call string [mscorlib]System.String::Concat(object,
object)
IL_001d: call void [mscorlib]System.Console::WriteLine(string)
IL_0022: nop
IL_0023: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0028: pop
IL_0029: ret
} // end of method Program::Main

3、会用到的IL指令:

nop:无操作

ret:从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。

call:调用由传递的方法说明符指示的方法。

box:将值类转换为对象引用,就是装箱,同理可以知道拆箱unbox

ldc.i4.X:把int32的值推送到计算堆栈

stloc.X:把计算堆栈顶部的值放到调用堆栈索引为X处

ldloc.X:把调用堆栈X处的值复制到计算堆栈

4、理解注释后的代码

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint //程序入口
// 代码大小 42 (0x2a)
.maxstack // 计算出计算堆栈的能存几个值 .locals init ([] int32 i,
[] int32 j,
[] int32 k,
[] int32 answer) //定义int32类型的i,j,k,answer IL_0000: nop //无操作 IL_0001: ldc.i4.1 //把i的值放到计算堆栈上
IL_0002: stloc.0 //把计算堆栈顶部的值(i的值)放到调用堆栈索引0处
IL_0003: ldc.i4.2 //把j的值放到计算堆栈上
IL_0004: stloc.1 //把计算堆栈顶部的值(j的值)放到调用堆栈索引1处
IL_0005: ldc.i4.3 //把k的值放到计算堆栈上
IL_0006: stloc.2 //把计算堆栈顶部的值(k的值)放到调用堆栈索引2处 IL_0007: ldloc.0 //把调用堆栈索引为0处的值复制到计算堆栈
IL_0008: ldloc.1 //把调用堆栈索引为1处的值复制到计算堆栈
IL_0009: add //相加
IL_000a: ldloc.2 //把调用堆栈索引为2处的值复制到计算堆栈
IL_000b: add //相加
IL_000c: stloc.3 //把计算堆栈顶部的值(add的值)放到调用堆栈索引3处
IL_000d: ldstr "i+j+k=" //推送对元数据中存储的字符串的新对象引用。
IL_0012: ldloc.3 //把调用堆栈索引为3处的值复制到计算堆栈 IL_0013: box [mscorlib]System.Int32 //装箱
IL_0018: call string [mscorlib]System.String::Concat(object,object) //调用内部方法
IL_001d: call void [mscorlib]System.Console::WriteLine(string) //调用WriteLine
IL_0022: nop //无操作
IL_0023: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() //调用ConsoleKey
IL_0028: pop //无操作
IL_0029: ret //return
} // end of method Program::Main

四、最后

IL是跟我高级架构经理的分享和博客园相关的博客学习总结的,最后留2个题目,也是我的高级架构经理分享中提到的两个好玩的问题,也能看出对IL的掌握的程度

答案后续公布。

最新文章

  1. linux进程管理(上)
  2. SSH整合报错:No result defined for action and result input
  3. CLR线程池
  4. thinkphp框架3.2的cookie删除问题记录
  5. 利用NTFS交换数据流隐藏文件
  6. Hibernate 检索查询的几种方式(HQL,QBC,本地SQL,集成Spring等)
  7. Unity的物理引擎是如何实现碰撞的呢?
  8. Repeater 控件 当数据源没有数据的时候显示 暂无数据 的两种方式
  9. JSP实现数据库(MySQL)查询——Java Web练习(二)
  10. Mysql 索引的基础(上)
  11. Gray Code 解答
  12. Entity Framework+SQLite+DataBaseFirst
  13. windows2012服务器中安装php7+mysql5.7+apache2.4环境
  14. 理解Golang哈希表Map的元素
  15. HDU3031 To Be Or Not To Be 左偏树 可并堆
  16. 教你下载BarTender 2016
  17. actionBar_Tab导航
  18. mysql导出csv文件excel打开后数字用科学计数法显示且低位变0的解决方法
  19. *2_3_5_加入reference model
  20. SQL查询语句执行的逻辑顺序

热门文章

  1. ms sql server 在abator生成的 insert 无法获取插入 id 的原因
  2. saltstack通过salt.client执行命令(转)
  3. 超链接的那些事(三): 属性target
  4. 烂泥:ubuntu安装KVM虚拟机管理virt-manager
  5. Python Backup Files
  6. linux进程间通信-XSI IPC
  7. Python HeapSort
  8. 我的vim配置文件.vimrc
  9. 数据结构Java实现06----中缀表达式转换为后缀表达式
  10. Android中static和final用法小结