You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在DOS汇编中重置标准输出,实现计数器更新时的屏幕内容覆盖?

解决DOS汇编图形模式下计数器覆盖显示问题

嘿,这个问题我太熟了!我之前做DOS汇编项目的时候也踩过这个坑😆

问题根源

你当前的代码用int 21h ah=02h输出字符时,DOS会自动把光标移到下一个位置,而且不会清除之前已经显示的字符。所以每次计数器递增后,新数字会追加在上一次输出的末尾,旧字符还留在屏幕上,最终就变成了0→01→012→0123...的叠加效果。

解决方案

因为你提到是在图形模式下,更合适的方式是用BIOS的int 10h图形模式中断来控制输出位置,直接在固定区域覆盖旧内容。下面给你两种可行的修改方案:


方案1:基于原代码的文本模式兼容修改(快速适配)

如果你的项目其实是文本模式(或者兼容文本模式的图形模式),可以通过定位光标+覆盖空格的方式解决:

  1. 先定义变量保存计数器的起始显示位置:
; 保存计数器显示的起始光标位置(行和列)
cursor_row db ?
cursor_col db ?
  1. 在第一次打印计数器前,获取当前光标位置并保存:
mov ah, 03h   ; BIOS中断:获取光标位置
xor bh, bh    ; 指定页号为0
int 10h
mov cursor_row, dh  ; 保存行号
mov cursor_col, dl  ; 保存列号
  1. 修改你的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直接在指定位置打印字符串,自动覆盖旧内容:

  1. 定义一个缓冲区用来存放转换后的数字字符串:
num_buf db 5 dup(0)  ; 最多存储5位数字的缓冲区
  1. 重写打印函数,先把数字转成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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:13:16