编写引导加载器遇E2028错误:small_code未定义引用如何解决?
解决引导加载器编译时
small_code未定义引用的问题 步骤1:修复C代码的死循环bug
你的STRLEN_函数存在指针未递增的问题,会导致程序运行时死循环,先修正这个逻辑:
int STRLEN_(const char *str) { int len = 0; while (*str != '\0') { len++; str++; // 新增指针递增操作 } return len; }
步骤2:解决small_code未定义引用错误
这个错误是Watcom C在Tiny内存模型下编译时,会引用small_code段符号,而你使用nodefaultlibs跳过了标准库链接导致的,有两种解决方式:
方式一:在汇编代码中定义small_code别名
在StartPoint.asm的.code段前添加以下代码,将small_code映射到Tiny模型共用的CODE段:
small_code equ CODE
方式二:调整C编译选项避免依赖
修改C编译命令,添加-zn选项禁用段别名,同时移除可能干扰符号的-s选项:
wcl.exe -v -mt -zn -c -bt=dos -fo=main.obj main.c
步骤3:修正链接配置,生成符合引导扇区要求的二进制文件
你当前生成的是DOS COM格式文件,但引导扇区需要512字节原始二进制且末尾必须带有0xAA55签名,调整流程如下:
- 链接生成临时可执行文件:
.\VC152\wlink.exe file "StartPoint.obj" file "main.obj" name temp.exe format dos option nodefaultlibs option quiet
- 转换为原始二进制:
使用Watcom的wobjcopy工具转换格式:
.\VC152\wobjcopy.exe -O binary temp.exe bootloader.bin
- 截断并添加引导签名:
用dd工具(Windows可通过Git Bash/WSL运行)将文件截断为512字节,并写入末尾签名:
dd if=bootloader.bin of=bootloader.mbr bs=512 count=1 conv=notrunc printf '\x55\xAA' | dd of=bootloader.mbr bs=1 seek=510 count=2 conv=notrunc
额外注意事项
- 确保代码总大小不超过510字节(预留2字节签名),可添加
-O2编译选项开启优化缩减体积; - 测试可使用QEMU虚拟机:
qemu-system-i386 -fda bootloader.mbr
内容的提问来源于stack exchange,提问作者Артем Соколов
相关产品推荐
相关产品推荐

