Bootloader混合C与汇编开发:调用C函数遇未定义引用错误求助
汇编调用C函数时出现未定义引用错误的解决
问题背景及代码
我是操作系统开发新手,第一次尝试用C和汇编混合开发OS,但在汇编代码调用C函数时遇到了未定义引用错误。相关代码和编译报错如下:
boot.asm
BITS 32 global start extern dmain start: call dmain jmp $ times 510 - ($- $$) db 0 dw 0xAA55
main.c
#define NULL 0 void clear(); void clear() // 清空整个屏幕 { char *mem = (char*)(0xb8000); while (*mem != NULL){ *mem = NULL; mem++; } } void dmain(void *mbr, unsigned int magic) { clear(); }
Makefile
main: gcc -m32 -ffreestanding -c main.c -o main.o nasm -f win32 boot.asm -o boot.o ld -m i386pe -T NUL -o main.tmp -Ttext 0x100000 boot.o main.o objcopy -O binary main.tmp main.img qemu-system-x86_64 main.img
编译报错
gcc -m32 -ffreestanding -c main.c -o main.o nasm -f win32 boot.asm -o boot.o ld -m i386pe -T NUL -o main.tmp -Ttext 0x100000 boot.o main.o boot.o:boot.asm:(.text+0x1): undefined reference to `dmain' make: *** [Makefile:4: main] Error 1
问题原因及修复方案
报错核心是Windows PE格式的符号命名规则与汇编、编译器的符号不匹配:用gcc -m32编译C代码时,生成的符号会自带下划线前缀(比如dmain会变成_dmain),但汇编代码直接引用dmain,再加上使用win32格式的目标文件和PE链接器,最终导致符号查找失败。同时代码还存在内存布局和逻辑错误,以下是完整修复步骤:
统一目标文件格式为ELF(更适合OS开发)
把nasm输出格式改为elf32,链接器使用i386 ELF格式,同时修正MBR的加载地址为标准的0x7c00(之前的0x100000不符合MBR运行逻辑)。修改后的Makefile:main: gcc -m32 -ffreestanding -c main.c -o main.o nasm -f elf32 boot.asm -o boot.o ld -m elf_i386 -Ttext 0x7c00 -o main.tmp boot.o main.o objcopy -O binary main.tmp main.img qemu-system-x86_64 main.img修复C代码的逻辑错误
原clear函数的循环判断逻辑错误(显存区域不一定会出现0值),且汇编调用dmain时未传参,需调整函数参数和循环逻辑:#define NULL 0 void clear(); void clear() // 清空整个屏幕 { char *mem = (char*)(0xb8000); // 80列×25行,每个字符占2字节,共4000字节 for (int i = 0; i < 4000; i++) { mem[i] = 0; } } void dmain() { // 移除未传递的参数,避免栈不匹配 clear(); }验证修复
重新执行make,若编译无报错,QEMU启动后会显示黑屏(屏幕已被清空),说明代码正常运行。
内容的提问来源于stack exchange,提问作者Federico Occhiochiuso
相关产品推荐
相关产品推荐

