INT 15h AH=86h returns after the given time has passed. CX:DX is a 32-bit count of microseconds, so one second is 1 000 000 = 000F4240h: CX = 000Fh, DX = 4240h. The BIOS programs the real-time clock to interrupt 1024 times a second (IRQ 8), counts the time down in that interrupt, and lets the caller wait with interrupts enabled, so the timer, the keyboard and the mouse keep working during the wait.

It is the simple way to pause independent of the CPU speed, where a counting loop would run ten times faster on a faster machine. The examples in this chapter use it to keep a picture on the screen for a moment before switching the video mode back.

prints: waiting one second... done (with a one-second pause before "done")
MOV DX, OFFSET WAITING1
MOV AH, 09h ; DOS: print the $-string at DS:DX
INT 21h
MOV CX, 000Fh ; CX:DX = 1,000,000 microseconds = 000F4240h
MOV DX, 4240h
MOV AH, 86h ; BIOS: wait
INT 15h
MOV DX, OFFSET DONE1
JNC SHOW1 ; CF = 0: the time has passed
MOV DX, OFFSET BUSY1
SHOW1:
MOV AH, 09h
INT 21h
WAITING1 DB "waiting one second... $"
DONE1 DB "done", 13, 10, "$"
BUSY1 DB "not supported here", 13, 10, "$"

Resolution and limits

The RTC interrupt comes every 976 µs, so the wait is rounded up to about a millisecond: asking for 10 µs waits a millisecond. For short exact delays programs read the timer chip (port 40h) instead. The longest wait is 4295 seconds. Only one wait can run at a time; a second call while one is active (from an interrupt handler, say) returns CF = 1 immediately. The PC and XT have no RTC and no such function.

Pitfalls

The wait needs IRQ 8, which goes through the second interrupt controller and IRQ 2 of the first. A program that masks IRQ 2 or IRQ 8 at the 8259 (port 21h or A1h) makes the wait last forever on many BIOSes; DOSBox-X warns about this in its log and has an option to unmask them. Do not call it from inside a hardware interrupt handler: the handler would block every interrupt of lower priority for the whole wait.