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
相关产品推荐
相关产品推荐

