添加汇编代码后显示字符串被截断的16位迷你OS技术求助
嘿,这个问题我之前帮朋友排查过类似的,大概率是引导扇区大小限制或者内存覆盖的问题,咱们一步步来分析解决:
可能的原因与解决方法
1. 引导扇区大小超出512字节限制
MBR引导扇区必须严格是512字节,最后两个字节固定为0xAA55。如果新增代码后,你的bootloader(不含签名)的大小超过了510字节,汇编器或镜像写入工具会自动截断内容,导致字符串或后续代码被砍掉。
排查方法:
- 用NASM生成列表文件查看字节数:
打开nasm -l boot.lst boot.asm -f bin -o boot.binboot.lst,看最后一行的地址减去起始地址(一般是0x7C00),结果就是代码的字节数,必须≤510。 - 直接查看bin文件大小:
输出必须是512,否则就是超了。wc -c boot.bin
解决方法:
- 精简代码,把非必要逻辑移到内核(内核可以放在后续扇区,bootloader只负责加载内核);
- 用更精简的汇编指令替代冗余指令(比如用
xor ax,ax代替mov ax,0,前者更短); - 确保
times 510 - ($ - $$) db 0x00这条语句正确填充空字节,让代码+字符串的总长度刚好到510字节,再加上0xAA55签名凑满512字节。
2. 字符串内存区域被意外覆盖
新增的代码可能不小心修改了字符串所在的内存位置:
- 新增的变量、栈操作(
push/pop)占用了字符串的地址; - 代码段和字符串放在同一段,新增代码后字符串的位置被指令覆盖;
- 初始化寄存器时误写了字符串所在的内存。
排查方法:
- 把字符串放在代码段的末尾,靠近
0xAA55签名的位置,这样新增代码时不容易覆盖到; - 用QEMU调试功能查看内存:启动QEMU时加
-s -S,用GDB连接后,查看字符串指向的内存地址,确认内容是否完整。
解决方法:
- 显式固定字符串的位置,比如:
org 0x7C00 ; 你的bootloader代码... ; 把字符串放在代码最后 welcome_str db 'Welcome to my OS!', 0x00 ; 自动填充空字节到510字节 times 510 - ($ - $$) db 0x00 dw 0xAA55
3. 打印函数的依赖被破坏
如果新增代码修改了打印函数依赖的寄存器(比如bx、si,或者ah里的中断号),或者字符串的终止符0x00被覆盖,都会导致打印提前停止。
排查方法:
- 检查打印函数的实现,比如常见的16位打印逻辑:
确保调用这个函数前,print_str: mov ah, 0x0E ; BIOS teletype输出功能 print_char: lodsb ; 从si指向的地址取字符到al cmp al, 0x00 ; 判断是否到字符串结尾 je print_done int 0x10 ; 调用BIOS中断 jmp print_char print_done: retsi指向正确的字符串,且ah的值没有被新增代码修改; - 用GDB查看字符串内存,确认最后一位是
0x00终止符。
解决方法:
- 在调用打印函数前,保存和恢复关键寄存器,比如:
push ax push si mov si, welcome_str call print_str pop si pop ax - 确保字符串的
0x00终止符没有被误删或覆盖。
4. 软盘镜像写入错误
如果新增代码后,没有正确把更新后的boot.bin写入软盘镜像,也可能导致旧代码被运行(不过这个情况一般不会出现截断,但也可以排查):
解决方法:
- 用
dd写入时加上conv=notrunc参数,避免截断镜像:dd if=boot.bin of=floppy.img bs=512 count=1 conv=notrunc - 直接用QEMU加载
boot.bin测试:qemu-system-i386 boot.bin,排除镜像的问题。
内容的提问来源于stack exchange,提问作者Joker
相关产品推荐
相关产品推荐

