一切从IL开始
IL是什么?
IL是Intermediate Language的缩写,是.Net代码转化成机器语言的一个中间语言,因此又把IL语言称之为反汇编语言。
IL工具有哪些?
俗话说,工欲善其事必先利其器。了解IL就要首先从使用工具开始。在.Net世界里有数个不同的IL工具,包含编译器和反编译器。最经典的编译和反编译利器就是.Net Framework自带的ILASM.exe和ILDASM.exe工具,同时还有其他,例如Reflector.exe,ILSay.exe等等。
具体IL指令介绍
要了解IL的指令,我们以一个非常简单的程序开始,源代码如下:
using System;
namespace HelloWorld
{
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
相信大家对这段代码再熟悉不过,对于编译后的可执行文件应用ILDasm.exe反编译工具,还原为文本MSIL编码,编译后的IL结构中,包含了MANIFEST和HelloWorld类,如下图所示:

其中MANIFEST是附加信息表,主要包含了程序集的一些属性,例如程序集名称、版本号、哈希算法、程序集模块等等,以及对外部引用程序集的引用项;下面我们重点根据Hello World类来介绍IL指令
首先是Hello World类型,IL代码如下:

>.class表明了HelloWorld是一个类,该类型继承自外部程序集mscorlib的System.Object类。
>public为访问控制权限,表示具有最高的访问权限,为访问成员没有限制。
>auto表示程序加载时内存的布局是有CLR决定的,而不是程序本身。
>.ansi属性则为了在没有被托管和被托管的代码之间实现无缝转换。没有被托管的代码,值的是没有运行在CLR运行库之上的代码,例如原来的C,C++代码等。
>.beforefieldinit属性为HelloWorld提供一个附加信息,用于标记运行库可以在任何时候执行类型构造函数方法,只要该方法在第一次访问其静态字段之前执行即可。如果没有beforefieldinit则运行库必须在某个精确时间执行构造函数方法,从而影响性能优化。
然后是.ctor方法,代码如下:

>.cil managed说明方法体中为IL代码,指示编译器编译为托管代码。
>.maxstack表明执行构造函数.ctor期间的评估堆栈可容纳数据项的最大个数。关于评估堆栈,其用于保存方法所需变量的值,并在方法执行结束时清空,或者存储一个返回值。
>.IL_0000,是一个标记码行开头,一般来说,IL_标记之前的部分为变量的声明和初始化。
>.ldarg.0(ldarg即load argument)表示装载第一个成员参数,在实例方法中值的是当前实例的引用,该引用将用于积累构造函数中调用。
>.call指令一般用于调用静态方法,因为静态方法是在编译期指定的,而在此处call并非调用静态方法,而是构造函数.ctor(),也是在编译期指定的;而另一个指令callvirt则表示调用实例方法,它的调用过程有异于call,函数的调用时在运行时确定的,首先会检查被调用函数是否为虚函数,如果不是就直接调用,如果是则向下检查子类是否有重现,如果有就调用重写实现,如果没有还调用原来的函数。
>.ret表示执行完毕,返回。
最后是Main方法,代码如下:

>.entrypoint指令表明了CLR加载程序HelloWorld.exe时,是首先从.entrypoint方法开始执行的,也就是表明Main方法将作为程序的入口函数。没有托管程序必须有且只有一个入口程序。这区别于将Main函数作为程序入口标志。
>.ldstr(即load string)指令表示将字符串压栈,“Hello World!”字符串将被移到stack顶部。CLR通过从元数据表中获取文字常量来构造string对象。
>.hidebysig属性用于表示如果当前类作为父类时,类中的方法不会被子类继承。因此HelloWorld子类中不会看到Main方法。
>.关于注释,IL代码中注释和C#等高级语言的注释相同。
参考:
《你必须知道的.Net》
一切从IL开始的更多相关文章
- IL异常处理
异常处理在程序中也算是比较重要的一部分了,IL异常处理在C#里面实现会用到一些新的方法 1.BeginExceptionBlock:异常块代码开始,相当于try,但是感觉又不太像 2.EndExcep ...
- CLR via C# 摘要二:IL速记
最简单的IL程序 .assembly test {} .method void Func() { .entrypoint ldstr "hello world" call void ...
- IL实现简单的IOC容器
既然了解了IL的接口和动态类之间的知识,何不使用进来项目实验一下呢?而第一反应就是想到了平时经常说的IOC容器,在园子里搜索了一下也有这类型的文章http://www.cnblogs.com/kkll ...
- IL接口和类的属性
上一篇文章学习了IL的入门,接下来我们再通过两个例子来了解下类的属性.构造函数以及接口的使用 一.类的属性.构造函数 1.先看下我们要构建的类的C#代码,然后再进行IL的实现,示例代码如下: [Ser ...
- IL初步了解
一.概述: 近来也是在看AOP方面的东西,了解到Emit可以实现.之前对Emit的了解也就是停留在Reflector针对方法反编译出来的部分指令.就用这次机会学习下Emit也用这篇随笔记录下学习的过程 ...
- 【转】fatal error C1900: “P1”(第“20081201”版)和“P2”(第“20080116”版)之间 Il 不匹配
转自:这里(然而这里并没有写原出处) 背景:今天傻逼逼地想用vs2010来编译一个vs2013的项目,其中这个项目用到了一个库(应该是用2013编译的) 在我浅薄的认知中,以为只是13支持的特性更多, ...
- VS2012 集成 IL DASM IL微软中间语言查看器
第一步: 找到IL DASM的安装位置,默认在C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools 第二步: ...
- 玩转动态编译 - 高级篇:一,IL访问静态属性和字段
IL介绍 通用中间语言(Common Intermediate Language,简称CIL,发音为"sill"或"kill")是一种属于通用语言架构和.NET ...
- 玩转动态编译 - 高级篇:二,IL设置静态属性,字段和类型转换
静态属性赋值 先来看 Reflector反射出的IL源码(感谢Moen的提示),这次用 Release模式编译,去掉那些无用的辅助指令 public void AAA(string s) { MyCl ...
- 30分钟?不需要,轻松读懂IL
先说说学IL有什么用,有人可能觉得这玩意平常写代码又用不上,学了有个卵用.到底有没有卵用呢,暂且也不说什么学了可以看看一些语法糖的实现,或对.net理解更深一点这些虚头巴脑的东西.最重要的理由就是一个 ...
随机推荐
- LightOJ1170 - Counting Perfect BST(卡特兰数)
题目大概就是求一个n个不同的数能构造出几种形态的二叉排序树. 和另一道经典题目n个结点二叉树不同形态的数量一个递推解法,其实这两个问题的解都是是卡特兰数. dp[n]表示用n个数的方案数 转移就枚举第 ...
- 坑爹的strcat
strcat是会改变原来的字符型数组的值的. #include<stdio.h> #include<stdlib.h> #include<string.h> voi ...
- BZOJ3463 : [COCI2012] Inspector
考虑将序列分成$\sqrt{n\log n}$块,每块维护下凸壳,修改时在相应块打上需要修改的标记. 查询时,对于两端零散部分暴力查询. 对于中间的块,如果有修改标记,则暴力重构. 然后在凸壳上查询时 ...
- POJ 3352 (边双连通分量)
题目链接: http://poj.org/problem?id=3352 题目大意:一个连通图中,至少添加多少条边,使得删除任意一条边之后,图还是连通的. 解题思路: 首先来看下边双连通分量的定义: ...
- 首发 手把手教你制作 Windows8 应用程序内部的 hubtile (动态瓷砖控件) MetroStyle(转)
http://blog.csdn.net/wangrenzhu2011/article/details/8175492 (转) 在metro 风格中 动态磁贴是他的精髓 在wp7 的开发中 我们可以使 ...
- PHP 如何读取一个1G的文件大小
需求如下: 现有一个1G左右的日志文件,大约有500多万行, 用php返回最后几行的内容. 1. 直接采用file函数来操作 or file_get_content() 肯定报内存溢出注: 由于 fi ...
- 利用java实现的一个发送手机短信的小例子
今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservi ...
- javascript中的function
function / 对象 所有的变量和方法名的:以字母,$ _开头其他随便,尽量使用英文字母命名,见名知意注意点:不允许使用关键字定义变量和方法的名称====函数即方法,方法即函数====百度:ja ...
- php 数组操作
<?php $vegetables[0] = "corn"; $vegetables[1] = "broccoli"; $vegetables[2] = ...
- 当PHP引擎试图实例化一个未知类的操作
在PHP开发过程中,如果希望从外部引入一个class,通常会使用include和require方法,去把定义这个class的文件包含进来,但是这样可能会使得在引用文件的新脚本中,存在大量的includ ...