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
调用的时候也要使用这个修饰后的名字。但这种方法依赖于特定编译器的修饰规则,换个编译器可能就失效了,所以优先推荐方案一。
额外注意事项
如果是内核开发场景,编译链接时还要注意架构和编译选项:
- 编译C++文件时,可能需要添加
-ffreestanding -m32(针对32位内核)等参数,告诉编译器这是无操作系统环境的代码:g++ -c kernel.cpp -o kernel.o -ffreestanding -m32 - 编译NASM文件时,要指定对应的目标格式(比如32位ELF):
nasm -f elf32 start.asm -o start.o - 链接时要指定正确的架构和入口点(比如通过链接脚本
link.ld):ld -m elf_i386 -T link.ld start.o kernel.o -o kernel.bin
内容的提问来源于stack exchange,提问作者Ondřej Langr
相关产品推荐
相关产品推荐

