使用1ah导致装配延迟的例程

时间:2017-07-23 21:44:15

标签: assembly x86 delay nasm

我无法理解使用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吗?如何计算延迟时间?

1 个答案:

答案 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值时,并且在大多数情况下将触发延迟循环结束,所以在午夜延迟可能会被人为缩短。