x86汇编中的定时器中断

时间:2017-01-17 23:47:46

标签: assembly x86 interrupt x86-16

我正在尝试编写一个程序,使用n*55ms停止INT 08h的执行,但到目前为止我还没有找到任何有用的东西。
我该如何使用此中断?

3 个答案:

答案 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有两种可能性 - 硬件或软件中断。目前尚不清楚你提到的问题是哪一个。