You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NASM调用外部C++函数报错:undefined reference to kernel_main

解决NASM调用C++函数时的"undefined reference to `kernel_main'"错误

这个错误的核心原因是**C的名字修饰(Name Mangling)**机制——C编译器会对函数名进行特殊编码,用来支持函数重载、命名空间等特性,导致编译后的函数符号名不再是你写的kernel_main,自然会让NASM找不到对应的引用。

下面给你两种靠谱的解决方案:

方案一:用extern "C"禁用C++名字修饰(推荐)

修改你的C++代码,给kernel_main加上extern "C"声明,让编译器按照C语言的规则导出这个函数,避免名字修饰:

extern "C" void kernel_main() {
    char* vidmem = (char*)0xb8000;
    /* 你的其他代码 */
}

这样编译后,函数的符号名就会保持kernel_main,和NASM里extern kernel_main的声明完全匹配,链接时就不会报错了。

方案二:直接使用C++修饰后的符号名(不推荐,兼容性差)

如果你不想修改C代码,可以先查看C目标文件里的实际符号名。比如用nm工具查看编译后的.o文件:

nm kernel.o

你会看到类似_Z11kernel_mainv这样的修饰后名称(不同编译器的修饰规则可能略有不同),然后修改NASM代码里的extern声明:

extern _Z11kernel_mainv

调用的时候也要使用这个修饰后的名字。但这种方法依赖于特定编译器的修饰规则,换个编译器可能就失效了,所以优先推荐方案一。

额外注意事项

如果是内核开发场景,编译链接时还要注意架构和编译选项:

  1. 编译C++文件时,可能需要添加-ffreestanding -m32(针对32位内核)等参数,告诉编译器这是无操作系统环境的代码:
    g++ -c kernel.cpp -o kernel.o -ffreestanding -m32
    
  2. 编译NASM文件时,要指定对应的目标格式(比如32位ELF):
    nasm -f elf32 start.asm -o start.o
    
  3. 链接时要指定正确的架构和入口点(比如通过链接脚本link.ld):
    ld -m elf_i386 -T link.ld start.o kernel.o -o kernel.bin
    

内容的提问来源于stack exchange,提问作者Ondřej Langr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:39:23