|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
也许唯一可以让世人留恋net网页编程的理由就剩下它的王牌——跨平台。系列文章目次索引:《你必需晓得的.NET》
<br>说在,开篇之前很早就有说说Metadata(元数据)和IL(两头言语)的设法了,一向在这篇入手下手才算兢兢业业的对这两个阶层兄弟投往些细关切,固然来得没有《第一回:恩仇情仇:is和as》那末敏捷,可是Metadata和IL倒是相对分量级的内容,值得我们在任什么时候间存眷,本文就是入手下手。1弁言你可曾想到,我们的C#代码,编译以后事实为什么物?你可曾认知,我们的可实行程序,运转之时的轨迹事实为哪般?那末,本文经由过程对Metadata(元数据)和IL(IntermediateLanguage,两头言语)的熟悉入手下手,来慢慢给出谜底。在这个探究轨迹上,元数据、IL、程序集、程序域、JIT、虚分拨、办法表和托管堆这些五花八门的奥秘佳宾将在某个时候萍水相逢,作为你必需晓得的.NET系列2.0版本的一部分,本文起首从熟悉元数据和IL这两位分量级选手入手下手,而其他的佳宾也将很快退场。
2初度打仗
在现实上,编译以后的cs代码被构造为两种基础的元素:元数据(Metadata)和IL。我们能够以最复杂的体例来懂得程序集(*.dll)或可实行文件(*.exe)中包括的Metadata和IL的奥密,这类体例就是我们常说的反编译,翻开ILDasm并加载完成筹办的程序集,我们能够看到托管PE文件的相干内容:
<br>
具体的布局信息和IL代码剖析,能够拜见[你必需晓得的.NET]第3章“统统从IL入手下手”的先容,在此就不做太多的剖析。别的,我们能够经由过程实行“View/MetaInfo/Show!”大概Ctrl+M快速键来猎取该程序集所利用的MetaData信息列表:
个中该程序集利用的元数据次要有:Module、TypeRef、TypeDef、Method、Param、MemberRef、CostomAttribute、Assembly、AssemblyRef等,同时还包含#Strings、#GUID、#Blob、#US堆等。
固然,关于ILDasm工具,另有良多好玩的利用体例来满意我们探究IL代码的猎奇心,比方:
<br>ildasmAnytao.Insidenet.MetadataIL.exe/output:my.il,将反编译了局导出为il代码格局,天生一个my.il包括了一切的IL代码和一个my.res包括了一切的资本文件。
<br>ildasmAnytao.Insidenet.MetadataIL.exe/text,将反编译了局以Console情势输入。 固然我们仍是保举以GUI情势来检察IL细节,构造布局优秀的ClassView:
<br>ildasmAnytao.Insidenet.MetadataIL.exe
上面起首给出介入编译的相干代码文件,然后再睁开我们对Metadata和IL的会商:
//Release:code01,2009/02/12
//Author:Anytao,http://www.anytao.com
//List:One.cs
publicclassOne
{
publicintID{get;set;}
}//Release:code02,2009/02/12
//Author:Anytao,http://www.anytao.com
//List:Two.cs
publicclassTwo
{
publicstringSayHello()
{
return"Hello,world.";
}
}//Release:code03,2009/02/12
//Author:Anytao,http://www.anytao.com
//List:Program.cs
classProgram
{
staticvoidMain(string[]args)
{
intid=1;
Oneone=newOne();
one.ID=id;
Twotwo=newTwo();
Console.WriteLine(two.SayHello());
}
}接着,我们对上述程序的编译实行历程举行一点探究,以命令行编译器来演变其大抵的编译历程,以此进一步懂得托管模块,程序集和可实行文件之间的干系:
- 翻开VisualStudio2008CommandPrompt,并定位到cs代码地点文件夹,编译One.cs为托管模块,实行命令:
<br>csc/t:moduleOne.cs
实行以后,将天生名为One.netmodule文件;
<br>csc/t:library/addmodule:One.netmoduleTwo.cs实行以后,将天生名为Two.dll文件;
- 最初,编译Main函数和Two.dll为可实行文件
<br>csc/out:Anytao.Insidenet.MetatdataIL.exe/t:exe/r:Two.dll/r:mscorlib.dllProgram.cs终极将失掉本文入手下手时所加载的用于反编译的程序集文件Anytao.Insidenet.MetadataIL.exe,在该实行命令中对几个唆使符开关做点申明:
- /out:Anytao.Insidenet.MetadataIL.exe,暗示输入的可实行文件,及其称号
- /t:exe,暗示输入的文件范例为CUI(把持台界面程序)程序;而/t:winexe,暗示输入为GUI(图形界面程序)程序
- /r:Two.dll,暗示援用方才临盆的Two.dll程序集
- /r:mscorlib.dll,暗示由于内部程序集mscorlib.dll,由于我们的程序中利用了Console静态办法,而该办法则被界说在mscorlib.dll中。mscorlib.dll是云云的主要,我们将在本文以后的某些时分再次与mscorlib.dll握手,当时在对其举行一个具体的剖析,敬请等候。
在cmd中的实行历程能够参考:
<br>
经由过程分步实行的体例我们对csc编译器的实行历程有个基础的懂得,也同时从正面熟悉了每次在VisualStudio中实行“Build“大概“ReBuild”的缩影。综上剖析,我们能够复杂的看到:
Note:在VisualStudio中,编译是分模块举行的,编译了局保留在obj目次中,最初再兼并为可实行文件于bin目次,同时默许情形下,编译历程是增量式的,仅编译产生修正的模块,我将在后文给出较为具体的历程。
同时,我们还能够劳绩以下几个基础的结论:
- cs代码编译以后将天生元数据和IL,并构成托管模块(Module)的基础单位。
- 多个托管模块构成程序集,实在还包含必定的资本文件,只是没有在此表现。
- 程序集大概可实行文件是逻辑构造的基础单位,切合基础的WindowsPE文件格局,能够被x86大概x64Windows间接加载实行。
3持续深切
一个大概多个模块,再加上资本文件就构成了程序集(Assembly),作为逻辑构造的基础单位,
<br>
现实上,此图仅仅从粗粒度对程序集的基础构成有个大抵的懂得,实践上程序会合包括了庞大的布局和要素,比方PESignature、ManagedResources、StrongNameSignatureHash,而个中最中心的要素则表现在上图。
- 程序集清单(MANIFEST)包括了程序集的自形貌信息,次要包括AssemblyDef、FileDef、ManifestResourceDef和ExportedTypeDef,在反编译选项中MANIFEST包括了具体的内容。在《你必需晓得的.NET》3.1节“从Hello,world入手下手熟悉IL”对其有过具体的形貌,此不赘述。
- PE文件头,尺度WindowsPE头文件(PE32或PE32+),PE文件的基础信息,比方文件范例,创立工夫,当地CPU信息等。
- CLR头,包括CLR版本、模块元数据、资本等信息。
- 资本文件。
实行View/Statisctics菜单,能够翻开相干的统计信息:
Filesize:5632
PEheadersize:512(496used)(9.09%)
PEadditionalinfo:1691(30.02%)
Num.ofPEsections:3
CLRheadersize:72(1.28%)
CLRmeta-datasize:2212(39.28%)
CLRadditionalinfo:0(0.00%)
CLRmethodheaders:52(0.92%)
Managedcode:287(5.10%)
Data:2048(36.36%)
Unaccounted:-1242(-22.05%)
Num.ofPEsections:3
.text-3072
.rsrc-1536
.reloc-512
CLRmeta-datasize:2212
Module-1(10bytes)
TypeDef-4(56bytes)0interfaces,0explicitlayout
TypeRef-25(150bytes)
MethodDef-8(112bytes)0abstract,0native,8bodies
FieldDef-1(6bytes)0constant
MemberRef-29(174bytes)
ParamDef-2(12bytes)
CustomAttribute-16(96bytes)
StandAloneSig-4(8bytes)
PropertyMap-1(4bytes)
Property-1(6bytes)
MethodSemantic-2(12bytes)
Assembly-1(22bytes)
AssemblyRef-1(20bytes)
Strings-920bytes
Blobs-328bytes
UserStrings-68bytes
Guids-16bytes
Uncategorized-192bytes
CLRmethodheaders:52
Num.ofmethodbodies-8
Num.offatheaders-4
Num.oftinyheaders-4
Managedcode:287
Avemethodsize-35
我们将在后篇《深切程序集和模块》中对PE头,CLR头和资本文件举行具体叙述。
.classpublicautoansibeforefieldinitAnytao.Insidenet.MetadataIL.Two
extends[mscorlib]System.Object
{
.methodpublichidebysiginstancestring
SayHello()cilmanaged
{
//Codesize11(0xb)
.maxstack1
.localsinit([0]stringCS$1$0000)
IL_0000:nop
IL_0001:ldstr"Hello,world."
IL_0006:stloc.0
IL_0007:br.sIL_0009
IL_0009:ldloc.0
IL_000a:ret
}//endofmethodTwo::SayHello
.methodpublichidebysigspecialnamertspecialname
instancevoid.ctor()cilmanaged
{
//Codesize7(0x7)
.maxstack8
IL_0000:ldarg.0
IL_0001:callinstancevoid[mscorlib]System.Object::.ctor()
IL_0006:ret
}//endofmethodTwo::.ctor
}//endofclassAnytao.Insidenet.MetadataIL.Two包装在相似于汇编容貌的外套下,我看模糊可见class,System.Object,method,public,string这些面向对象初级言语中的熟习面目面貌,分歧的只是多了良多benforefieldinit(参考:[你必需晓得的.NET]第二十三回:咀嚼细节,深切.NET的范例机关器),ret,maxstack,ldstr,stloc这些生疏的指令。但是IL并不是一个怪胎,而恰是基于其自己面向对象的汇编式作风,才作育了IL代码成为名不虚传的“两头言语”的重担。经由过程IL代码,CLR便可在编译时由JIT编译转换为NativeCode,我们将鄙人节持续剖析这个历程的前因后果。
<br>欲知后事怎样,且听下文持续:-)
- 元数据是甚么?
- IL是甚么?
- 元数据和IL在JIT编译时
参考文献
- 《你必需晓得的.NET》第3章“统统从IL入手下手”
- DonBox,《.NET实质论》
- http://www.sloppycode.net/articles/inside-net-assemblies-and-metadata.aspx
- http://www.codeproject.com/KB/dotnet/dotnetformat.aspx
来自:http://www.ckuyun.com/anytao/archive/2009/02/24/must_net_24.html
因为二次编译器太复杂,那么建议只是在安装程序的时候编译一次,而不类似net网页编程那样运行就编译。并且我觉得,一次痛苦,总比多次低效率要舒服多了。 |
|