You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何设置定时器?能否用指定汇编代码实现60秒定时功能?

DOS环境下定时器设置与汇编定时按键问题解答

嘿,我来帮你拆解这两个问题:

一、如何设置定时器?

在DOS/BIOS环境下(从你用的int 16h中断来看,应该是这个场景),常用的定时器实现方式有三种:

  • BIOS实时时钟中断法:调用int 1Ah中断获取系统从午夜开始的时钟滴答数(每秒约18.2次),通过记录起始时间、循环计算时间差来实现定时,这种方法精度适中,不需要操作硬件。
  • 硬件定时器(8253/8254)法:直接编程操作PC的可编程定时器芯片,设置计数初值并开启中断,当计数结束时触发定时事件,精度很高,但需要熟悉硬件寄存器操作。
  • 循环延时代码:通过空循环消耗CPU时间来模拟定时,这种方法最简单但精度极差,不同主频的CPU执行速度差异大,时间误差会很明显。

二、你给出的汇编代码能实现60秒定时+检测S键吗?

先把你的代码贴出来方便分析:

xor ah,ah
Enter_Again:
    xor ah, ah ; I should put 60 seconds here
    int 16h ; The user should press S before 60 seconds
    mov bl,al
    cmp al,"S"

很遗憾,这段代码完全做不到60秒定时的需求。原因很简单:当ah=0时调用int 16h,是BIOS的「阻塞式按键读取」——程序会卡在这一步,直到用户按下任意键才会继续执行,根本不会去计时。

要实现“60秒内按下S键”的功能,需要结合非阻塞按键检测定时逻辑,这里给你一个基于BIOS实时时钟的修改示例:

; 定义存储起始时间的变量
start_cx dw ?
start_dx dw ?

; 程序入口
start:
    ; 记录起始时钟滴答数(int 1Ah ah=0:获取系统时间,cx:dx为总滴答数,每秒约18.2次)
    mov ah, 00h
    int 1Ah
    mov [start_cx], cx
    mov [start_dx], dx

check_loop:
    ; 第一步:非阻塞检查是否有按键输入(int 16h ah=1:有按键则ZF=0,al存按键ASCII)
    mov ah, 01h
    int 16h
    jz check_timer ; 没按键,先检查时间

    ; 有按键,读取按键并判断是否是S
    mov ah, 00h
    int 16h
    cmp al, 'S'
    je success ; 按下S,跳转到成功逻辑

    ; 不是S,回到循环继续等待
    jmp check_loop

check_timer:
    ; 获取当前时间
    mov ah, 00h
    int 1Ah
    ; 计算时间差:当前cx:dx - 起始cx:dx
    sub dx, [start_dx]
    sbb cx, [start_cx]
    ; 60秒对应的滴答数约为 60*18.2065 ≈ 10924
    cmp cx, 0
    jne time_up ; cx不为0说明时间远超60秒
    cmp dx, 10924
    jge time_up ; 时间达到60秒,跳转到超时逻辑

    ; 时间还没到,回到循环继续检测
    jmp check_loop

success:
    ; 这里可以添加成功提示,比如调用int 21h显示字符串
    mov ah, 09h
    mov dx, offset success_msg
    int 21h
    jmp exit

time_up:
    ; 超时提示
    mov ah, 09h
    mov dx, offset timeout_msg
    int 21h

exit:
    ; 退出程序
    mov ah, 4Ch
    int 21h

; 定义提示字符串
success_msg db "恭喜!你在60秒内按下了S键!$"
timeout_msg db "超时啦!你没在60秒内按下S键...$"

这段代码的核心逻辑是:循环交替做两件事——非阻塞检查用户是否按了S,以及计算当前时间和起始时间的差值,一旦时间到60秒或者用户按下S,就跳出循环执行对应逻辑。

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

火山引擎 最新活动