我无法理解使用int 1ah
导致延迟的此例程。我知道int 1ah
与系统时钟有关,但我不明白这个函数是如何使用的。
delay:
pusha
pushf
mov ah, 0
int 1ah
mov di, 30
mov ah, 0
int 1ah
mov bx, dx
wait:
mov ah, 0
int 1ah
sub dx, bx
cmp di, dx
ja wait
popf
popa
ret
为什么在这里使用注册表di
?我可以使用其他跳转指令代替ja
吗?如何计算延迟时间?
答案 0 :(得分:4)
delay:
pusha
pushf
将所有当前寄存器值保留为堆栈。
mov ah, 0
int 1ah
调用BIOS服务“1Ah,00”(返回cx:dx
=午夜以来的滴答数,al
=自上次呼叫后的午夜标志)。此调用的结果不会用于任何事情。
mov di, 30
di = 30
(有时会用来稍微延迟执行)。
mov ah, 0
int 1ah
再次拨打“1Ah,00”,刷新cx:dx
+ al
个结果。
mov bx, dx
将当前滴答计数低16b复制到bx
。
wait:
mov ah, 0
int 1ah
再次拨打“1Ah,00”,刷新cx:dx
+ al
个结果。
sub dx, bx
从新的低16b减去在循环之前存储的值。
cmp di, dx
将30与减法结果进行比较。
ja wait
如果结果是从0到29,它将跳转到wait
,对于30到65535,它将继续返回序列。即使对于例如bx = 65530
的情况,这种情况也很有效,并且计数器的低16b确实重置为0,由sub
计算的增量仍将从0稳步增长到30。
popf
popa
ret
恢复所有内容并返回。
所以这个程序将等待大约30个滴答(如果使用默认的DOS定时器速度,则为~1.65s)。
唯一一次可能等待意外数量的滴答声是在午夜左右,当返回的dx
突然跳转到0值时,并且在大多数情况下将触发延迟循环结束,所以在午夜延迟可能会被人为缩短。