我正在尝试编写一个程序,使用n*55ms
停止INT 08h
的执行,但到目前为止我还没有找到任何有用的东西。
我该如何使用此中断?
答案 0 :(得分:3)
基本思路是获取此中断的现有IVT条目(0x000:0x0020处的四个字节)并将它们保存在某处,然后用中断处理程序的段和偏移量替换这四个字节。你的中断处理程序将被调用每秒18.2次,你的中断处理程序应该“跳远”到旧的中断处理程序(使用你最初保存的四个字节)。
完成后(例如,当你的程序退出到DOS或其他东西时),你将原始的四个字节恢复为0x000:0x0020。
对于n*55 ms
部分,您将全局变量设置为n+1
,并且您的中断处理程序将减少该全局变量。当全局变量减少到0时,您知道已经过的时间在n*55 ms
和(n+1)*55 ms
之间。
请注意,这种精度不足是由于安装中断处理程序和第一次发生IRQ之间的时间差异(例如,安装中断处理程序后立即发生计时器的IRQ,或者安装后最多55毫秒)你的中断处理程序)。如果您等待第一个计时器IRQ发生,然后让代码运行n*55 ms
,您可以在“完全”n*55 ms
之后停止代码。
此外,请确保您的中断处理程序保存它使用的所有寄存器(包括段寄存器)并在执行“jmp far”之前恢复它们。可以递减一个值并与零进行比较而不使用任何寄存器(因此可以避免保存和恢复您使用的寄存器,因为您没有使用任何寄存器)。例如(NASM):
interruptHandler:
sub word [cs:globalCounter],1
je .counterIsZero
jmp far [cs:oldInterruptHandler]
.counterIsZero:
答案 1 :(得分:2)
您可以通过INT 1Ah, AH=0服务或直接在内存地址int 08h
阅读0040h:006C
的输出。
; cx = "n" to wait "at least n*55ms", will modify cx
DelayProcedure:
push ax
push ds
mov ax,40h
mov ds,ax
; make sure that the delay will take "at least n*55ms"
; by waiting for first incomplete (<= 55ms) tick
mov ax,[6Ch]
.waitFirstForOneTickHappen:
nop
cmp [6Ch],ax
je .waitFirstForOneTickHappen
; remove the loop above to get "at most n*55ms" behaviour
; (which may be more practical for some situations, like animation syncing)
; wait "at most n*55ms" ticks
.waitNticks:
mov ax,[6Ch]
.waitForTick:
nop
cmp [6Ch],ax
je .waitForTick
loop .waitNticks
; restore ds, ax and return
pop ds
pop ax
ret
(我没有调试它,只是从头开始编写它,所以不能保证它会起作用)
另外,从电源使用的角度来看,将几个nops放入这些循环中会很好(比如4-8个)(再次cmp + je很可能像nop一样低功耗)现代x86)。
答案 2 :(得分:1)
您可以参考Ralph Browns Interrupt List获取INT 08h
的相关信息。
根据您的使用情况,您可以选择以下两种选择:
无论您的使用情况如何,这都可以解释得很清楚。
因此发生INT 08h
有两种可能性 - 硬件或软件中断。目前尚不清楚你提到的问题是哪一个。