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

FreeDOS下16位汇编程序print *指令失效问题求助

问题:FreeDOS下Debug编写的16位汇编程序输入1不打印'*'

问题概述

用FreeDOS的Debug工具编写了一个16位汇编程序,预期行为:

  • 显示? 提示并接收一位整数输入
  • 输入0或大于1的数字时,程序直接终止
  • 输入1时,换行、打印*、再次换行后终止

实际运行时,输入1后仅完成换行,未打印*。已在FreeDOS虚拟机和MacOS的DOSBox-x(2024.07.01版本)中验证,结果一致。


相关文件与操作

源文件prinst.txt

a 100
mov ah,02  ; prepare for print
mov dl,3f  ; set '?'
int 21     ; print '?'
mov dl,20  ; set ' '
int 21     ; print ' ', hence generate the '?(space)' prompt.
mov ah,01  ; prepare for saving user input
int 21     ; ask user input. The input saved in al.
mov ah,02  ; prepare for print
mov dl,0d  ; set LF
int 21     ; print LF
mov dl,0a  ; set CR
int 21     ; print CR, hence generate new line
cmp al,30  ; compare user input in al, with '0'
je 012e    ; if equal jump to address 0126 (e.g. int 20)
cmp al,31  ; compare input with '1'
jne 012e   ; if input != '1', jump to address 0126
mov ah,02  ; prepare for print
mov dl,2a  ; set the symbol to print, e.g. '*'
int 21     ; print '*'
mov dl,0d  ; set LF
int 21     ; print LF
mov dl,0a  ; set CR
int 21     ; print CR, hence generate new line
int 20

n prinst.com
rcx
30
w
q

汇编命令

C:\>debug <prinst.txt> prinst.lst

生成的列表文件prinst.lst

-a 100
0DAB:0100 mov ah,02  ; prepare for print
0DAB:0102 mov dl,3f  ; set '?'
0DAB:0104 int 21     ; print '?'
0DAB:0106 mov dl,20  ; set ' '
0DAB:0108 int 21     ; print ' ', hence generate the '?(space)' prompt.
0DAB:010A mov ah,01  ; prepare for saving user input
0DAB:010C int 21     ; ask user input. The input saved in al.
0DAB:010E mov ah,02  ; prepare for print
0DAB:0110 mov dl,0d  ; set LF
0DAB:0112 int 21     ; print LF
0DAB:0114 mov dl,0a  ; set CR
0DAB:0116 int 21     ; print CR, hence generate new line
0DAB:0118 cmp al,30  ; compare user input in al, with '0'
0DAB:011A je 012e    ; if equal jump to address 012e (e.g. int 20)
0DAB:011C cmp al,31  ; compare input with '1'
0DAB:011E jne 012e   ; if input != '1', jump to address 012e
0DAB:0120 mov ah,02  ; prepare for print
0DAB:0122 mov dl,2a  ; set the symbol to print, e.g. '*'
0DAB:0124 int 21     ; print '*'
0DAB:0126 mov dl,0d  ; set LF
0DAB:0128 int 21     ; print LF
0DAB:012A mov dl,0a  ; set CR
0DAB:012C int 21     ; print CR, hence generate new line
0DAB:012E int 20
0DAB:0130 
-n prinst.com
-rcx
CX 0000  :30
-w
Writing 0030 bytes
-q

程序运行输出

C:\>prinst.com
? 0

C:\>prinst.com
? 1

问题原因与解决方法

核心问题

DOS系统中,换行需要先执行CR(回车,ASCII码0D)再执行LF(换行,ASCII码0A),原程序中顺序写反了。这会导致光标位置异常:输入后的换行操作实际是先换行再回车,光标回到上一行的开头,后续打印的*会被覆盖,或者输出到了不可见的位置。

另外,源文件中的跳转注释存在错误(注释写的是跳转到0126,实际是012e),但这不是功能异常的原因。

修改后的代码

调整换行指令的顺序,确保先CR后LF:

; 输入后的换行修正
mov ah,02  ; 准备打印
mov dl,0d  ; 设置CR(回车)
int 21     ; 执行回车
mov dl,0a  ; 设置LF(换行)
int 21     ; 执行换行,正确切换到新行

; 打印*后的换行也同步修正
mov dl,0d  ; 设置CR(回车)
int 21     ; 执行回车
mov dl,0a  ; 设置LF(换行)
int 21     ; 执行换行

完整修正后的prinst.txt

a 100
mov ah,02  ; 准备打印
mov dl,3f  ; 设置字符'?'
int 21     ; 打印'?'
mov dl,20  ; 设置空格
int 21     ; 打印空格,生成"? "提示
mov ah,01  ; 准备读取用户输入
int 21     ; 获取输入,存储到al寄存器
mov ah,02  ; 准备打印
mov dl,0d  ; 设置CR(回车)
int 21     ; 执行回车
mov dl,0a  ; 设置LF(换行)
int 21     ; 执行换行,切换到新行
cmp al,30  ; 比较输入与字符'0'
je 012e    ; 相等则跳转到程序终止
cmp al,31  ; 比较输入与字符'1'
jne 012e   ; 不等则跳转到程序终止
mov ah,02  ; 准备打印
mov dl,2a  ; 设置字符'*'
int 21     ; 打印'*'
mov dl,0d  ; 设置CR(回车)
int 21     ; 执行回车
mov dl,0a  ; 设置LF(换行)
int 21     ; 执行换行
int 20

n prinst.com
rcx
30
w
q

重新汇编运行后,输入1即可正确打印*并完成换行。


内容的提问来源于stack exchange,提问作者utobi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:24:54