Millisecond timing without assembly

Posted on 1998-01-29
Last Modified: 2008-02-01

I am interested in having millisecond timing for
psychology experiments.  The timer...() routines below
were given to me, but dont seem to work properly on
my pentium (200 Mhz).  You will see i have been trying to
test them by timing the vertical refresh, just giving
output every second, or most recently just printing out
timer0count().  Things are generally ok for a little while
but then crazy numbers appear.  (I am making a DOS program
in Borland 5, and then running in a DOS window, or in
DOS mode)

timer0Init() seems to be the critical routine.  I am
hoping one of you can see something obviously wrong with
it, or suggest an alternative source of code.


Mark Chappell

#include <time.h>
#include <process.h>
#include <dos.h>

#include <stdio.h>


/* control register addr of 8253 timer counter chip */
#define CTRL_REG 0x0043
/* word to initialise channel 0 */
#define CTRL_INIT_WORD 0x0036
/* addr of channel 0 */
#define CH2 0x0040
/* number of system clock ticks in a timer tick */

#define CLOCK_DIVISOR 1193
/* #define CLOCK_DIVISOR 1193
       1.193 MHz divided by 1193 gives a timer tick every 1 ms */

/* BIOS interrupt number for tick generated by 8253 channel 0 */
#define TICK_INT_NR 0x1C

/* Below taken from setvect Example.  MC 25/11/97 */
#ifdef __cplusplus
    #define __CPPARGS ...
    #define __CPPARGS

static int initialised = 0;  /* false */
/* static int ch = 0, notstalled = 1 */;
static unsigned long tickCnt = 0 /* , timecount = 0 */ ;
static void interrupt (*origTickHandler)(__CPPARGS); /* arg was empty MC */
static void interrupt newTickHandler(__CPPARGS); /* arg was void MC */

void timer0Init(void), timer0Dispose(void), timer0Reset(void);
unsigned long timer0TickCount(void);

unsigned char ch;
int i, ok, c;
long arr[1000];


for(i = 0; i < 100; i++)
    printf("%u ", timer0TickCount());
/*   while(timer0TickCount() < (i + 1) * 1000)
      if(timer0TickCount() > 30000)
            printf("%d ", timer0TickCount());
   printf("\n%d ", i + 1);      */

for(i = 0; i < 0; i++)
   ok = 0;  ch = 1;
   while(ch != 0)
      ch = inportb(0x3DA)&8;
/*      ok++;
      printf("h1 %X ", ch);
      if(ok > 1000)
            exit(0);              */
  /*    printf("\n");                */

       while(ch == 0)
            ch = inportb(0x3DA)&8;
/*       ok++;
     printf("h2 %X ", ch);
      if(ok > 1000)
            exit(0);            */
/*   printf("\n");                   */

arr[i] = timer0TickCount();

   printf("%u ", timer0TickCount());


for(i = 0; i < 100; i++)
      printf("%ld ", arr[i]);

void timer0Init(void)
      if (!initialised)
            initialised = 1;  /* true */
            /* install new ISR for bios tick interrupt, and save
current one */
            origTickHandler = getvect(TICK_INT_NR);
            setvect(TICK_INT_NR, newTickHandler);
            /* set channel 0 count period */
            outport(CTRL_REG, CTRL_INIT_WORD);
             outportb(CH2, CLOCK_DIVISOR & 0x00FF); /*  LSB     */
            outportb(CH2, CLOCK_DIVISOR >> 8);  /* MSB */
   /*   outportb(CH2, CLOCK_DIVISOR);      */
        /* init tick count */
      tickCnt = 0;

void timer0Dispose(void)
      if (initialised)
            initialised = 0;  /* false */
            /* restore channel 0 count period to 18.203 Hz */
            outport(CTRL_REG, CTRL_INIT_WORD);
            outportb(CH2, 0);
            outportb(CH2, 0);
            /* reinstall original ISR for bios tick */
            setvect(TICK_INT_NR, origTickHandler);

/* the new interrupt handler for the BIOS tick interrupt */
static void interrupt newTickHandler(__CPPARGS)

void timer0Reset(void)
      tickCnt = 0;

unsigned long timer0TickCount(void)
      return (tickCnt);
Question by:markc2

Expert Comment

ID: 1257119
I have a similar piece of code which essently times the vertical retrace which I wrote a while back. Just having a quick look at it, I have at the very end of my interrupt handler the following
This was with BC3.11 and I'm not sure if you'll need it with BC5. Also BC3.11 docs say don't compile with 'Test stack overflow' on, I don't know if you are doing this or it is required with BC5.

Just a few thoughts.

LVL 15

Accepted Solution

Tommy Hui earned 100 total points
ID: 1257120
If this is running on a Pentium, you can use its time counter, using the rdtsc instruction. There's code to do this with Visual C++, you search for pentium counter on the web. There may be code to do this with Borland C++. The counter is maintained by the hardware, so it is very accurate. You might want to search the web for the Zen Timer by Michael Abrash.

Author Comment

ID: 1257121
Thanks, i found, after a bit.  I am wondering
if there is a more recent version (it seems to be early
to mid 96); i cant seem to find it.  With this i seem
to be getting sensible timing.

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is posted by Aaron Wojnowski, administrator at  To view more iPhone tutorials, visit This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question