MS-DOS 6.22 Timer Interrupts: Using Interrupt 1Ch

This article explores how MS-DOS 6.22 manages periodic background execution through the system timer, focusing on the interplay between the hardware-level timer interrupt (INT 08h) and the software-exposed user timer interrupt (INT 1Ch). You will learn how the Intel architecture generates regular timing pulses, how the ROM BIOS cascades these events into INT 1Ch, and how MS-DOS applications and Terminate-and-Stay-Resident (TSR) programs safely hook this vector to execute time-critical tasks without disrupting the operating system.

The Hardware Foundation: PIT and INT 08h

MS-DOS 6.22 relies on the PC architecture's Intel 8253 or 8254 Programmable Interval Timer (PIT). The PIT operates at an input frequency of 1.193182 MHz. In standard DOS configurations, Channel 0 of the PIT is set to Mode 3 (square-wave generator) with a 16-bit divisor of 65,536 (0000h). This configuration triggers a hardware interrupt—Interrupt Request 0 (IRQ0)—approximately 18.2 times per second (roughly every 54.9 milliseconds).

When IRQ0 triggers, the Programmable Interrupt Controller (PIC 8259A) maps the request to CPU Interrupt 08h. The default handler for INT 08h resides within the system ROM BIOS.

The Delegation to Interrupt 1Ch

The BIOS INT 08h handler performs essential low-level housekeeping tasks on each tick:

  1. Increments a 32-bit tick counter at memory address 0040:006Ch in the BIOS Data Area (BDA).
  2. Checks for a 24-hour rollover (at tick 1,573,040) and updates the midnight rollover flag at 0040:0070h.
  3. Decrements the floppy drive motor shutoff counter.
  4. Executes a software interrupt: INT 1Ch.
  5. Sends the Non-Specific End of Interrupt (EOI) byte (20h) to the 8259 PIC at port 20h.
  6. Executes an IRET (Interrupt Return) instruction.

By default, the BIOS initializes the vector for INT 1Ch in the Interrupt Vector Table (located at 0000:0070h) to point directly to an IRET instruction, consuming no processing time if unused.

Why MS-DOS Uses INT 1Ch Instead of INT 08h

Interrupt 1Ch functions as a safe, user-accessible hook into the system's hardware clock cycle. Directly hooking the hardware timer at INT 08h requires an application to maintain accurate BIOS tick counters, manage drive motor timeouts, and manually signal the PIC with an EOI byte. Failure to handle any of these steps accurately destabilizes the PC.

By delegating execution to INT 1Ch, the BIOS ensures all system-critical timing updates occur before user-defined code runs. When an application hooks INT 1Ch, the BIOS retains ownership of the hardware acknowledge sequence, simplifying background scheduling.

Hooking INT 1Ch in MS-DOS 6.22

In MS-DOS 6.22, software intercepts INT 1Ch using standard DOS API services:

  1. Read Current Vector: The program invokes INT 21h, Function 35h with AL = 1Ch to obtain the existing handler's segment and offset (ES:BX).
  2. Store Original Vector: The program saves this address in local memory to preserve the chain of execution.
  3. Set New Vector: The program invokes INT 21h, Function 25h with AL = 1Ch and DS:DX pointing to the custom Interrupt Service Routine (ISR).

When the timer fires, the custom ISR executes, optionally calls the preserved original vector address, and concludes with an IRET.

Limitations and Re-entrancy in MS-DOS

Because INT 1Ch runs in an interrupt context 18.2 times per second, developers face strict limitations inside an INT 1Ch handler under MS-DOS 6.22:

  • Non-Reentrant DOS API: MS-DOS 6.22 is inherently single-threaded and non-reentrant. An INT 1Ch routine cannot safely execute standard INT 21h system calls (such as file I/O or console output) if the interrupted program was already inside an INT 21h routine.
  • The InDOS Flag: To bypass this limitation, TSRs monitoring INT 1Ch query the internal MS-DOS InDOS flag (retrieved via undocumented INT 21h, Function 34h). The ISR only invokes DOS services if the InDOS flag and the error-mode flag are both zero, confirming the OS is idle.
  • Execution Time: INT 1Ch code must execute rapidly. Lengthy processing starves subsequent timer ticks and delays other hardware interrupts, leading to degraded system performance or lost clock cycles.