网站首页设计与制作,中国做网站的网站,工程信息价查询,网站制作中搜索栏怎么做本文将介绍以下内容#xff1a; IL代码分析方法 IL命令解析 .NET学习方法论 1. 引言 自从『你必须知道.NET』系列开篇以来#xff0c;受到大家很多的关注和支持#xff0c;给予了anytao巨大的鼓励和动力。俱往昔#xff0c;我发现很多的园友都把…本文将介绍以下内容
· IL代码分析方法
· IL命令解析
· .NET学习方法论 1. 引言 自从『你必须知道.NET』系列开篇以来受到大家很多的关注和支持给予了anytao巨大的鼓励和动力。俱往昔我发现很多的园友都把目光和焦点注意在如何理解IL代码这个问题上。对我来说这真是个莫大的好消息因为很明显我们的思路慢慢的从应用向底层发生着转变技巧性的东西是一个方面的积累底层的探索在我认为也是必不可少的修炼。如果我们选择了来关注这项修炼那么我们就应该选择如何来着手这项修炼首先关注anytao的『你必须知道的.NET』系列可以给你提供一个捷径少花一些功夫其次对大师级的作品也应有更深入的了解如《Applied Microsoft .NET Framework Programming》、《.NET本质论》再次就是像我一样从博客园和MSDN的知识库中不断的成长。呵呵除了给自己做了个广告之外我认为不管是何种途径了解和认识IL代码对于我们更深刻的理解.NET和.NET应用之上的本质绝对有不一样的收获这也就是本文研究和分享的理由。 那么我们要了解IL代码就要知道了解IL的好处时间对每个程序设计师来说都是宝贵的你必须清楚自己投资的价值再决定投入的资本。对于.NET程序员来说IL代码意味着
· 通用的语言基础是.NET运行的基础当我们对程序运行的结果有异议的时候如何透过本质看表面需要我们从本质入手来探索这时IL是你必须知道的基础
· 元数据和IL语言是CLR的基础了解必要的中间语言是深入认识CLR的捷径
· 大量的事例分析是以IL来揭密的因此了解IL是读懂他人代码的必备基础可以给自己更多收获。 很明显这些优越性足以诱惑我们花时间和精力涉猎其中。然而了解了IL的好处并不意味着我们应该过分的来关注IL有人甚至可以洋洋洒洒的写一堆IL代码来实现一个简单Hello world程序但是正如我们知道的那样程序设计已经走过了几十年的发展如果纯粹的陶醉在历史中除了脑子不好没有其他的解释。不然看见任何代码都以IL的角度来分析又将走进另一个误区我们的宗旨是追求但不过分。 因此有了上述了应该了解的理由和不应该过分的基线在摆正心态的前提下本文开始以作者认为的方式来展开对IL代码的认识作者期望通过本文的阐述与分析使得大家都能对IL有个概观之解并在平时的项目实践中使用这种方法通过了解自己的代码来了解.NET。我想这种方法应该是值得提倡和发挥的最佳实践不知你信不信呢呵呵。
2. 使用工具 俗话说工欲善其事必先利其器。IL的器主要就是ILadsm.exe和reflector.exe这两个工具都是了解IL的基础其原理都是通过反射机制来查看IL代码。
· ILadsm.exe 打开.NET Framework SKD 命令提示行输入ildasm回车即可打开如图所示 上图是我们熟悉的《第十三回从Hello, world开始认识IL》中的示例其中的树形符号代表的意思可以从MSDN的一张经典帮助示例来解释如下图所示 图表来源MSDN
· reflector.exe【下载】 Reflector是Lutz Roeder开发的一个让人兴奋的反编译利器目前的版本是Version 5.0.35.0可以支持.NET3.0其功能也相当强大在使用上也较ILDASM更加灵活如图所示 Reflector可以方便的反编译为IL、C#、VB、Delphi等多种语言是深入了解IL的最佳利器。 在本文中我们以最简单的ILadsm.exe为说明工具。
3. 分析结构 分析IL结构就参阅《第十三回从Hello, world开始认识IL》 已经有了大致的介绍在此不需要进行过多的笔墨实际上IL的本身的结构也不是很复杂了解了大致的体系即可。
4. 解析常用命令 我们在了解了IL文件结构的基础上通过学习常用的IL命令就可以基本上对IL达到了了解不过分的标准因此对IL常用命令的分析就是本文的重点和要点。我们通过对常用命令的解释、示例与分析逐步了解你陌生的语言世界原来也很简单。 IL指令集包括了基础指令集和对象模型指令集大概有近200多个对我们来说消化这么多的陌生指令显然不是明智的办法就行高级语言的关键字一样我们只取其一瓢独饮抓大放小的革命传统同样是有效的学习办法详细的指令集解释请下载[MSIL指令速查手册]。
4.1 newobj和initobj newobj和intiobj指令就像两个兄弟常常让我们迷惑在其然而不知其所以然虽然认识但是不怎么清楚这种感觉很郁闷下面就让我们看看他们的究竟
代码引入 指令说明 深入分析
从上面的代码中我们可以得出哪些值得推敲的结论呢
MSDN给出的解释是newobj用于分配和初始化对象而initobj用于初始化值类型。
那么newobj又是如何分配内存完成对象初始化而initobj又如何完成对值类型的初始化呢
显然关于newobj指令在《第五回深入浅出关键字---把NEW说透》中已经有了一定的介绍简单说来关于newobj我们有如下结论
· 从托管堆分配指定类型所需要的全部内存空间。
· 在调用执行构造函数初始化之前首先初始化对象附加成员一个是指向该类型方法表的指针一个是SyncBlockIndex用于进行线程同步。所有的对象都包含这两个附加成员用于管理对象。
· 最后才是调用构造函数ctor进行初始化操作。并返回新建对象的引用地址。
而initobj的作用又可以小结为
· 构造新的值类型完成值类型初始化。值得关注的是这种构造不需要调用值类型的构造函数。具体的执行过程呢以上例来说initobj MyStruct的执行结果是将MyStruct中的引用类型初时化为null而基元类型则置为0。
因此值类型的初始化可以是
//initobj方式初始化值类型
initobj Anytao.net.My_Must_net.IL.MyStruct
同时也可以直接显示调用构造函数来完成初始化具体为 MyStruct ms new MyStruct(123); 对应于IL则是对构造函数cto的调用。
//调用构造函数方式初始化值类型
call instance void Anytao.net.My_Must_net.IL.MyStruct::.ctor(int32)
· Initobj还用于完成设定对指定存储单元的指针置空null。这一操作虽不常见但是应该引起注意。
由此可见newobj和initobj都具有完成实例初始化的功能但是针对的类型不同执行的过程有异。其区别主要包括
· newobj用于分配和初始化对象而initobj用于初始化值类型。因此可以说newobj在堆中分配内存并完成初始化而initobj则是对栈上已经分配好的内存进行初始化即可因此值类型在编译期已经在栈上分配好了内存。
· newobj在初始化过程中会调用构造函数而initobj不会调用构造函数而是直接对实例置空。
· newobj有内存分配的过程而initobj则只完成数据初始化操作。
关于对象的创建还有其他的情况值得注意例如
· Newarr指令用来创建一维从零起始的数组而多维或非从零起始的一维数组则仍由newobj指令创建。
· String类型的创建由ldstr指令来完成具体的讨论我们在下文来展开。
4.2 call、callvirt和calli
call、callvirt和calli指令用于完成方法调用这些正是我们在IL中再熟悉不过的几个朋友。那么同样是作为方法调用这几位又有何区别呢我们首先对其做以概括性的描述再来通过代码与实例进入深入分析层面。
· call使用静态调度也就是根据引用类型的静态类型来调度方法。
· callvirt使用虚拟调度也就是根据引用类型的动态类型来调度方法
· calli又称间接调用是通过函数指针来执行方法调用对应的直接调用当然就是前面的call和callvirt。
然而虽然有以上的通用性结论但是对于call和callvirt不可一概而论。call在某种情况下可以调用虚方法而callvirt也可以调用非虚方法。具体的分析我们在以后的文章中来展开暂不做过多分析。
5. 结论 本文从几个重点的IL指令开始力求通过对比性的分析和深入来逐步揭开IL的神秘与迷惑正如我们在开始强调的那样本文只是个开始也许也是个阶段对IL的探求正如我自己的脚步一样也在继续着为的是在.NET的技术世界能够有更多的领悟。作者期望通过不断的努力逐渐和大家一起从IL世界探求.NET世界在以后的讨论中我们间或的继续这个主题的不断成长。 [下载]
reflector.exe
IL指令速查手册感谢温少提供
参考文献
USAJeffrey Richter, Applied Microsoft .NET Framework Programming
USADavid Chappell Understanding .NET
[公告]
【CLR团队公告】活动公告、邀请函、团队纲领
【系列公告】从架构到设计、你必须知道的.NET
温故知新
[开篇有益] [第一回恩怨情仇is和as] [第二回对抽象编程接口和抽象类] [第三回历史纠葛特性和属性] [第四回后来居上class和struct] [第五回深入浅出关键字---把new说透] [第六回深入浅出关键字---base和this] [第七回品味类型---从通用类型系统开始] [第八回品味类型---值类型与引用类型上内存有理] [第九回品味类型---值类型与引用类型中规则无边] [第十回品味类型---值类型与引用类型下应用征途] [第十一回参数之惑---传递的艺术上] [第十二回参数之惑---传递的艺术下] [第十三回从Hello, world开始认识IL]