16位汇编Bootloader循环异常:仅能打印单个点无法输出一行点
你的Bootloader循环打印问题分析与修复
我看了你的16位汇编Bootloader代码,问题出在repeat子程序的逻辑上,咱们一步步拆解:
核心问题点
- 循环顺序完全搞反了:你把
loop repeat放在了int 21h前面,这会导致CPU先循环10次(每次cx减1,直到cx=0),最后才执行一次打印指令,自然只输出一个点。 - 用错了中断功能:你想用
int 21h的09h功能打印字符串,但这个功能要求字符串以$结尾,而你的square是0结尾的;更关键的是,Bootloader阶段DOS环境还没初始化,用DOS中断本来就不靠谱——你前面的writeString用的是BIOS的int 10h0Eh功能,应该保持一致。 - 参数设置错误:
mov dx, square是把字符串地址给dx,但09h功能需要的是ds:dx指向字符串,而且你要打印单个字符的话,根本不需要传地址,直接把字符加载到al里就行。
修复后的完整代码
[BITS 16] [ORG 0x7C00] top: ;; Put 0 into ds (data segment) ;; Can't do it directly mov ax,0x0000 mov ds,ax mov cx, 10 ; 设置循环打印10个点 mov si, Name call writeString mov si ,Course call writeString mov si, Student_num call writeString mov si, fav_movie call writeString call repeat ; 调用打印点的子程序 jmp $; Spin repeat: mov ah, 0x0E ; 复用BIOS teletype输出功能(和writeString一致) mov bh, 0x00 ; 页码0 mov bl, 0x07 ; 默认文本属性(黑底白字) print_dot: mov al, '.' ; 要打印的单个字符 int 0x10 ; 调用BIOS中断打印 loop print_dot ; cx减1,直到cx=0停止循环 ; 打印回车换行,和前面的输出格式对齐 mov al, 13 int 0x10 mov al, 10 int 0x10 ret writeString: mov ah,0x0E ; Display a character (as before) mov bh,0x00 mov bl,0x07 mov di,si nextchar: Lodsb ; Loads [SI] into AL and increases SI by one ;; Effectively "pumps" the string through AL cmp al,0 ; End of the string? jz done int 0x10 ; BIOS interrupt jmp nextchar done: ret Name db 'Petar',13,10,0 ; Null-terminated Course db '1234',13,10,0 Student_num db '123456789',13,10,0 fav_movie db 'GoT',13,10,0 times 510-($-$$) db 0 dw 0xAA55
修复细节说明
- 把
repeat改成用int 10h0Eh功能,和你之前的字符串打印逻辑统一,避免DOS中断的兼容性问题。 - 调整循环顺序:先打印一个点,再执行
loop指令减少计数,这样循环10次就会输出10个点。 - 补充了回车换行的打印,让点行和前面的内容格式保持一致。
- 删掉了原来错误的
int 21h调用和dx相关代码,简化逻辑同时保证可靠性。
内容的提问来源于stack exchange,提问作者Pepo Raev
相关产品推荐
相关产品推荐

