TASM 8086中如何为int 16h(ah=1)实现限时按键输入?
解决DOS汇编中限时等待键盘输入的问题
问题分析
你用INT 16H (AH=1)的方式存在错误:这个功能只是检查键盘缓冲区是否有输入,不会阻塞等待,也不会把输入字符直接读到AL里(有输入时ZF=0,AH存扫描码、AL存ASCII码;无输入时ZF=1)。你之前的写法会直接把寄存器内的随机值存入INPUT[SI],而且要实现限时等待,不能直接调用会阻塞的INT 16H (AH=0),必须结合计时循环+键盘状态检查来实现。
实现思路
- 用BIOS时钟中断
INT 1AH记录初始时间(系统时钟每秒约产生18.2个滴答) - 循环中反复用
INT 16H (AH=1)检查键盘是否有输入 - 每次循环计算已流逝的时间,超过设定时长就终止等待
- 检测到输入时立即读取并存储,超时则标记无输入
修改后的代码
; 定义常量:限时20秒,对应时钟滴答数(20*18=360,取近似值) TIME_LIMIT EQU 360 GET_INPUT PROC FAR PUSH CX PUSH DX PUSH AX ; 记录初始时间:INT 1AH AH=0,CX:DX返回当前累计时钟滴答数 MOV AH, 0 INT 1AH MOV INIT_CX, CX MOV INIT_DX, DX ; 计时循环 WAIT_LOOP: ; 非阻塞检查键盘缓冲区 MOV AH, 1 INT 16H JNZ READ_INPUT ; ZF=0,检测到输入,跳转读取 ; 检查是否超时 MOV AH, 0 INT 1AH ; 计算时间差:当前CX:DX - 初始INIT_CX:INIT_DX SUB DX, INIT_DX SBB CX, INIT_CX ; 判断是否超过限时 CMP CX, 0 JG TIMEOUT ; CX>0,肯定超时 CMP DX, TIME_LIMIT JAE TIMEOUT ; DX>=TIME_LIMIT,超时 ; 短暂延时(可选,降低CPU占用) MOV AH, 86H MOV CX, 0 MOV DX, 50000 ; 延时约50ms INT 1AH JMP WAIT_LOOP READ_INPUT: ; 读取输入字符:INT 16H AH=0 MOV AH, 0 INT 16H MOV SI, TURN MOV INPUT[SI], AL JMP INPUT_EXIT TIMEOUT: ; 超时处理:存入特殊值表示无输入,这里用0 MOV SI, TURN MOV INPUT[SI], 0 INPUT_EXIT: POP AX POP DX POP CX RET GET_INPUT ENDP ; 需要提前定义的变量 INIT_CX DW ? INIT_DX DW ? TURN DW ? INPUT DB 2 DUP(?) ; 假设存储两位玩家的输入
代码说明
INT 1AH AH=0:读取系统累计时钟,CX:DX存储从午夜开始的滴答数,可用于计算时间差INT 16H AH=1:非阻塞检查键盘状态,不会卡住程序,适合在循环中反复调用INT 16H AH=0:真正读取键盘输入(会清空缓冲区),AL存储输入字符的ASCII码- 超时分支可根据需求调整标记值,比如用
0或其他特殊字符表示玩家未在限时内操作 - 可选的
INT 1AH AH=86H延时能减少循环对CPU的占用,避免资源浪费
内容的提问来源于stack exchange,提问作者Rober
相关产品推荐
相关产品推荐

