咨询:旧DOS汇编应用重定向输入完成后切换回键盘输入的方法
修复DOS汇编程序输入重定向后挂起的问题
问题根源
当输入被重定向到文件时,DOS会将标准输入(stdin,句柄0)关联到该文件。文件读取到EOF后,程序若继续调用DOS 21h功能6(DL=0xFF)尝试读取输入,DOS不会自动将stdin切换回键盘——此时功能6会陷入等待(DOS仍认为stdin指向已读完的文件),导致程序挂起。
解决方案
1. 检测输入是否被重定向
在读取输入前,用DOS 21h功能0x44(IOCTL)子功能0x00获取stdin的设备属性,判断是否处于重定向状态:
; 检测stdin是否为重定向(句柄0) check_redirect: mov ah, 0x44 mov al, 0x00 ; 子功能0:获取设备信息 mov bx, 0x00 ; stdin句柄 int 0x21 jc redirect_error ; 调用失败,处理错误 test dl, 0x80 ; 设备属性第7位:1=文件/管道(重定向),0=字符设备(键盘) jz input_from_keyboard ; 此处为输入重定向状态,执行文件读取逻辑
2. 检测EOF并恢复stdin到键盘
当读取到文件EOF时(不同DOS版本返回值有差异,调试确认:部分版本功能6返回AL=0xFF且CF=0,部分返回CF=1),立即将stdin重新关联到键盘设备(CON):
; 恢复stdin到键盘 restore_stdin: ; 打开CON设备(键盘输入) mov ah, 0x3D mov al, 0x00 ; 只读模式 lea dx, con_device int 0x21 jc con_open_error ; 打开CON失败,处理错误 ; 将CON句柄复制到stdin(句柄0) mov ah, 0x46 mov bx, ax ; 源句柄:CON的句柄 mov cx, 0x00 ; 目标句柄:stdin int 0x21 jc handle_copy_error ; 关闭临时CON句柄(可选,DOS会自动管理,但关闭更规范) mov ah, 0x3E mov bx, ax int 0x21 ; 恢复完成,现在stdin指向键盘 jmp input_from_keyboard con_device db 'CON', 0 ; 键盘设备名
3. 调整输入读取逻辑
修改功能6的调用逻辑,在重定向状态下检测EOF:
read_input: mov ah, 0x06 mov dl, 0xFF ; 控制台输入 int 0x21 jc no_input ; 无输入(键盘未按键) ; 检查是否为EOF(重定向状态下) cmp al, 0xFF ; 适配部分DOS版本的EOF返回值 je restore_stdin ; 处理读取到的字符(原有业务逻辑) ; ... jmp read_input no_input: ; 键盘无输入时的等待/处理逻辑 ; ...
关键注意事项
- 不同DOS版本对EOF的返回值有差异,需通过调试确认你的运行环境中EOF的标识。
- 使用功能0x46复制句柄时,DOS会自动关闭原stdin指向的文件句柄,无需手动操作。
- 若程序需支持多次重定向,可提前保存原stdin句柄,恢复时切换回去;普通场景直接恢复到CON即可。
内容的提问来源于stack exchange,提问作者rfdes
相关产品推荐
相关产品推荐

