7

我试图深入理解 DOS 标头,但我被这些标头所困扰。我知道唯一需要的字节是 MZ 签名和指向 PE 部分的指针,但我必须知道这两个到底是什么:

USHORT e_cblp;          // Bytes on last page of file
USHORT e_cp;            // Pages in file

在大多数可执行文件的二进制代码中,这些值分别是 90h 和 03h。一页是 512 字节的代码,所以有 3 页,但是在哪里呢?在文件中哪里可以找到它们?如何在 512 字节的最后一页中识别这些 90h (144) 字节?

此信息仅由 DOS 要求。在 DOS 中运行的 PE 文件的唯一代码是 DOS 存根,它不是 3 页代码,而是只有 64 个字节。那么,90h 和 03h 必须在那里做什么?我不能说e_cblp=01he_cp=DOS header+DOS stub吗?

4

2 回答 2

1

它是“整个”MZ 格式可执行文件的大小,最后一页中最后一个字节之后的任何内容都将被忽略。当 MS-DOS 加载 MZ 格式的可执行文件时,它会复制文件中标题之后的所有内容,直到此限制。因此,事实上大多数 PECOFF 可执行文件都将此字段设置为大于 MS-DOS 存根的值,这意味着当可执行文件在 MS-DOS 下运行时,PECOFF 标头和部分 PECOFF 节数据将被加载到内存中。

我不知道为什么 Microsoft 链接器(和 GNU 链接器,但不是 Borland 或 Watcom 的)使用的默认 DOS 存根说它的大小为 1168 字节,而实际上要小得多。如果您在使用 Microsoft 的链接器时提供自己的存根,它将使用提供的可执行文件的大小。Windows 在加载 PECOFF 可执行文件时似乎忽略了这个值,并且默认的 DOS 存根对额外数据没有任何用处。

请注意,可以使用 Microsoft 的链接器来创建只有 1024 字节长的有效 PECOFF 可执行文件。这要求可执行文件只有一个部分,并且大小小于 512 字节。虽然 Windows 将加载并运行可执行文件,但 MS-DOS 将拒绝,因为文件大小小于 MZ 标头中给出的 1168 大小值。

于 2017-04-06T20:34:37.330 回答
0

e_cblp

指定最后一页中实际使用的字节数,整页的特殊情况用零值表示(因为最后一页永远不会为空)。例如,假设页面大小为 512 字节,对于 1024 字节文件,该值将是 0x0000,对于 1025 字节文件,该值将是 0x0001(因为它只包含一个有效字节)。

所以,1024 + 144(90h) = 1168 字节

资源

于 2019-09-18T03:15:00.380 回答