一 前言

  IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致。个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 。感谢 @冰麟轻武 的指点

你没有看第一篇?  点这里看第一篇 读懂IL代码就这么简单(一)

IL指令大全 :IL指令详解

IL反编译工具: ILDasm

知识点回顾:

Managed Heap(托管堆):用于存放引用类型的值

Evaluation Statck(计算栈):临时存放值类型数据,引用类型地址的堆栈(这个是栈,所以遵循栈的操作特点,先进后出)

Call Stack(调用栈):其中的Record Frame 用于存放.locals init(int32 V_0)指令的参数值如:V_0 (Record Frame是一个局部变量表,所以不遵守FILO原则 )

二 指令详解(基本介绍)

2.1 知识点介绍

  在第一篇时,我只详细的写了值类型的IL指令,这一篇会主要以引用类型为主,这一篇会有装箱操作,所以先写一下装箱操作在内存中是如何操作的

装箱操作:1 内存分配,在托管堆中分配内存空间,2 将值类型的字段拷贝到新分配的内存中,3 将托管堆中的对象地址返回给新的对象

操作过程如下图

C#代码 

          /*
Author:zery-zhang
BlogAddress:http://www.cnblogs.com/zery/
*/
static void Main(string[] args)
{
string name = "Zery";
int age = 22;
Console.WriteLine(age.ToString() + name);//已ToString的操作
Console.WriteLine(age+name);//未ToString操作 }

IL代码

     /*
Author:zery-zhang
BlogAddress:http://www.cnblogs.com/zery/
*/
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 48 (0x30) //以下代码 完成 C#代码中初始化变量的操作 //计算栈(Evaluation Stack) 可容纳数据项的最大个数
.maxstack 2
//定义并初始化参数 并存入 局部变量表(Record Frame)中
.locals init (string V_0,int32 V_1)
IL_0000: nop
//把字符串压入计算栈(Evaluation Stack)中
IL_0001: ldstr "Zery"
// 从计算栈中弹出("Zery")字符,并赋值给局部变量表中第0个位置的元素V_0
IL_0006: stloc.0
//把整数22压入计算栈中
IL_0007: ldc.i4.s 22
//把整数22弹出,并赋值给局部变量表中第1个位置的元素V_1
IL_0009: stloc.1 //以下代码完成C#中的输出操作 //取出局部变量表中V_1元素的值 "22" (copy)并压入计算栈中
IL_000a: ldloca.s V_1
//弹出刚刚压入的值("22")调用ToString方法转成string类型并将引用存入计算栈中
IL_000c: call instance string [mscorlib]System.Int32::ToString()
//取出局部变量表中第0个位置元素(V_0)的值("Zery")压入计算栈中(此时计算栈中有两个值,指向推管堆中"22"的引用地址和字符串"Zery")
IL_0011: ldloc.0
//弹出计算栈中两个值调用String的Concat方法把字个字符拼接存入托管堆中(Managed Heap )并返回地址压入计算栈中
IL_0012: call string [mscorlib]System.String::Concat(string,string)
//调用输出方法,调用输出方法后计算栈中的值(指向托管堆字符的地址)会被回收 。
IL_0017: call void [mscorlib]System.Console::WriteLine(string) //未ToString的操作
IL_001c: nop
//取局部变量表中第1个位置的元素V_1的值("22") 压入计算栈中
IL_001d: ldloc.1
//把刚刚压入的整数22 装箱并返回指向托管堆的地址存入计算栈中
IL_001e: box [mscorlib]System.Int32
//取局部变量表中第0个位置的f元素V_0的值("Zery")并压入计算栈中
IL_0023: ldloc.0
//弹出计算栈中两个值调用String的Concat方法把字个字符拼接存入托管堆中(Managed Heap )并返回地址压入计算栈中
IL_0024: call string [mscorlib]System.String::Concat(object,object)
//调用输出方法
IL_0029: call void [mscorlib]System.Console::WriteLine(string)
IL_002e: nop
//标记返回
IL_002f: ret
} // end of method Program::Main

2.2 IL指令详解

  .maxstack:计算栈(Evaluation Stack)可容纳数据项的最大个数

  .locals init (int32 V_0,int32  V_1,int32 V_2):定义变量并存入Call Stack中的Record Frame中

  nop:即No Operation 没有任何操作,我们也不用管它,

  ldstr.:即Load String 把字符串加压入Evaluation Stack中 

  stloc.:把Evaluation Stack中的值弹出赋值到Call Stack中的Record Frame中

  ldloc.:把Call Stack里的Record Frame中指定位置的值取出(copy)存入 Evaluation Stack中   以上两条指令为相互的操作stloc赋值,ldloc取值

  call:  调用指定的方法

  box:执行装箱操作

  ret: 即return  标记返回

三 指令详解(深入介绍)

如果看代码中的注释你还不是很理解,那就看看下面的图解过程吧,如果每一步都画图,那工程太大了,所以我会把简单的的步组合成一张图并做上注释

先画初始化的代码详解图  注:为了减少图片所以栈的弹出与压入操作就省去了,都只画出了结果

IL_0001: ldstr "Zery"
IL_0006: stloc.0
IL_0007: ldc.i4.s 22
IL_0009: stloc.1

因为字符串是引用类型,所以是保存在托管堆中,而栈中只保存对字符引用的地址,可以看到图中的字符串是在托管中的,而计算栈中只保存了引用

