Previous | Table of Contents | Next

Moreover, because it uses an undocumented feature, the timer-stop approach could conceivably cause erratic 8253 operation, which could in turn seriously affect your computer’s operation until the next reboot. In non-8253-compatible systems, I’ve observed not only wildly incorrect timing results, but also failure of a diskette drive to operate properly after the long-period Zen timer with PS2 set to 0 has run, so be alert for signs of trouble if you do set PS2 to 0.

Rebooting should clear up any timer-related problems of the sort described above. (This gives us another reason to reboot at the end of each code-timing session.) You should immediately reboot and set the PS2 equate to 1 if you get erratic or obviously incorrect results with the long-period Zen timer when PS2 is set to 0. If you want to set PS2 to 0, it would be a good idea to time a few of the listings in this book with PS2 set first to 1 and then to 0, to make sure that the results match. If they’re consistently different, you should set PS2 to 1.

While the the non-PS/2 version is more dangerous than the PS/2 version, it also produces more accurate results when it does work. If you have a non-PS/2 PC-compatible computer, the choice between the two timing approaches is yours.

If you do leave the PS2 equate at 1 in Listing 3.5, you should repeat each code-timing run several times before relying on the results to be accurate to more than 54 ms, since variations may result from the possible lack of synchronization between the timer 0 count and the BIOS time-of-day count. In fact, it’s a good idea to time code more than once no matter which version of the long-period Zen timer you’re using, since interrupts, which must be enabled in order for the long-period timer to work properly, may occur at any time and can alter execution time substantially.

Finally, please note that the precision Zen timer works perfectly well on both PS/2 and non-PS/2 computers. The PS/2 and 8253 considerations we’ve just discussed apply only to the longZen timer.

### Example Use of the Long-Period Zen Timer

The long-period Zen timer has exactly the same calling interface as the precision Zen timer, and can be used in place of the precision Zen timer simply by linking it to the code to be timed in place of linking the precision timer code. Whenever the precision Zen timer informs you that the code being timed takes too long for the precision timer to handle, all you have to do is link in the long-period timer instead.

Listing 3.6 shows a test-bed program for the long-period Zen timer. While this program is similar to Listing 3.2, it’s worth noting that Listing 3.6 waits for a few seconds before calling ZTimerOn, thereby allowing any pending keyboard interrupts to be processed. Since interrupts must be left on in order to time periods longer than 54 ms, the interrupts generated by keystrokes (including the upstroke of the Enter key press that starts the program)—or any other interrupts, for that matter—could incorrectly inflate the time recorded by the long-period Zen timer. In light of this, resist the temptation to type ahead, move the mouse, or the like while the long-period Zen timer is timing.

LISTING 3.6 LZTEST.ASM

    ; Program to measure performance of code that takes longer than
    ; 54 ms to execute. (LZTEST.ASM)
    ;
    ; Link with LZTIMER.ASM (Listing 3.5). LZTIME.BAT (Listing 3.7)
    ; can be used to assemble and link both files. Code to be
    ; measured must be in the file TESTCODE; Listing 3.8 shows
    ; a sample file (LST3-8.ASM) which should be named TESTCODE.
    ;
    ; By Michael Abrash
    ;
    mystack   segment    para stack ‘STACK’
         db         512 dup(?)
    mystack    ends
    ;
    Code  segment   para public ‘CODE’
          assume    cs:Code, ds:Code
          extrn ZTimerOn:near, ZTimerOff:near, ZTimerReport:near
    Startproc   near
          push  cs
         pop    ds     ;point DS to the code segment,
                       ; so data as well as code can easily
                       ; be included in TESTCODE
    ;
    ; Delay for 6-7 seconds, to let the Enter keystroke that started the
    ; program come back up.
    ;
         mov  ah,2ch
         int  21h        ;get the current time
         mov  bh,dh      ;set the current time aside
    DelayLoop:
         mov   ah,2ch
         push  bx                 ;preserve start time
         int   21h                ;get time
         pop   bx                 ;retrieve start time
         cmp   dh,bh              ;is the new seconds count less than
                                  ; the start seconds count?
         jnb   CheckDelayTime     ;no
         add   dh,60              ;yes, a minute must have turned over,
                                  ; so add one minute
    CheckDelayTime:
         sub   dh,bh                 ;get time that’s passed
         cmp   dh,7                  ;has it been more than 6 seconds yet?
         jb    DelayLoop             ;not yet
    ;
         include   TESTCODE          ;code to be measured, including calls
                                     ; to ZTimerOn and ZTimerOff
    ;
    ; Display the results.
    ;
         call  ZTimerReport
    ;
    ; Terminate the program.
    ;
         mov  ah,4ch
         int  21h
    Start endp
    Code  ends
          end     Start

As with the precision Zen timer, the program in Listing 3.6 is used by naming the file containing the code to be timed TESTCODE, then assembling both Listing 3.6 and Listing 3.5 with MASM or TASM and linking the two files together by way of the Microsoft or Borland linker. Listing 3.7 shows a batch file, named LZTIME.BAT, which does all of the above, generating and running the executable file LZTEST.EXE. LZTIME.BAT assumes that the file LZTIMER.ASM contains Listing 3.5 and the file LZTEST.ASM contains Listing 3.6.

Previous | Table of Contents | Next

Graphics Programming Black Book © 2001 Michael Abrash