Microsoft KB Archive/57851

From BetaArchive Wiki

Article ID: 57851

Article Last Modified on 11/21/2006


  • Microsoft QuickBasic 2.0
  • Microsoft QuickBasic 3.0
  • Microsoft QuickBasic 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBasic 4.5 for MS-DOS
  • Microsoft BASIC Compiler 6.0
  • Microsoft BASIC Compiler 6.0b
  • Microsoft BASIC Professional Development System 7.0
  • Microsoft BASIC Professional Development System 7.1

This article was previously published under Q57851


The TIME$ function in Basic returns the current time in hours, minutes, and seconds from DOS or OS/2, but it cannot return any increments smaller than one second.

However, a program can use the INTERRUPT routine to call the IBM ROM BIOS interrupt 1A Hex (26 decimal) with function 0. This function returns the number of system timer ticks since midnight. The number of timer ticks can then be used to calculate the number of seconds that have passed since midnight. You can then time to a resolution of 18.20648 ticks per second (or .05492549 of a second).

This information applies to Microsoft QuickBasic versions 2.00, 3.00, 4.00, 4.00B, and 4.50, to Microsoft Basic Compiler versions 6.00 and 6.00b for MS-DOS, and to Microsoft Basic Professional Development System (PDS) versions 7.00 and 7.10 for MS-DOS.


Here are three separate methods to get a small time interval:

  1. Use BIOS INTERRUPT 15 Hex, with function 86 hex (or, in decimal, INTERRUPT 21 with function 134) for a resolution at intervals of 976 microseconds (976 millionths, or .000976 of a second).
  2. Use BIOS INTERRUPT 1A hex (26 decimal) with function 0 for a resolution at about 18.20648 ticks per second (or .05492549 seconds).
  3. Use the ON PLAY statement for resolution at 30 times per second (or .0333333).

This article describes method 2 above. To find two other articles, which explain methods 1 and 3, search in this Knowledge Base using the following exact words:

Basic and timer and increments and smaller and second

Explanation of PC Timer Ticks

Below is an explanation of how the PC system timer works. Also included is a Basic program example that shows how to calculate the number of seconds since midnight to the hundredths place, with a resolution of .05492549 of a second.

A timer "tick" is an interrupt that is generated by the PC's system timer. When this interrupt occurs, the ROM BIOS interrupt handler is called, and it increments a count in the ROM BIOS data area reserved for recording the number of ticks since midnight.

Timer ticks work as follows. More than one system timer tick occurs per second. In fact, a timer tick occurs approximately 18.2 times every second. To be even more exact, a timer tick occurs every 1,193,180 / 65,536 times per second, which is 18.20648 times per second. The first value, 1,193,180, represents the frequency at which the PC system timer operates, which is 1.193 MHz. This means that the system timer can actually recognize increments as small as 1 / 1,193,180 seconds.

However, since very few programs could possibly need a time increment this small, the system timer uses another method to determine when to generate a tick. The system timer maintains an internal register. The timer initializes the register to 65,535 and then decrements the register or "counts down" from 65,535 to zero. When zero occurs, the timer generates a tick (it actually generates an interrupt that increments the tick count). Note that this is where the lower half of the fraction 1,193,180 / 65,536 comes from. If the timer runs at 1.93 MHz and it decrements a counter 65,536 times before it generates a tick, this means that dividing the timer speed by this countdown value gives us how many ticks occur per second.

For more information on the PC system timer, please refer to Page 145 of "The New Peter Norton Programmer's Guide to the IBM PC & PS/2" (Microsoft Press, 1988).

The following program example shows how to use the tick count returned by interrupt &H1A function 0 to calculate the number of seconds since midnight to the hundredth place. To run this program in the QB.EXE editor, you must load the program with /L to load the QB.QLB Quick library (but for Basic PDS 7.00 or 7.10, use QBX /L to load QBX.QLB). If you compile from the command line, you must link in the QB.LIB library (or the QBX.LIB library for Basic PDS 7.00).

Code Example

' For Basic PDS 7.00 you must change above line to QBX.BI
CONST tps = 18.2064819336# ' tps is ticks per second
DIM inregs AS RegType, outregs AS RegType
LOCATE 1, 20: PRINT "Hit any key to end"
WHILE INKEY$ = "" = 0
        CALL INTERRUPT(&H1A, inregs, outregs)
        ' CX should never be larger than &H0017, so direct
        ' assignment is possible.
        ticks& = * &H10000
        ' The following IF accounts for the fact that the
        ' interrupt is using an unsigned int (register) but Basic
        ' has only signed integers. Special action must be taken
        ' for numbers that appear to be negative.
        IF outregs.dx < 0 THEN
                a2& = (outregs.dx AND &H7FFF&)
                ticks& = (ticks& + a2&)
                ticks& = (ticks& OR &H8000&)
                ticks& = ticks& + outregs.dx
        END IF
        IF Previous > ticks& THEN BEEP ' It's midnight!
        Previous = ticks&

        Previous = ticks&
        seconds# = ticks& / tps 'ticks per second

        LOCATE 10, 10
        PRINT "Clock ticks since midnight: ";
        PRINT ticks&
        LOCATE 11, 10
        PRINT "Seconds since midnight: ";
        PRINT USING "######.##"; seconds#

Additional query words: QuickBas BasicCom

Keywords: KB57851