Search code examples
assemblyx86dosinterrupt-handling

Find a free interrupt slot


Some joker (BIOS/DOS/TSR...) has written random data in the Interrupt Vector Table. I know this because disassembling told me so.

Ordinarily before seizing an interrupt vector, I verify that the selected IVT slot is empty. But with all this left-behind-data, how can an humble application know that it is nonetheless safe to hook a particular interrupt vector?

Although my programmer's reference describes the DOS function 25h SetInterruptVector as

"Safely modifies an interrupt vector to point to a specified interrupt handler"

I don't think it cares too much about this pre-existing bogus content. So far for safely!


Is there some ingenious way to be absolutely sure that an interrupt vector is free?


Solution

  • No, there is no ingenious absolutely sure way to check if a vector is free.

    This is because every of the possible 232 values for an interrupt is potentially a valid value.

    Some value can be very suspicious, yet valid:

    • 0ffffh:0ffffh can be valid (pointing to 0ffefh with the A20 masked).
    • 0000h:0000h can be valid, even on vector 0. A DWORD of value zero decodes to a pair of add [bx+si], al which are valid.
    • 0b800h:0000h and other similar ROM addresses can be valid as expansion ROMs can be used to carry code. Though it's unlikely that the standard video memory will.
    • Addresses in reserved BIOS areas, like (E)BDA, can be valid in theory if the data is specially crafted to be both valid code and valid info.

    Of course some of the above are very stretched and involve having data executed as code, but the main reason you should not trust vector pointers is that the BIOS is likely to fill every vector slot with at least a dummy ISR.
    This won't let an unintentionally bad crafted int instruction hang the system.


    There are a couple of things you could do:

    1. Chaining
      Pick a not overcrowded interrupt number N. Pick up a set of input values I not yet used (say AH=d0-ff). Attach your ISR to N and handle only those I values, delegating the other inputs to the previous ISR.

    2. Target a specific platform
      Some interrupt vectors, like int EA, are used only in specific systems. Since most of those systems are gone, you can reclaim their interrupts.
      If you steal an interrupt vector and everything keeps working and nobody is complaining, then it's your interrupt. Just double check the premises.

    3. Use interrupt 2F
      The Int 2F and its variant Alternate Multiplex Interrupt Specification (AMIS) at Int 2D can be used as a shared/multiplexed interrupt.
      The AMIS did not gain much popularity however.

    4. Try to find an empty spot anyway
      As a first attempt you can try to search for null entries1 in the IVT, though valid in theory, they are likely empty slots.
      You can also try to find a pointer that is present more than one or two times, suggesting the presence of a dummy ISR (as an ISR cannot identify its vector number easily).

    I would go with n. 1 personally, if not possible I would implement n. 3. If not possible I would use n. 4 with fallback to n. 2.


    1 Catching all the "suspicious" values is impractical and would only give a little gain, so just shoot for the big ones.