13

最近我一直在维护一个用 VC++ 6.0 编写的遗留项目。该代码使用了该编译器的许多独特特性,因此将其移植到更新的标准编译器已被证明是一项艰巨的任务。

在项目的数千行代码中,有四个汇编文件。出于某种原因,我不明白,MASM615 和 TASM 也无法编译它们(它们会发送错误),但我有目标文件。但是,当我链接库时,我收到一条消息

警告 LNK4033:将对象格式从 OMF 转换为 COFF

该库按预期工作,但我一直想知道这些二进制格式之间有什么区别,或者我是否应该期望这种转​​换会产生一些丑陋的东西。

4

1 回答 1

16

答案从“MetaWINDOW FAQ - OMF vs COFF Object File Formats.htm”中剔除

自 PC 文明诞生以来,直到 Microsoft Win32 编程工具出现时,几乎所有 PC 编译器都使用英特尔对象模块格式 (OMF) 标准生成对象文件。后来,英特尔推出了 386 处理器和 32 位保护模式,此时他们还扩展了 32 位的 OMF 规范,导致“OMF-386”成为大多数 PC 保护模式环境的标准。大约在同一时间,最初的 Windows NT 开发团队也在设计代码,不仅针对英特尔处理器,还支持其他供应商的处理器。Microsoft NT 团队选择了一种更便携的对象模块格式,称为通用对象文件格式 (COFF),它源自 UNIX System V 的官方对象代码格式。

正如有 OMF 和 COFF 格式的对象文件 (.obj's) 一样,也有 OMF 和 COFF 格式的库文件 (.lib's)。幸运的是,这些库基本上只是目标文件的集合,以及一些头信息,这些信息使链接器可以确定要从库中使用哪些目标文件。然而,为了让事情变得困难,OMF 和 COFF 都使用相同的文件扩展名,.obj 和 .lib,来引用两种不同类型的对象和库文件格式(因此,您不能只查看文件扩展名来判断目标模块或库文件是 OMF 还是 COFF)。

混合来自不同编译器供应商的目标文件和库文件的问题在于,一些供应商支持 COFF,其他供应商使用 OMF,而少数供应商可以同时处理这两者。例如,Borland 仍然使用 OMF 目标文件和库,而 Microsoft 的 32 位编译器生成 COFF 格式文件。在编译和链接 Windows 应用程序时,Watcom C/C++ v11.0 似乎更喜欢 COFF,但会生成 OMF 对象文件以用于其 DOS4GW 32 位保护模式 DOS 扩展程序。除此之外,Microsoft MASM 6.13 默认生成 OMF 文件,但使用 /coff 开关可以改为发出 COFF 对象文件。

当需要链接不同格式的文件时,不同的链接器会做不同的事情。例如,Microsoft Visual C/C++ 链接器是为 COFF 格式的目标文件和库而设计的,但会在必要时尝试将 OMF 目标文件转换为 COFF 文件。这在某些情况下有效,但不幸的是 Microsoft LINK 不支持所有 OMF 记录类型,因此在许多情况下,当给定 OMF 格式的目标文件时,链接器仍可能失败。此外,虽然 Microsoft LINK 尝试对 OMF 对象文件提供一些支持,但它会拒绝处理任何 OMF 格式库。其他链接器,例如 Borland 的 TLINK,是为 OMF 目标文件设计的,同样会拒绝使用 COFF 格式的目标文件或库文件。一些 DOS 扩展器和嵌入式系统供应商,例如 Phar Lap,提供自己的链接器,支持 OMF 和 COFF,

底线是混合 OMF 和 COFF 对象和库文件类型可能是一团糟(加上来自链接器的神秘错误消息无济于事)。除非您的链接器特别支持它,否则您应该坚持为您的编译器/链接器/平台推荐的对象和库格式,并避免混合 OMF 和 COFF 文件。

于 2009-06-08T19:59:55.877 回答