最近我一直在维护一个用VC ++ 6.0编写的遗留项目。代码使用了这个编译器的许多独特特性,将它移植到更新的标准编译器已被证明是一项艰巨的任务。
在项目的数千行代码中,有四个汇编程序文件。由于某种原因,我不明白,MASM615和TASM也无法编译它们(它们发送错误),但我有目标文件。但是,当我链接库时,我收到一条消息
警告LNK4033:将对象格式从OMF转换为COFF
该库按预期工作,但我一直想知道这些二进制格式之间的区别是什么,或者我是否应该期望这种转换有些丑陋。
答案 0 :(得分:14)
从“MetaWINDOW常见问题解答 - OMF与COFF对象文件Formats.htm”中删除答案
自PC文明出现以来,直到微软Win32编程工具出现的时候,几乎所有PC编译器都使用英特尔对象模块格式(OMF)标准生成目标文件。后来,英特尔推出了386处理器和32位保护模式,此时他们还扩展了32位的OMF规范,导致“OMF-386”成为大多数PC保护模式环境的标准。大约在同一时间,最初的Windows NT开发团队也在设计代码,不仅适用于英特尔处理器,还支持其他供应商的处理器。 Microsoft NT团队选择了一种更便携的对象模块格式,即从UNIX System V的官方对象代码格式派生的通用对象文件格式(COFF).COFF对象模块后来成为所有Microsoft Win32开发工具的事实标准,并获得了在格式上更接近可移植可执行文件的优势 - Win32的本机可执行格式(COFF格式链接器从COFF文件创建32位EXE或DLL的工作少于从OMF格式文件创建的工作。)
正如OMF和COFF格式的目标文件(.obj)一样,还有OMF和COFF格式库文件(.lib)。幸运的是,这些库基本上只是目标文件的集合,还有一些头信息可以让链接器确定从库中使用哪些目标文件。但是,为了使事情变得困难,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文件。