读懂IL代码(二)
上一篇提到了最基本的IL代码,应该是比较通俗易懂的,所以有了上一篇的基础之后,这篇便要深入一点点的来讲述了。
首先我必须再来说一些重要的概念:
Evaluation Stack(评估栈):这是由.NET CLR在执行时候自动管理的记忆体,每一个线程都有自己的评估栈,也就是说,它是用来存储临时变量的线程栈(应该可以这么理解)。值类型存储数据,引用类型存储地址。
Call Stack(调用栈):这也是由.NET CLR在执行时候自动管理的记忆体,每一个线程都有自己的调用栈,每一次调用method,就会产生一个栈帧(stack frame),当方法结束的时候,此栈帧就会被丢弃。
大家一定疑问怎么都是栈呀,堆到哪里去了嘞,大家别急,下面说:
Managed Heap:这是动态配置的记忆体,由Garbage Collector(GC)执行时自动管理,整个程序共用一个。我把这个理解为托管堆,用来存储引用类型的值。
这一篇主要是以引用类型为主来讲述IL代码。
大家都知道把值类型变成引用类型是采用装箱的操作,所以这里也先说一下装箱的过程:
(1)内存分配,在Managed Heap(托管堆)中分配一个内存空间;
(2)将值类型的字段拷贝到分配的内存中;
(3)将托管堆中的对象地址返回给新的对象,Over。
以上是一些基本知识点,现在主要来讲解IL代码:
正规代码如下:
我用Reflector进行查看IL代码:
上图就是IL代码了,经过上一篇的介绍,我觉得这里大家应该也看得懂吧,下面我就来解释这段IL代码吧。
.method private hidebysig static void Main(string[] args)cilmanaged
{
.entrypoint //入口
.maxstack 2 //评估栈可容纳数据项的最大个数。
.locals init (
[] string str,
[] int32 num) //定义并初始化参数,并存入局部变量表(Call Stack)中。
L_0000: nop //No Operation
L_0001: ldstr "Helius" //将字符串“Helius”压入评估栈中。
L_0006: stloc.0 //将字符串从评估栈中弹出,赋值给局部变量表的第0个变量。
L_0007: ldc.i4.s 0x1b //解析:int类型的数值大小不一样,IL代码也是不一样的。比如int i=-1;IL代码为ldc.i4.M1;当i的值大于等于9的时候,IL代码就为ldc.i4.s(i的十六进制表示形式),当i的值小于等于-2时,IL代码表示为ldc.i4.s(i)。
L_0009: stloc.1 //将值从评估栈中弹出,赋值给局部变量表的第1个变量。
L_000a: ldloca.s num //取出局部变量表中num的值“27”并压入评估栈中。
L_000c: call instance string [mscorlib]System.Int32::ToString() //从评估栈中取出数值“27”,调用ToString方法转成string类型并将引用存入评估栈中。
L_0011: ldloc.0 //取出局部变量表中的第0个位置元素值“Helius”,并压入评估栈,(此时评估栈中有两个值,字符串“Helius”和“27”的引用地址)。
L_0012: call string [mscorlib]System.String::Concat(string, string) //调用String类的Concat方法把字符串拼接并存入托管堆中,把引用地址返回给评估栈。
L_0017: call void [mscorlib]System.Console::WriteLine(string) //调用输出方法,调用输出方法后评估栈中的值(指向托管堆中字符的地址)会被回收。
L_001c: nop
------------------------------------------分割线---------------------------------------------------------------------------------------------------
L_001d: ldloc.1 //取局部变量表中的第1个位置参数num值,存入评估栈中。
L_001e: box int32 //把num值27装箱,并返回托管堆中的地址存入评估栈中。
L_0023: ldloc.0 //去局部变量表中的第0个参数,并压入评估栈中。
L_0024: call string [mscorlib]System.String::Concat(object, object)//弹出评估栈中两个值,并调用String的Concat方法把字符拼接,存入托管堆中,并返回引用地址到评估栈中。
L_0029: call void [mscorlib]System.Console::WriteLine(string) //调用输出方法。
L_002e: nop
L_002f: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()//调用ReadKey方法
L_0034: pop //把评估栈的内容清空
L_0035: ret //return 标记返回
} 以图来解释上面的例子可能更明白一点(程序员学会画图很重要,我记得去面试的时候,面试官还叫我画项目的架构图):
图1
图2
图3
从以上的图中可以明显看出调用方法与装箱的流程。引用类型都是存放在托管堆里面的,而栈只存放引用类型的地址,这点是要特别注意的。
下一篇我会写方法,委托和类的IL代码解析。
读懂IL代码(二)的更多相关文章
- 读懂IL代码就这么简单(二)
一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...
- 【转载】读懂IL代码就这么简单(二)
一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...
- 读懂IL代码就这么简单(三)完结篇
一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍 这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认 ...
- 读懂IL代码就这么简单 (一)
一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道你的代码是如何运行相互调用的,此言一出不明觉 ...
- 读懂IL代码就这么简单
原文地址:http://www.cnblogs.com/zery/p/3366175.html 一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不 ...
- 读懂IL代码就这么简单 ---- IL系列文章
读懂IL代码就这么简单 (一) 读懂IL代码就这么简单(二) 读懂IL代码就这么简单(三)完结篇 出处:http://www.cnblogs.com/zery/tag/IL%20%E7%B3%BB%E ...
- 【转载】读懂IL代码就这么简单(三)完结篇
一 前言 写了两篇关于IL指令相关的文章,分别把值类型与引用类型在 堆与栈上的操作区别详细的写了一遍这第三篇也是最后一篇,之所以到第三篇就结束了,是因为以我现在的层次,能理解到的都写完了,而且个人认为 ...
- 【转载】读懂IL代码就这么简单 (一)
一前言 感谢 @冰麟轻武 指出文章的错误之处,现已更正 对于IL代码没了解之前总感觉很神奇,初一看完全不知所云,只听高手们说,了解IL代码你能更加清楚的知道你的代码是如何运行相互调用的,此言一出不明觉 ...
- 读懂IL代码(一)
以前刚开始学C#的时候,总有高手跟我说,去了解一下IL代码吧,看懂了你能更加清楚的知道你写出来的代码是如何运行互相调用的,可是那时候没去看,后来补的,其实感觉也不晚.刚开始看IL代码的时候,感觉非常吃 ...
随机推荐
- magic c c++ unix 注册机 注册码 破解版 下载
说起来都是伤心的事情前段时间,忙于找工作,面试的公司和入职的公司,想想都觉得很奇葩,其中有一家叫什么湖南普天科技有限公司的,他们是从国防科大接项目做的,那天他们叫我去面试,面试完了,说我们这里有个c+ ...
- 【HDOJ】1422 重温世界杯
简单题. #include <stdio.h> #define MAXN 100005 int wi[MAXN], li[MAXN]; ]; int main() { int n, tot ...
- Microsoft Windows 远程权限提升漏洞(CVE-2013-3175)(MS13-062)
漏洞版本: Microsoft Windows XP Microsoft Windows Vista Microsoft Windows Server 2008 Microsoft Windows R ...
- php-Mysql示例1
- javascipt取整数四舍五入
1.丢弃小数部分,保留整数部分 parseInt(5/2) 2.向上取整,有小数就整数部分加1 Math.ceil(5/2) 3,四舍五入. Math.round(5/2) 4,向下取整 Math.f ...
- python for selenium 数据驱动测试
# -*- coding:utf-8 -*- """ 数据驱动测试,从 csv 文件中读取数据 """ from selenium impo ...
- ubuntu安装jdk1.8
sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-i ...
- java多线程编程(3)买票
1,买票非同步版本 http://www.cnblogs.com/anbylau2130/archive/2013/04/17/3025347.html很详细 public class 多线程2 { ...
- Google协作平台
本博文的主要内容有 .Google协作平台的介绍 1.Google协作平台的介绍 https://zh.wikipedia.org/wiki/Google%E5%8D%8F%E4%BD%9C%E5%B ...
- 353. Design Snake Game
贪食蛇. GAME OVER有2种情况,1是咬到自己,2是出界. 1)用QUEUE来保留占据的格子,每走一格就添加1个,然后POll()最后一个. 做一个一样的SET来check要走的格子是不是已经在 ...