表4-3 EXE文件头结构
偏移量 | 表示意义 |
00h-01h | 4DH,5AH :EXE |
02h-03h | 文件长度除512的余数 |
04h-05h | 文件长度除512的商 |
06h-07h | 重定位项的个数 |
08h-09h | 文件头除16的商 |
0ah-0bh | 程序运行所需最小段数 |
0ch-0dh | 程序运行所需最大段数 |
oeh-0fh | 堆栈段的段值(SS) |
10h-11h | 堆栈段的段值(SP) |
12h-13h | 文件校验和 |
14h-15h | 装入 模块 入口时的IP值 |
16h-17h | 装入模块代码段相对段值 |
18h-19h | 重定位表,开始位置,以位移地址指示 |
1ah-1bh | 覆盖号(程序驻留为0) |
1ch- | 重定位表,起点由偏移18h-19h给出,项数由06h-07h标明 |
文件头还指向一个重定位表,该表包含指向程序映象中可重定位段地址的指针链表。文件头的形式与EXEHEADER结构对应: EXEHEADER STRUC exSignature dw 5A4Dh ;EXE标志 exExraBytes dw ? ;最后(部分)页中的字节数 exPages dw ? ;文件中的全部和部分页数 exRelocItems dw ? ;重定位表中的指针数 exHeaderSize dw ? ;以字节为单位的文件头大小 exMinAlloc dw ? ;最小分配大小 exMaxAlloc dw ? ;最大分配大小 exInitSS dw ? ;初始SS值 exInitSP dw ? ;初始SP值 exChechSum dw ? ;补码校验值 exInitIP dw ? ;初始IP值 exInitCS dw ? ;初始CS值 exRelocTable dw ? ;定位表的字节偏移量 exOverlay dw ? ;覆盖号 EXEHEADER ENDS
程序映象包含处理器代码和程序的初始 数据 ,紧接在文件头之后。它的大小以字节为单位,等于EXE文件的大小减去文件头的大小,也等于exHeaderSize域的值乘以16。MS-DOS通过把该映象直接从文件拷贝到 内存 加载EXE程序,然后调整定位表中说明的可重定位段地址。
定位表是一个重定位指针数组,每个指针指向程序映象中的可重定位段地址。文件头中的exRelocItems域说明了数组中指针的个数,exRelocTable域说明了分配表的起始文件偏移量。每个重定位指针由两个16位值组成,它们分别是偏移量和段值。为了加载EXE程序,MS- DOS首先读文件头以确定EXE标志,并计算程序映象的大小。然后就试图 申请 内存。首先,MS-DOS计算程序映象文件的大小加上PSP的大小,再加上EXEHEADER结构中的exMinAlloc域说明的内存大小这三者之和,如果总和超过最大可用内存块的大小,则MS-DOS停止加载程序并返回一个出错值。否则,MS-DOS 分配计算得到的内存量。
分配完内存后,MS-DOS确定段地址,也称为起始段地址,MS-DOS从此处加载程序映象。如果exMinAlloc域和exMaxAlloc域中的值都为零,则MS-DOS把映象尽可能地加载到内存最高端。否则,它把映象加载到紧挨着PSP域之上。
接下来,MS-DOS读取重定位表中的 项目 调整所有由可重定位指针说明的段地址。对于重定位表中的每个指针,MS-DOS寻找程序映象中相应的可重定位段地址,并把起始段地址加到它之上。一旦调整完毕,段地址便指向了内存中被加载程序的代码和数据段。MS-DOS在所分配内存的最低端建立256字节的PSP,使用文件头中的值设置SP与SS,调整 SS初始值,把起始地址加到它之上。同时,还把ES和DS设置为PSP的段地址。最后,MS-DOS从程序文件头读取CS和IP的初始值,把起始段地址加到CS之上,把 控制 转移到位于调整后地址处的程序。
文件 标记