MS-DOS頭部/實模式頭部 如上所述,PE文件格式的第一個組成部分是MS-DOS頭部。在PE文件格式中,它并非一個新概念,因為它與MS-DOS 2.0以來就已有的MS-DOS頭部是完全一樣的。保留這個相同結構的最主要原因是,當你嘗試在Windows 3.1以下或MS-DOS 2.0以上的系統下裝載一個文件的時候,操作系統能夠讀取這個文件并明白它是和當前系統不相兼容的。換句話說,當你在MS-DOS 6.0下運行一個Windows NT可執行文件時,你會得到這樣一條消息:“This PRogram cannot be run in DOS mode.”假如MS-DOS頭部不是作為PE文件格式的第一部分的話,操作系統裝載文件的時候就會失敗,并提供一些完全沒用的信息,例如:“The name specified is not recognized as an internal or external command, Operable program or batch file.” MS-DOS頭部占據了PE文件的頭64個字節,描述它內容的結構如下: WINNT.H typedef strUCt _IMAGE_DOS_HEADER { // DOS的.EXE頭部 USHORT e_magic; // 魔術數字 USHORT e_cblp; // 文件最后頁的字節數 USHORT e_cp; // 文件頁數 USHORT e_crlc; // 重定義元素個數 USHORT e_cparhdr; // 頭部尺寸,以段落為單位 USHORT e_minalloc; // 所需的最小附加段 USHORT e_maxalloc; // 所需的最大附加段 USHORT e_ss; // 初始的SS值(相對偏移量) USHORT e_sp; // 初始的SP值 USHORT e_csum; // 校驗和 USHORT e_ip; // 初始的IP值 USHORT e_cs; // 初始的CS值(相對偏移量) USHORT e_lfarlc; // 重分配表文件地址 USHORT e_ovno; // 覆蓋號 USHORT e_res[4]; // 保留字 USHORT e_oemid; // OEM標識符(相對e_oeminfo) USHORT e_oeminfo; // OEM信息 USHORT e_res2[10]; // 保留字 LONG e_lfanew; // 新exe頭部的文件地址 } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; 第一個域e_magic,被稱為魔術數字,它被用于表示一個MS-DOS兼容的文件類型。所有MS-DOS兼容的可執行文件都將這個值設為0x5A4D,表示ASCII字符MZ。MS-DOS頭部之所以有的時候被稱為MZ頭部,就是這個緣故。還有許多其它的域對于MS-DOS操作系統來說都有用,但是對于Windows NT來說,這個結構中只有一個有用的域——最后一個域e_lfnew,一個4字節的文件偏移量,PE文件頭部就是由它定位的。對于Windows NT的PE文件來說,PE文件頭部是緊跟在MS-DOS頭部和實模式程序殘余之后的。
實模式殘余程序 實模式殘余程序是一個在裝載時能夠被MS-DOS運行的實際程序。對于一個MS-DOS的可執行映像文件,應用程序就是從這里執行的。對于Windows、OS/2、Windows NT這些操作系統來說,MS-DOS殘余程序就代替了主程序的位置被放在這里。這種殘余程序通常什么也不做,而只是輸出一行文本,例如:“This program requires Microsoft Windows v3.1 or greater.”當然,用戶可以在此放入任何的殘余程序,這就意味著你可能經常看到像這樣的東西:“You can't run a Windows NT application on OS/2, it's simply not possible.”