dotnet学习笔记二 - 运行.net程序的秘密

.NET Framework给我们提供了良好的开发平台。有很好的类库,可以跨语言,跨平台等等。但是他的内部实现细节是怎样的呢?.NET编译出来的exe文件并不是机器码,它是怎样和CLR结合起来的呢?下面就让我们揭开这个小秘密。

首先做一个简单的.NET应用,把它编译成EXE文件。然后用Visual Studio 6.0带的工具Depends把它打开。如下图:

这里可以看到一个很奇怪的现象,我的.net应用程序只直接依赖于一个dll – MSCOREE.DLL。而且这个DLL输出的这么多函数中也只用到了一个_CorExeMain。我的这个APPENDLINE.EXE中还用到了自己做的一个.NET组件,在这里也看不到。

再让我们借助一些PE察看工具来分析一下这个EXE文件。这一步得到的结果是什么呢?在这个PE文件的入口函数上可以看到一条唯一的汇编语句:

JMP  DS:_CorExeMain

经过上面的步骤,我们可以明确的断定所有的.net编译后的EXE文件一旦运行,就执行MSCOREE.DLL输出的一个函数_CorExeMain。而在开发过程中我们使用到的一些外部组件、控件由于是被.net编译器编译成了中间代码,在Depends中是无法看到的,所有使用外部组件的过程全部由CLR处理。

幸运的是微软这次公布了一个CLI实现的代码,我们可以看个究竟。我下载的代码中没有找到_CorExeMain,只找到了一个_CorExeMain2。参数有5个:

PBYTE   pUnmappedPE,                // -> memory mapped code

    DWORD   cUnmappedPE,                // Size of memory mapped code

    LPWSTR  pImageNameIn,               // -> Executable Name

    LPWSTR  pLoadersFileName,           // -> Loaders Name

    LPWSTR  pCmdLine

一目了然,pUnmappedPEcUnmappedPE就是.net编译后的中间代码的内存缓冲和长度。pImageNameIn就是这个EXE的名字,pLoadersFileName是载入者的名字,pCmdLine就是命令参数。有了这几个参数我们就可以猜到.net将中间代码编译后放入到PE文件中,再加入一段代码直接执行MSCOREE.DLL_CorExeMain,参数就是中间代码的内存指针。JIT就把这段中间代码编译成机器代码执行。

_CorExeMain2代码不长,简单总结一些,做了如下的5步工作:

1.         验证签名。

2.         初始化CLR环境

3.         创建了一个代表EXE文件的PEFile对象

4.         使用SystemDomain的静态方法执行这个PEFile

5.         执行后,做一些清除工作,退出。

 

很明显,上面5个步骤里最重要,最关键的就是第4步了,究竟做了什么呢?有兴趣的朋友可以去看微软的CLI代码,我在以后的文章中也会进一步分析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

kenli

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值