IL_000a: ldloca.s V_1
IL_000c: call instance string [mscorlib]System.Int32::ToString()
IL_0011: ldloc.0
IL_0012: call string [mscorlib]System.String::Concat(string,string)
IL_0017: call void [mscorlib]System.Console::WriteLine(string)

IL_001d: ldloc.1
IL_001e: box [mscorlib]System.Int32
IL_0023: ldloc.0
IL_0024: call string [mscorlib]System.String::Concat(object,
object)
IL_0029: call void [mscorlib]System.Console::WriteLine(string)

装箱的过程图在上面已给出此处只把结果画出

四 总结

  1 用两篇把 值类型与引用类型在内存中不同的位置与不同的操作详细的写了,我觉得还是很有必要的,因为所有的数据类型由这两种类型组成,把这两种类型的操作了解了

看其它IL指令就是透过本质看现象了。

2  关于画图,我觉得画图是程序员必学的知识,牛X的程序员画出来的,系统架构图,系统设计图等都是很有结构很清晰的。我的画图技能还有太多不足,只是画这种简单的图都觉得,无法完美的表达自己头脑所想的那样。

【转自】http://www.cnblogs.com/zery/p/3376973.html

【转载】读懂IL代码就这么简单(二)的更多相关文章

  1. 读懂IL代码就这么简单(二)

    一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...

  2. 【转载】读懂IL代码就这么简单(三)完结篇

    一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认为 ...

  3. 读懂IL代码就这么简单(三)完结篇

    一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍 这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认 ...

  4. 读懂IL代码就这么简单 ---- IL系列文章

    读懂IL代码就这么简单 (一) 读懂IL代码就这么简单(二) 读懂IL代码就这么简单(三)完结篇 出处:http://www.cnblogs.com/zery/tag/IL%20%E7%B3%BB%E ...

  5. 【转载】读懂IL代码就这么简单 (一)

    一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道你的代码是如何运行相互调用的,此言一出不明觉 ...

  6. 读懂IL代码就这么简单 (一)

    一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道你的代码是如何运行相互调用的,此言一出不明觉 ...

  7. 读懂IL代码就这么简单

    原文地址:http://www.cnblogs.com/zery/p/3366175.html 一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不 ...

  8. 读懂IL代码(一)

    以前刚开始学C#的时候,总有高手跟我说,去了解一下IL代码吧,看懂了你能更加清楚的知道你写出来的代码是如何运行互相调用的,可是那时候没去看,后来补的,其实感觉也不晚.刚开始看IL代码的时候,感觉非常吃 ...

  9. 读懂IL代码(四)

    这一篇是IL系列的最后一篇的,主要是要说一下IL中的流程控制.我相信,经过前面三篇的介绍,看IL代码应该不是什么大问题了吧.好吧,闲话不多说了,就来简单的说一下吧. 还是跟前几篇一样,以例子来解释说明 ...

随机推荐

  1. 安装mongodb卡顿

    "3.6下载安装会卡死."的原因在于,默认安装是包含mongodb compass,这个包的,这个包大约有180MB,下载很慢,导致所谓的的”卡死“. 如果你选用自定义安装的并且不 ...

  2. 如何在JS中应用正则表达式

    背景:在之前的随笔中写过C#中如何使用正则表达式,这篇随笔主要讲如何在js中应用正则表达式 如下代码: $("#zhengze").click(function () { var ...

  3. POJ 2396 Budget ——有上下界的网络流

    给定矩阵的每行每列的和,和一些大于小于等于的限制.然后需要求出一组可行解. 上下界网络流. 大概的思想就是计算出每一个点他需要强行流入或者流出的量,然后建出超级源点和汇点,然后删除下界,就可以判断是否 ...

  4. Codeforces Round #345 (Div. 2) E. Table Compression(并查集)

    传送门 首先先从小到大排序,如果没有重复的元素,直接一个一个往上填即可,每一个数就等于当前行和列的最大值 + 1 如果某一行或列上有重复的元素,就用并查集把他们连起来,很(不)显然,处于同一行或列的相 ...

  5. 关于事件委托和时间冒泡(以及apply和call的事项)

    搜索事件委托和事件冒泡,网上一大堆乱七八糟的解释,当然意思都对,没毛病. but,真的无聊. 事件冒泡:事件会从点击的元素开始依次向上流出,直到html,遇见事件监听则执行. 事件委托:原因——父元素 ...

  6. Bayan 2015 Contest Warm Up D. CGCDSSQ (math,pair,map,暴力)

    哎,只能转题解了,,, 8165031                 2014-10-10 15:53:42     njczy2010     D - CGCDSSQ             GN ...

  7. msp430项目编程42

    msp430综合项目---无线通信直流电机调速系统42

  8. cout与cerr

    cout对应于标准输出流,默认情况下是显示器.这是一个被缓冲的输出,可以被重定向. cerr对应标准错误流,用于显示错误消息.默认情况下被关联到标准输出流,但它不被缓冲,也就说错误消息可以直接发送到显 ...

  9. mysql续

    接上篇博客,写完以后看了看,还是觉的写的太简单,就算是自己复习都不够,所以再补充一些 1.创建多表关联 需求:图书管理系统,创建几张表,包含书籍,出版社,作者,作者详细信息等内容 分析: (1)图书只 ...

  10. list或map 打印成json 方便调试

    private final Logger logger = Logger.getLogger(this.getClass()); logger.info(JSON.toJSONStringWithDa ...