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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:43:29