汇编global与extern使用问题:Bootloader跨文件调用输出异常
问题原因及解决方案
核心错误点
错误使用64位目标文件格式编译16位代码
你用nasm -f elf64编译16位Bootloader代码,生成的是64位ELF目标文件,其中的指令编码是针对64位模式的。而Bootloader运行在16位实模式下,CPU无法正确解析这些64位指令,比如call printc会被编译成64位调用指令,执行时直接出错。链接时未指定16位模式
默认ld链接elf64文件会生成64位可执行程序,即使指定了-Ttext=0x7c00,也不会生成16位兼容的代码段,导致实模式下无法正常运行。多文件链接时引导扇区填充计算错误
原代码中的times 510 - ($-$$) db 0里,$$是单个目标文件的起始地址,而非整个程序的起始地址,链接后会导致填充长度错误,引导签名0xaa55无法落在正确的位置(第511、512字节),影响BIOS引导。
修复步骤
1. 改用32位ELF格式编译
使用elf32格式编译,配合后续链接时的16位模式指定,生成兼容16位实模式的目标文件:
nasm -f elf32 start.asm -o start.o nasm -f elf32 print.asm -o print.o
2. 使用链接脚本控制程序布局
创建boot.ld链接脚本,明确指定程序起始地址、16位代码段布局,以及引导扇区的填充和签名:
ENTRY(_start); SECTIONS { . = 0x7c00; .text : AT(0x7c00) { *(.text); /* 填充到510字节,插入引导签名 */ . = ALIGN(1); FILL(0); . = 0x7c00 + 510; SHORT(0xaa55); } }
3. 链接生成可执行文件
用ld指定32位ELF模式并加载链接脚本:
ld -m elf_i386 -T boot.ld start.o print.o -o printer.elf
4. 转换为原始二进制文件
objcopy -O binary printer.elf printer.bin
5. 运行测试
qemu-system-x86_64 -drive format=raw,file=printer.bin
为什么%include能正常工作?
使用%include时,所有代码会被合并到单个源文件中,如果你之前是用nasm -f bin直接编译成16位原始二进制文件,生成的代码完全符合实模式要求,不存在目标文件格式不兼容和链接布局的问题,因此可以正常运行。
内容的提问来源于stack exchange,提问作者Junior Ohanyere
相关产品推荐
相关产品推荐

