【问题标题】:How do I link an object file generated from C code, a static library and a NASM generated object file?如何链接从 C 代码生成的目标文件、静态库和 NASM 生成的目标文件?
【发布时间】:2018-10-06 02:30:45
【问题描述】:

我正在开发一个程序(用于实实模式),该程序由引导加载程序加载到内存中的地址并跳转到该地址并开始执行该程序。问题是我将项目分成两个文件:a.asm(16 位 asm,NASM 语法)和 bc(我用 gcc for dos (djgpp) 编译)。此外,b.c 使用了 allegro 库中的一些函数(我将它作为静态库,.a)。

我的问题是,如何编译和链接这 3 个文件?我的第一个想法是:

  1. 用 gcc(带有 -c 标志)编译和组装 b.c,结果我得到一个 b.o 文件
  2. a.asm 与 NASM(-fbin 或.. ?)组装并得到 a.o
  3. 链接 b.oa.oallegro.a 以获得纯二进制文件(无 .exe 标头, 没有调试信息等)

我尝试了上面的方法,但是在第3步,链接器抛出一个错误,说ao的格式(NASM生成的目标文件)无法识别,这可能是因为要么我在组装文件时没有调用正确的标志和选项,要么..

我想要一些关于如何解决这个问题的指导。

谢谢。

【问题讨论】:

  • 你不想要-f bin。您想要使用的任何目标文件格式。可能是-f coff。见nasm -hf
  • @Jester 我使用了 -fcoff,我得到“coff 格式不支持非 32 位重定位。”
  • djgpp 生成 32 位代码,无法以您期望的方式链接到 16 位代码。它生成的代码通常需要 DOS,Allegro 库也需要。我的建议只是使用 FreeDOS 作为“引导加载程序”,并将启动程序的命令放在 AUTOEXEC.BAT 文件中。

标签: c assembly linker dos real-mode


【解决方案1】:

DJGPP生成的.o文件包含32位(i386)代码,不能直接从16位代码调用。

在 DOS 下,32 位代码通常使用 DOS extender 运行,它切换到 32 位保护模式,设置内存映射和 DOS API 转换(即切换回 16 位实数的小型蹦床函数调用 int 21h DOS API 时的模式)。然后加载并调用 32 位代码。

用于在 16 位和 32 位模式之间切换的 DOS 扩展器的轻量级替代品:

  • unreal modegcc -m16 (.code16gcc)。有关 gcc -m16 的更多详细信息,请参阅 this answer 和其他答案。

  • Syslinux 项目的引导加载程序,包含 16 位汇编 (NASM)、32 位汇编 (NASM) 和 32 位 C (GCC) 代码,并在它们之间切换。

要将 16 位和 32 位代码链接在一起,您可以运行 objcopy -O binary func.o func.bin(32 位),然后将 %incbin "func.bin" 添加到您的 16 位 NASM 源文件中。但是,这会破坏重定位(因此您将无法使用全局变量)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    相关资源
    最近更新 更多