c - 对主 ld 的 undefined reference

标签 c windows assembly ld

我正在尝试链接到文件 - 一个包含 main 函数的 c 文件和一个仅跳转到 main 的 asm 文件。

我已经安装了 mingw。 我的文件:

//kernel.c
void some_function(){
}
void main(){
char* video_memory = (char*) 0xb8000;
*video_memory = 'X';
some_function();
}

;kernel_entry.asm
[bits 32]
[extern main]
call main
jmp $

我调用构建的命令:

gcc -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f elf -o kernel_entry.o
ld -o kernel.bin -Ttext 0x1000 kernel_entry.o kernel.o

我遇到的错误:

kernel_entry.o:(.text+0x1): undefined reference to `main'
kernel.o:kernel.c:(.text+0xf): undefined reference to `__main'

编辑:

哪些命令有效:

ld -r -o kernel.out -Ttext 0x1000 kernel.o
objcopy -O binary -j .text kernel.out kernel.bin

当我尝试使用 -r 运行 ld 时,出现错误:

ld: Relocatable linking with relocations from format elf32-i386 (kernel_entry.o)
 to format pe-i386 (kernel.bin) is not supported

编辑2: 使用这些命令时我得到了最好的结果:

gcc -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f win32 -o kernel_entry.o
ld -r -o kernel.out -Ttext 0x1000 kernel_entry.o kernel.o
objcopy -O binary -j .text kernel.out kernel.bin

文件链接成功,但运行时,主函数永远不会被调用。 也尝试过coff格式,也能链接,但是Bochs一直重启。

最佳答案

第一个错误是因为在C中一个函数名为_name,所以你不能这样调用main,你必须调用_main >。在TASM中可以设置调用约定,这样汇编器就可以自动调用正确的函数,不知道nasm是否也有这样的功能。

第二个问题可能是,因为您直接调用链接器。在这种情况下,您必须指定 C 启动模块,该模块通常由编译器添加到链接器选项中。通常我认为这是一个名为 crt0 的文件。如果您编写自己的启动代码,则必须自己提供。该模块从操作系统特定的入口点设置 C 环境。我猜你的项目中缺少这个。

http://en.wikipedia.org/wiki/Crt0

关于c - 对主 ld 的 undefined reference ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18165891/

相关文章:

java - 等效于 Linux 上的数据保护 API

assembly - 入门教程 : Assembler, 段错误

c++ - 你能在 C++ 内联汇编中建议我更好的解决方案吗?

c++ - 在32位数字中查找第一个(最低)置位位置

c - 为什么++i ||++j &&++k 没有给出期望值

c - 单元测试 C 模块静态变量

c++ - 为什么返回浮点值会改变它的值?

c++ - 测试串口应用

c# - 从命令行关闭正在运行的程序

c++ - 在 free/malloc、外部内存 Hook 上花费了大量时间?