如何 link 从 C 代码生成的 object 文件、静态库和 NASM 生成的 object 文件?

How do I link an object file generated from C code, a static library and a NASM generated object file?

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

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

  1. 使用 gcc(使用 -c 标志)编译和 assemble b.c,结果我得到一个 b.o 文件
  2. Assemble a.asm 与 NASM (-fbin 或.. ?)并得到 a.o
  3. Link b.o, a.oallegro.a 得到一个纯二进制文件(没有 .exe headers, 没有调试信息等)

我尝试了上面的方法,但是在第 3 步,linker 抛出一个错误,指出 a.o 的格式(object 由 NASM) 生成的文件无法识别,这可能是因为我在组装文件时没有调用正确的标志和选项,或者..

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

谢谢。

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

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

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

  • unreal mode with gcc -m16 (.code16gcc). See this answer 和其他答案有关 gcc -m16.

    的更多详细信息
  • Syslinux项目的bootloader,包含16位汇编(NASM)、32位汇编(NASM)和32位C (GCC) 代码,并在它们之间切换。

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