150 lines
6.1 KiB
Markdown
150 lines
6.1 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](03-08.html) [Table of Contents](index.html) [Next](03-10.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
**LISTING 3.7 LZTIME.BAT**
|
||
|
||
echo off
|
||
rem
|
||
rem *** Listing 3.7 ***
|
||
rem
|
||
rem ***************************************************************
|
||
rem * Batch file LZTIME.BAT, which builds and runs the *
|
||
rem * long-period Zen timer program LZTEST.EXE to time the code *
|
||
rem * named as the command-line parameter. Listing 3.5 must be *
|
||
rem * named LZTIMER.ASM, and Listing 3.6 must be named *
|
||
rem * LZTEST.ASM. To time the code in LST3-8, you’d type the *
|
||
rem * DOS command: *
|
||
rem * *
|
||
rem * lztime lst3-8 *
|
||
rem * *
|
||
rem * Note that MASM and LINK must be in the current directory or *
|
||
rem * on the current path in order for this batch file to work. *
|
||
rem * *
|
||
rem * This batch file can be speeded up by assembling LZTIMER.ASM *
|
||
rem * once, then removing the lines: *
|
||
rem * *
|
||
rem * masm lztimer; *
|
||
rem * if errorlevel 1 goto errorend *
|
||
rem * *
|
||
rem * from this file. *
|
||
rem * *
|
||
rem * By Michael Abrash *
|
||
rem ***************************************************************
|
||
rem
|
||
rem Make sure a file to test was specified.
|
||
rem
|
||
if not x%1==x goto ckexist
|
||
echo ***************************************************************
|
||
echo * Please specify a file to test. *
|
||
echo ***************************************************************
|
||
goto end
|
||
rem
|
||
rem Make sure the file exists.
|
||
rem
|
||
:ckexist
|
||
if exist %1 goto docopy
|
||
echo ***************************************************************
|
||
echo * The specified file, “%1,” doesn’t exist. *
|
||
echo ***************************************************************
|
||
goto end
|
||
rem
|
||
rem copy the file to measure to TESTCODE.
|
||
:docopy
|
||
copy %1 testcode
|
||
masm lztest;
|
||
if errorlevel 1 goto errorend
|
||
masm lztimer;
|
||
if errorlevel 1 goto errorend
|
||
link lztest+lztimer;
|
||
if errorlevel 1 goto errorend
|
||
lztest
|
||
goto end
|
||
:errorend
|
||
echo ***************************************************************
|
||
echo * An error occurred while building the long-period Zen timer. *
|
||
echo ***************************************************************
|
||
:end
|
||
|
||
Listing 3.8 shows sample code that can be timed with the test-bed
|
||
program of Listing 3.6. Listing 3.8 measures the time required to
|
||
execute 20,000 loads of AL from memory, a length of time too long for
|
||
the precision Zen timer to handle on the 8088.
|
||
|
||
**LISTING 3.8 LST3-8.ASM**
|
||
|
||
;
|
||
; Measures the performance of 20,000 loads of AL from
|
||
; memory. (Use by renaming to TESTCODE, which is
|
||
; included by LZTEST.ASM (Listing 3.6). LZTIME.BAT
|
||
; (Listing 3.7) does this, along with all assembly
|
||
; and linking.)
|
||
;
|
||
; Note: takes about ten minutes to assemble on a slow PC if
|
||
;you are using MASM
|
||
;
|
||
jmpSkip;jump around defined data
|
||
;
|
||
MemVardb?
|
||
;
|
||
Skip:
|
||
;
|
||
; Start timing.
|
||
;
|
||
callZTimerOn
|
||
;
|
||
rept20000
|
||
moval,[MemVar]
|
||
endm
|
||
;
|
||
; Stop timing.
|
||
;
|
||
callZTimerOff
|
||
|
||
When LZTIME.BAT is run on a PC with the following command line (assuming
|
||
the code in Listing 3.8 is the file LST3-8.ASM)
|
||
|
||
lztime lst3-8.asm
|
||
|
||
the result is 72,544 µs, or about 3.63 µs per load of AL from memory.
|
||
This is just slightly longer than the time per load of AL measured by
|
||
the precision Zen timer, as we would expect given that interrupts are
|
||
left enabled by the long-period Zen timer. The extra fraction of a
|
||
microsecond measured per **MOV** reflects the time required to execute
|
||
the BIOS code that handles the 18.2 timer interrupts that occur each
|
||
second.
|
||
|
||
Note that the command can take as much as 10 minutes to finish on a slow
|
||
PC if you are using MASM, with most of that time spent assembling
|
||
Listing 3.8. Why? Because MASM is notoriously slow at assembling
|
||
**REPT** blocks, and the block in Listing 3.8 is repeated 20,000 times.
|
||
|
||
### Using the Zen Timer from C {#Heading15}
|
||
|
||
The Zen timer can be used to measure code performance when programming
|
||
in C—but not right out of the box. As presented earlier, the timer is
|
||
designed to be called from assembly language; some relatively minor
|
||
modifications are required before the **ZTimerOn** (start timer),
|
||
**ZTimerOff** (stop timer), and **ZTimerReport** (display timing
|
||
results) routines can be called from C. There are two separate cases to
|
||
be dealt with here: small code model and large; I’ll tackle the simpler
|
||
one, the small code model, first.
|
||
|
||
Altering the Zen timer for linking to a small code model C program
|
||
involves the following steps: **C** hange **ZTimerOn** to
|
||
**\_ZTimerOn**, change **ZTimerOff** to **\_ZTimerOff**, change
|
||
**ZTimerReport** to **\_ZTimerReport**, and change **Code** to
|
||
**\_TEXT** . Figure 3.2 shows the line numbers and new states of all
|
||
lines from Listing 3.1 that must be changed. These changes convert the
|
||
code to use C-style external label names and the small model C code
|
||
segment. (In C++, use the “C” specifier, as in
|
||
|
||
extern “C” ZTimerOn(void);
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](03-08.html) [Table of Contents](index.html) [Next](03-10.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|