什么样解读IL代码

 如何解读IL代码

   
 关于IL代码,我出以起三个点去揭开她神秘的面罩。IL代码是呀?我们怎么而失去读懂IL代码?我们什么错过念懂IL代码?这三单问题的解答,将是本人解读IL代码的共同体思路。

     IL代码是什么?IL(Intermediate
Language),它吧称CIL或者MSIL,翻译成中文即是“中间语言”。C#的JIT编译器可以用C#源程序编译为.exe或.dll文件,但此时编译出来的程序代码并无是CPU能一直实施的第二上前制代码,而是传说着的IL代码。因此,.exe或者.dll文件都好为VS安装自带的ILDASM打开,查看IL代码。

   
我们怎么要错过读懂IL代码?无论精通哪一样宗技术,我们还当打该本质出发,探明最基本之周转机理,最终有效地解和控制它。对于C#言语来说,掌握IL语言就如同抓住了C#言语的本色,它好有效地赞助我们错过了解编译器的运行机理。对于有些C#一把手而言,深入地研究IL语言后,能对IL语言直接开展改动后编译。但纵然自我时底水准,读懂IL代码是为更深刻地理解C#各种风味,比如C#遇最好重点之组成部分核心特色,委托、事件。

 
 我们又用如何错过读懂IL代码?在宣读懂IL代码之前,我必优先给大家介绍一下,C#代码编译环境下的内存结构。就自我时早就知晓分为5格外块内存区。分别吗,托管堆,线程堆栈,计算栈,调用栈,代码区。

   托管堆(Managed
Heap):存放引用类型的数码,引用类型的数码由GC(Garbage
Collection)负责管理。

   线程堆栈(Thread Heap
Stack):存放值类型的多寡及援类型地址,值类型的数据由操作系统直接负责管理。

   计算栈(Evaluation
Stack):临时存放值类型的数目及援类型的地址的堆栈。符合先进后出(FILO)基本栈规则。

   调用栈(Call Stack):其中的Record
Frame用于存放.locals init(int32
V_0)指令的参数值,是一个部分变量表,不吻合先进后出(FILO)基本栈规则。

 
 代码区(Code):存放各种程序指令集。

   
数据外存区有4单,按等级可以分开成3只级别。托管区为无限尖端,只有存放引用类型数据;线程堆栈为第二层,存放值类型数据与援类型地址;计算栈和调用栈为第三层,在线程中调用方法时,主要以及时半个栈中操作数据。要拘留懂IL代码第一步就是是需要鲜明地询问计算栈与调用栈互相操作数据的干。下面我将引入一个IL代码实例来证明几单内存区是怎么相互操作数据的。

    C#源代码

using System;

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

IL代码

.method private hidebysig static void
Main(string[] args) cil managed
{
.entrypoint //程序入口
// 代码大小 42 (0x2a)
.maxstack 2 //
计算起计算堆栈的能存几只价

.locals init ([0] int32 i,
[1] int32 j,
[2] int32 k,
[3] 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

     
总结:1.ldloc.0面前缀ld,load含义载入,即压入计算栈;loc,locals含义调用栈,即取值于调用栈第0员参数。

             
2.其他的ld前缀都是取值于线程堆栈。比如ldc.i4.0,ldstr,ldfld,ldfld。

             
3.st前缀,store含义存储,即弹来计算栈。弹出的价存放于调用栈。

         
基于上述3漫漫结论,大家基本得以看懂大部分IL代码的道中计算栈和调用栈的数码交互。在随后的博文被,我会讲述一下争通过IL代码去深入了解委托、事件。希望大家能支持一下。