2

我正在学习操作系统概念。我已经设法自己创建了一个引导加载程序。我生成的每个可执行文件都在 BIN 中。

我看到微软在其系统中使用了 PE 文件格式。同样,Unix 使用 COFF。

这些多种文件格式有什么用?与其他相比,它们是否具有任何文件保护或附加功能?

4

2 回答 2

9

从历史上看,今天使用的常见目标文件格式PECOFFELFMach-O是为特定操作系统(Windows NT、Unix System V R4 和 Mach)完全独立开发的,旨在解决以前目标文件格式的缺点。

Unix

a.out

Unix 使用的最早的目标文件和可执行格式是a.out格式。这是一种非常简单的格式,几乎是当时硬件所需的最低要求。它的名字来源于 Unix 汇编器和链接器使用的默认输出文件名。如果未指定输出文件,这些程序将创建一个名为a.out. 今天大多数 Unix 汇编器和链接器仍然这样做。

COFF

在 Unix System V 中,AT&T 引入了COFF(通用对象文件格式)来取代 a.out 格式。它也是一种可执行和目标文件格式。它对 a.out 格式的主要改进是多个部分。a.out 格式仅支持带有隐含部分的文本和数据.bss部分。多个部分使工具和应用程序在布置可执行文件方面具有更大的灵活性,例如允许它们创建只读数据部分。COFF 还增加了对共享库的支持。

精灵

为了解决 COFF 的许多问题,AT&T 为 Unix System V R4 创建了 ELF(可执行和可链接格式)。COFF 的主要问题是它不是很灵活且定义不明确,因此它必须由实施的各种供应商以各种不兼容的方式进行扩展。这不是它所希望的“通用”格式。ELF 还通过比 COFF 共享库更动态的符号链接形式为与位置无关的共享对象提供支持。它还有一个相当复杂和可扩展的关联调试格式,称为DWARF

在 Unix 机器上,ELF 是主要的可执行文件和目标文件格式。只有少数操作系统(如 AIX)坚持使用其自定义的基于 COFF 的格式。所有大型开源操作系统,Linux 和 BSD,都使用 ELF,但值得注意的是,它们直接从基于 a.out 的格式转到 ELF,跳过了 COFF。由于 ELF 是一种对象文件格式和可执行格式,这意味着大多数 Unix 开发工具创建 ELF 对象,这些对象链接在一起以创建 ELF 可执行文件。

微软

OMF、.COM 和 MZ .EXE

在 MS-DOS 下,标准的对象文件格式是英特尔为他们的 x86 处理器创建的OMF (对象模块格式)。MS-DOS 本身使用了两种不同的可执行格式。起初它只支持简单的.COM文件,只是像你的引导加载程序这样的平面二进制文件,取自 CP/M(就像 MS-DOS 1.x 中的几乎所有东西)。在 MS-DOS 2.0 中,微软增加了对“MZ”.EXE可执行文件的支持,之所以这么称呼是因为它使用了这两个字符MZ作为一个幻数来识别文件类型。MZ 格式允许可执行文件使用多个段,而 .COM 格式有效地将程序限制为一个 64K 段。Microsoft 自己的 MS-DOS 开发工具以及大多数其他第三方工具生成了 OMF 格式的对象文件,这些文件被链接以创建 .COM 和 MZ 格式的可执行文件。

新的可执行文件 (LE)

对于 Windows 1.0,微软创建了新的可执行文件Windows 可执行文件的 (NE) 格式。这种格式的主要特点是它使可执行文件中的段显式化,显示它们从哪里开始和在哪里结束。MZ 格式通过在代码中重新定位段值来支持段。否则,它是一个平面二进制文件,以单个连续块的形式加载到内存中,就像 .COM 文件一样,除了段引用已修复。在可执行文件中显式地显示段让 Windows 可以单独加载段,甚至可以根据需要移动和卸载它们。由于 Windows 与 MS-DOS 不同,支持一次运行多个程序,因此这一点非常重要,否则内存很快就会变得过于碎片化。NE 格式添加的另一个重要特性是对 DLL(动态链接库)的支持。

然而微软并没有改变使用的目标文件格式。Microsoft 用于早期 16 位版本 Windows(以及 16 位版本的 OS/2)的开发工具继续创建 OMF 对象文件,这些文件被链接以创建 NE 格式的可执行文件。OMF 格式易于扩展,NE 格式只需要少量添加,尤其是用于导入和导出 DLL 的符号。

线性可执行文件 (LE)

