题主说的是.NET Assembly(程序集)对吧。知乎没有“.NET”这个标签还真是恼人,只有“Dotnet”标签…
言归正传,.NET Assembly虽然后缀名是.exe和.dll,文件格式确实也跟普通Win32应用程序一样是PE(
Portable Executable)格式,但其内容不一样。
普通Win32应用的PE文件里,PE格式的代码段里的代码就是程序的主要代码了,是以平台相关的机器码形式存储的;
而对.NET Assembly而言,其代码主体是以MSIL(或者叫CIL)的中间代码形式存储在PE格式的“资源”部分而不是在代码部分;其PE格式的代码段里只包含一小块“桩程序”(stub),负责将程序控制权交给CLR去继续执行该assembly里的MSIL代码。
也就是说,.exe后缀的.NET Assembly的PE格式代码段里其实只有这样一个函数调用:
_CorExeMain(...)
.dll后缀的则是:
_CorDllMain(...)
通过调用CLR的入口函数把控制权交给CLR。
不过从Windows XP开始,Windows自身的loader能够识别出.NET Assembly,从而直接启动CLR去执行该assembly而不需要执行上面说的stub代码。这stub代码主要是为了兼容更老版本的Windows用的。
放个传送门:
Anatomy of a .NET Assembly