BIOS INT 10, AH=0E在引导加载程序第二阶段的异常行为
这种在预期字符串前出现乱码的情况,大多是因为程序误读取了内存中的垃圾数据,结合你的开发场景,我给你几个具体的排查和修复方向:
检查字符串的终止符是否正确
确保你的loading_message是以空字节(0x00)结尾的。如果没有这个终止符,print_string函数会一直往后读取内存,直到碰到0为止,这就会把前面的垃圾数据打出来。比如你的定义应该是:loading_message db 'Loading...', 0你可以检查下stage2.asm里是不是漏了这个结尾的0。
验证Stage2的加载地址与内存初始化
实模式下,BIOS会在内存中留下一些残留数据,比如0x7c00是Stage1的位置,如果你把Stage2加载到0x7e00,建议在Stage2执行打印前,先把加载区域的内存清零。比如加一段简单的循环:; 假设Stage2加载到0x7e00,要清零的内存范围是0x7e00到0x7fff mov ax, 0x7e0 mov es, ax xor di, di mov cx, 0x200 ; 512字节,对应1扇区的大小 mov al, 0 rep stosb这样能确保要使用的内存区域没有垃圾数据。
检查段寄存器的设置是否正确
实模式下,内存地址是段寄存器值 * 16 + 偏移,如果你的DS/ES段寄存器设置不对,访问loading_message时会取到错误的内存位置。比如如果Stage2加载到物理地址0x7e00,那DS应该设置为0x7e0(因为0x7e0*16=0x7e00),这样偏移地址才能正确指向字符串。你可以在Stage2开头加上:mov ax, 0x7e0 ; 根据你的实际加载地址调整这个值 mov ds, ax mov es, ax确认编译链接过程没有生成多余数据
检查你的Makefile,确保Stage2被编译成纯二进制文件,没有ELF头或者其他多余的头部信息。比如用nasm编译时,要指定-f bin参数:stage2.bin: stage2.asm nasm -f bin stage2.asm -o stage2.bin如果用了其他格式(比如elf32),链接后生成的文件开头会有额外的字节,这些就是你看到的乱码来源。
检查Stage1加载Stage2的扇区数是否正确
确保Stage1读取的扇区数正好是Stage2的大小,如果读多了,会把磁盘上的垃圾扇区数据加载到内存里,也会导致乱码。比如如果Stage2是1扇区(512字节),那Stage1里的读扇区指令要设置cx为1。
你可以先从检查字符串终止符和段寄存器设置开始,这两个是这类问题最常见的诱因。
内容的提问来源于stack exchange,提问作者Ryan Jones