对于 Windows/386 2.10,Microsoft 创建了另一种可执行格式,称为线性可执行文件(LE)。这个新版本的 Windows 有一个 32 位虚拟机管理器 (VMM),本质上是一个简单的虚拟机,可以并行运行 Windows 和一个或多个 MS-DOS 实例。对于每个操作系统来说,它们看起来就像拥有整台 PC,但实际上它只是一个虚拟机。由于 VMM,更重要的是它的驱动程序 ( VxDs ) 是 32 位的,因此旧的 16 位 NE 格式无法工作。

我不确定最初创建 LE 可执行文件时使用的对象格式。后来在创建VxDs时使用 PECOFF 对象文件成为标准,但直到几年后才创建该格式。他们可能使用了 OMF,扩展为支持 32 位对象,就像 IBM 对 OS/2 2.0 所做的那样,它也使用 LE 格式的变体来支持其 32 位可执行文件。

PECOFF

Microsoft 在 Windows NT 中引入了 PECOFF。虽然它们已经是可用的 32 位可执行格式,但 LE 格式和 OMF 都支持 32 位对象,但这两种格式都与 Intel x86 处理器相关联。Windows NT 旨在支持多种 CPU,最初除了基于 x86 Intel 的 PC 之外,它还支持 MIPS 和 DEC Alpha CPU。开发 Windows NT 的团队没有采用 LE 和 OMF 来支持这些其他处理器,而是决定采用现有的 Unix COFF 格式,该格式已经支持多个 CPU。我的猜测是,Microsoft Windows NT 团队早期使用现有的基于 Unix 的开发工具来开发 Windows NT,而不是等待 Microsoft 的独立开发工具团队为其他 CPU 创建工具。否则 Windows NT 可能会有 LE 和 OMF 格式的改编版本,

PECOFF 在 COFF 上添加的主要功能是对 DLL 的支持,这是 Windows 从一开始就固有的东西。COFF 支持类似但不同的共享库机制。微软后来扩展了 PECOFF 格式以支持 64 位 CPU。

由于 PECOFF 既是目标文件格式又是可执行文件,用于 32 位 Windows 版本的 Microsoft 开发工具创建 PECOFF 目标文件,这些文件链接以创建 PECOFF 可执行文件。值得注意的是,Borland 的工具生成了与创建 PECOFF 可执行文件相关联的 OMF 文件,但如今大多数其他工具都效仿 Microsoft 的做法(例如 MinGW 或 Intel 的 ICC)。

操作系统

马赫-O

Mach-O 格式是为Mach 内核创建的,因此得名。该内核用于 NeXTSTEP,它成为 Apple 的 OS X 的基础。创建 Mach-O 格式是为了替代 BSD 使用的 a.out 格式,后者提供了基于 Mach 的操作系统的大多数非内核部分。主要驱动力似乎是创建与位置无关的共享库和可执行文件。Mach-O 和使用它的操作系统的特点之一是所有代码都必须是位置独立的,而不仅仅是共享库。

结论

因此,正如您所看到的,在不同操作系统上工作的不同群体已经根据他们当时的需求独立工作以创建这些不同的格式。早期,Microsoft 需要格式来支持 Intel x86 特殊的分段内存模型,而 OMF 是唯一支持它的对象文件格式。Unix 需要一些不同的东西,支持多个 CPU。当微软需要多 CPU 支持时,他们选择了基于当时最近过时的 COFF 格式的格式,当时可能在比新的 ELF 格式更多的 CPU 类型上实现。与此同时,Mach 内核开发人员在他们自己的世界里,徒劳地试图创建一个可行的微内核。我不确定他们对 Mach-O 到底在想什么,但他们不得不用其他东西替换 a.out,我猜 COFF 不是

于 2016-05-24T21:37:03.850 回答
4

除了独立的团队会以不同的方式解决同一个问题之外,可能没有其他原因有多种目标文件格式。多年前,当每个计算机系统都不同且不兼容,都有专有的操作系​​统,并且没有开源代码可言时,目标文件格式标准化将毫无用处。随着 CP/M、Unix、MS-DOS、Linux 和 Windows 等便携式操作系统的引入,相同类型系统之间的一些标准化元素变得必要,但没有必要在这些系统之间进行标准化。

请注意,Microsoft 的可执行文件格式是 PE,但 PE 中使用的目标文件格式是 COFF。

使不同格式适用于不同环境的目标代码格式的另一个方面是运行时环境。加载到 ROM 的代码不需要元数据,因为它不是动态加载的,因为可能会使用原始二进制文件或十六进制编码文件,类似的位置相关代码需要加载的信息非常少,但是操作系统加载的用户应用程序代码包含使用的信息由操作系统的加载程序在合适的运行时环境中加载和启动应用程序。不同的操作系统以不同的方式执行此过程,因此它们具有不同的可执行格式也许不足为奇。

于 2016-05-24T14:03:07.353 回答