如何在DOS汇编中重置标准输出,实现计数器更新时的屏幕内容覆盖?
解决DOS汇编图形模式下计数器覆盖显示问题
嘿,这个问题我太熟了!我之前做DOS汇编项目的时候也踩过这个坑😆
问题根源
你当前的代码用int 21h ah=02h输出字符时,DOS会自动把光标移到下一个位置,而且不会清除之前已经显示的字符。所以每次计数器递增后,新数字会追加在上一次输出的末尾,旧字符还留在屏幕上,最终就变成了0→01→012→0123...的叠加效果。
解决方案
因为你提到是在图形模式下,更合适的方式是用BIOS的int 10h图形模式中断来控制输出位置,直接在固定区域覆盖旧内容。下面给你两种可行的修改方案:
方案1:基于原代码的文本模式兼容修改(快速适配)
如果你的项目其实是文本模式(或者兼容文本模式的图形模式),可以通过定位光标+覆盖空格的方式解决:
- 先定义变量保存计数器的起始显示位置:
; 保存计数器显示的起始光标位置(行和列) cursor_row db ? cursor_col db ?
- 在第一次打印计数器前,获取当前光标位置并保存:
mov ah, 03h ; BIOS中断:获取光标位置 xor bh, bh ; 指定页号为0 int 10h mov cursor_row, dh ; 保存行号 mov cursor_col, dl ; 保存列号
- 修改你的
multiDigPrint函数,每次打印前先回到起始位置,用空格覆盖旧内容:
multiDigPrint proc push ax push bx push cx push dx ; 步骤1:移回计数器的起始光标位置 mov ah, 02h xor bh, bh mov dh, cursor_row mov dl, cursor_col int 10h ; 步骤2:打印足够多的空格覆盖旧数字(假设最多5位,可按需调整) mov cx, 5 mov dl, ' ' mov ah, 02h clear_old: int 21h loop clear_old ; 步骤3:再次移回起始位置,准备打印新数字 mov ah, 02h xor bh, bh mov dh, cursor_row mov dl, cursor_col int 10h ; --- 以下是你原来的打印逻辑 --- mov cx,0 mov dx,0 mov ax,[counter] PushNumber: cmp ax,0 je PrintNumber mov bx,10 div bx push dx inc cx xor dx,dx jmp PushNumber PrintNumber: cmp cx, 0 je PrintZero pop dx add dx,48 mov ah,02h int 21h loop PrintNumber jmp exit_mdg PrintZero: mov dx, 48 mov ah, 2h int 21h exit_mdg: pop dx pop cx pop bx pop ax ret multiDigPrint endp
方案2:图形模式专用方案(更规范)
如果是纯图形模式,int 21h的文本输出可能不太适配,推荐用BIOS的int 10h ah=13h直接在指定位置打印字符串,自动覆盖旧内容:
- 定义一个缓冲区用来存放转换后的数字字符串:
num_buf db 5 dup(0) ; 最多存储5位数字的缓冲区
- 重写打印函数,先把数字转成ASCII字符串,再用图形模式中断打印:
multiDigPrint proc push ax push bx push cx push dx push si mov ax, [counter] mov si, offset num_buf + 4 ; 从缓冲区末尾开始填充(逆序) mov bx, 10 xor cx, cx ; 记录数字位数 ; 步骤1:把计数器数值转换成ASCII字符串(逆序存入缓冲区) convert_num: xor dx, dx div bx ; ax = ax / 10, dx = ax % 10 add dl, '0' ; 转成ASCII字符 mov [si], dl dec si inc cx cmp ax, 0 jne convert_num inc si ; 调整指针到第一个有效数字的位置 ; 步骤2:用BIOS图形中断在固定位置打印字符串 mov bh, 0 ; 页号0 mov dh, 10 ; 打印起始行(可按需修改) mov dl, 20 ; 打印起始列(可按需修改) mov ah, 13h ; BIOS中断:打印字符串 mov al, 0 ; 模式0:光标停在字符串开头,属性存在bl中 mov bl, 07h ; 显示属性:黑底白字(可按需修改为你的图形模式属性) int 10h exit_mdg: pop si pop dx pop cx pop bx pop ax ret multiDigPrint endp
注意事项
- 如果你用的是VGA等图形模式,
int 10h的参数可能需要根据具体模式调整(比如行/列的范围、属性字节的含义)。 - 方案2中,打印的行和列可以根据你的游戏界面需求自由调整,只要固定这个位置,每次打印就会自动覆盖之前的数字。
内容的提问来源于stack exchange,提问作者starfi
相关产品推荐
相关产品推荐

