GAS汇编开发bootloader时自定义print函数无输出问题排查
问题排查与修复方案
核心错误点
1. 字符串指针寄存器不匹配
你在main函数中将字符串地址存入了%ebx,但print函数中是从%rbp读取字符地址,根本没有访问目标字符串,自然无法输出预期内容。
2. BIOS中断参数被破坏
int $0x10的0x0e打印功能要求:
%ah固定为0x0e%al存储待打印字符%bh为显示页号(实模式下一般设为0)%bl为字符颜色(文本模式下默认0x07为黑底白字)
你将字符串地址存入%ebx,调用中断时%bh/%bl的值是地址的高低位,完全不符合中断参数要求,会导致输出失败。
3. 字符串无终止符
你用.ascii定义的字符串末尾没有添加0值,print函数是通过判断%al == 0终止打印的,会一直读取字符串后的随机内存内容,直到碰到随机0值才停止。
4. 编译链接参数错误
BIOS启动bootloader时处于16位实模式,默认as命令会生成32/64位代码,实模式下执行会出错;且bootloader会被BIOS加载到物理地址0x7c00,你链接时没有指定代码起始地址,所有符号(比如msg)的地址计算都是错误的。
5. 换行符不兼容
BIOS的0x0e打印功能不会自动处理\n为回车+换行,需要手动输出0x0d(回车)和0x0a(换行)才能实现正常换行。
修复方法
1. 修正编译链接命令
# 显式指定生成16位汇编代码 as --16 boot_main.s -o boot.o # 链接时指定代码起始地址为0x7c00,和BIOS加载位置一致 ld -o boot.bin --oformat binary -e main -Ttext 0x7c00 boot.o
2. 修正代码
boot_print.s
print: movb (%bx), %al cmpb $0, %al je print_end # 每次调用中断前重置参数,避免寄存器值干扰 movb $0x0e, %ah movw $0x0007, %bx int $0x10 inc %bx jmp print print_end: ret
boot_main.s
.code16 # 显式指定生成16位代码 .global main main: # 初始化段寄存器,消除BIOS残留值影响 xor %ax, %ax mov %ax, %ds mov %ax, %es movw $msg, %bx call print jmp . .include "boot_print.s" msg: .ascii "Hello, World!" .byte 0x0d, 0x0a # 显式添加回车换行 .byte 0 # 添加字符串终止符 .fill 510-(.-main), 1, 0 .word 0xaa55
内容的提问来源于stack exchange,提问作者wannastacksmash
相关产品推荐
相关产品推荐

