138 lines
5.6 KiB
Markdown
138 lines
5.6 KiB
Markdown
**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);
|