PE文件格式的第一个组成部分是MS-DOS头。熟悉DOS操作系统的读者会清楚,DOS头并非一个新概念,它与MS-DOS 2.0以来就有的MS-DOS头是完全一样的。保留这个相同结构的最主要原因是,当你尝试在低版本的Windows(比如16位的Windows)或者DOS操作系统下运行一个PE文件的时候,操作系统能够读有效地识别这个文件,并告诉用户这个文件不能在低版本的Windows操作系统下运行。如果MS-DOS头不是作为PE文件格式的第一部分的话,那么DOS操作系统将不能正确识别这个文件。作者认为,这也没有什么大碍,无非是不能运行而已。
下面是DOS头的格式定义,它占用了64B:
图14-1 PE文件格式的构成(www.xing528.com)
这些字段都是用于MS-DOS处理可执行文件时使用的,因此大部分字段的含义不用深入追究。这里重点关注一下e_lfanew变量,即最后一个变量。这个变量指向了PE文件头的地址(PE文件头在文件中的位置),我们就是通过这个字段,来获得PE文件头信息的。
前面我们提到,当你尝试在MS-DOS 6.0下运行一个Windows NT的可执行文件时,屏幕会显示这样一条消息:“This program cannot run in DOS mode”。这句话不是操作系统输出的,而是由PE文件头中的DOS stub程序输出的。即DOS在尝试运行一个PE文件的时候,首先检查其文件头是不是一个合法的MS-DOS头。显然,编译器会放置一个合法的MS-DOS头在PE文件的开始处。于是MS-DOS会认为这是一个可执行的DOS程序,于是“很高兴地”按照DOS头部的相关信息,加载这个程序并开始运行。显然,编译器会把MS-DOS头中的e_ip和e_cs等变量设置为指向DOS stub程序的开始处。最终结果是,DOS运行的只是一个stub程序,这个stub程序打印出上述提示信息,然后结束。DOS stub程序是由编译器添加上去的,当然,你也可以告诉编译器,在PE文件头中添加一个更加复杂的程序。比如有很多可执行程序,不论是在DOS下,还是在Windows下,都能够正确运行,但显示不同的界面。这就是通过替换缺省的stub程序做到的。这个可执行程序需要准备两个版本—16位的DOS版本和32位的Windows版本,然后把16位的DOS版本连接在DOS stub程序位置处。这样就实现了单一文件、双系统运行的效果。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。