Q57851: CALL INTERRUPT for Small Time Increments Using BIOS Tick Count
Article: Q57851
Product(s): See article
Version(s): 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | SR# S900111-209 B_BasicCom | mspl13_basic
Last Modified: 25-OCT-1990
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
------------
REM TIMEINT.BAS
DEFLNG A-Z
' $INCLUDE: 'QB.BI'
' 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
DIM flag AS INTEGER, Previous AS LONG
CLS
LOCATE 1, 20: PRINT "Hit any key to end"
WHILE INKEY$ = ""
inregs.ax = 0
CALL INTERRUPT(&H1A, inregs, outregs)
' CX should never be larger than &H0017, so direct
' assignment is possible.
ticks& = outregs.cx * &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&)
ELSE
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#
WEND
END
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.