Professional Documents
Culture Documents
chapter 3
assume nothing
chapter 3
33
The Costs of Ignorance
As diligent as the author had been, he had nonetheless committeda cardinal sin of
x86 assembly language programming: He had assumed that the information avail-
able to him was both correct and complete. While the execution times provided by
Intel for its processors are indeed correct,they are incomplete; the other-and of-
ten more important-part of code performance is instruction fetch time, a topic to
which I will return in later chapters.
Had the author taken the time to measure the true performance of his code, he
wouldn’t have put his reputation on the line with relatively low-performance code.
What’s more, had he actually measured the performanceof hiscode and found to it
be unexpectedly slow, curiosity might well have led him to experiment further and
thereby add to his store of reliable information about theCPU.
There you have an important tenet of assembly language optimization: After craft-
1 ing the best code possible, check it in action to see if it j. really doing what you
think it is. r f it k not behaving as expected, that 5. all to the good, since solving
mysteries is thepath to knowledge. You’ll learn more in thisway, Iassure you,than
from any manual or book on assembly language.
Assume nothing. I cannot emphasize this strongly enough-when you care about per-
formance, do your best to improve the code and thenmeasure the improvement. If
you don’t measure performance, you’re just guessing, and if you’re guessing, you’re
not very likely to write top-notch code.
Ignorance about true performance can be costly. When I wrote video games for a
living, I spent days at a time trying to wring more performance from my graphics
drivers. I rewrote whole sections of code justto save a few cycles,juggled registers,
and relied heavily on blurry-fast register-to-register shifts and adds. As I was writing
my last game, I discovered that the program ranperceptibly faster if I used look-up
tables instead of shifts and adds formy calculations. It shouldn’t have run faster, ac-
cording to my cycle counting, but it did. In truth, instruction fetching was rearing its
head again, as it often does, and the fetching of the shifts and adds was taking as
much as four times the nominal execution time of those instructions.
Ignorance can also be responsible for considerable wasted effort. I recall a debate in
the letters column of one computermagazine about exactly how quickly text can be
drawn on a Color/Graphics Adapter(CGA) screen without causing snow. The letter-
writers counted every cycle in their timing loops, just as the authorin the story that
started this chapter had. Like that author, the letter-writers had failed to take the
prefetch queue into account. In fact, they had neglected the effects of video wait
states as well, so the code they discussed was actually much slower than their esti-
mates. The proper test would, of course, have been to run the code to see if snow
resulted, since the only true measure of code performanceis observing it inaction.
34 Chapter 3
The Zen Timer
Clearly, one key to mastering Zen-class optimization is a tool with which tomeasure
code performance. The most accurate way to measure performance is with expen-
sive hardware, but reasonable measurements at no cost can be made with the PC’s
8253 timer chip, which counts at a rate of slightly over 1,000,000 times per second.
The 8253 can be started at the beginning of a block of code of interest and stopped
at the endof that code,with the resulting count indicating how long the codetook
to execute with an accuracy ofabout 1microsecond. (A microsecond is one millionth of
a second, and is abbreviated ps). To be precise, the 8253 counts once every 838.1
nanoseconds. (A nanosecond is one billionth of a second,and is abbreviated ns.)
Listing 3.1 shows 8253-based timer software, consisting of three subroutines:
ZTmerOn, ZTimerOff, and ZTimerReport. For the remainder of this book, 1’11 re-
fer to these routines collectively as the “Zen timer.” C-callable versions of the two
precision Zen timers are presented in Chapter K on the companion CD-ROM.
Uses t h e 8253 t i m e r t o t i m e t h e p e r f o r m a n c e o f c o d e t h a t t a k e s
l e s st h a na b o u t 5 4 m i l l i s e c o n d st oe x e c u t e ,w i t h a resolution
o fb e t t e rt h a n 10 microseconds.
By MichaelAbrash
E x t e r n a l l yc a l l a b l er o u t i n e s :
ZTimerOn: S t a r t st h e Zen t i m e r ,w i t hi n t e r r u p t sd i s a b l e d .
Z T i m e r O f f :S t o p st h e Zen t i m e r ,s a v e st h et i m e rc o u n t ,
t i m e st h eo v e r h e a dc o d e ,a n dr e s t o r e si n t e r r u p t st ot h e
s t a t et h e yw e r ei n when ZTimerOn was c a l l e d .
Z T i m e r R e p o r t :P r i n t st h en e tt i m et h a tp a s s e db e t w e e ns t a r t i n g
a n ds t o p p i n gt h et i m e r .
Note: I f l o n g e rt h a na b o u t 5 4 ms passesbetweenZTimerOnand
Z T i m e r O f fc a l l s ,t h et i m e rt u r n so v e ra n dt h ec o u n ti s
i n a c c u r a t e . When t h i sh a p p e n s , an e r r o r message i s d i s p l a y e d
i n s t e a d o f a c o u n t . The l o n g - p e r i o d Zen t i m e rs h o u l db eu s e d
i n suchcases.
N o t e :I n t e r r u p t s *MUST* be l e f t o f f b e t w e e nc a l l st o ZTimerOn
a n dZ T i m e r O f ff o ra c c u r a t et i m i n ga n df o rd e t e c t i o no f
t i m e ro v e r f l o w .
N o t e :T h e s er o u t i n e sc a ni n t r o d u c es l i g h ti n a c c u r a c i e si n t ot h e
s y s t e mc l o c kc o u n tf o re a c hc o d es e c t i o nt i m e de v e n if
t i m e r 0 d o e s n ’ to v e r f l o w . I f t i m e r 0 d o e so v e r f l o w ,t h e
s y s t e mc l o c kc a n become s l o w b y v i r t u a l l y anyamount of
t i m e ,s i n c et h es y s t e mc l o c kc a n ’ ta d v a n c ew h i l et h e
p r e c i s o nt i m e ri st i m i n g .C o n s e q u e n t l y ,i t ’ s a goodidea
t or e b o o ta tt h e end o fe a c ht i m i n gs e s s i o n .( T h e
Assume Nothing 35
: b a t t e r y - b a c k e dc l o c k , i f any. i sn o at f f e c t e db yt h e Zen
: timer.)
: Al r e g i s t e r s , and a l lf l a g se x c e p tt h ei n t e r r u p tf l a g ,a r e
: p r e s e r v e db ya l lr o u t i n e s .I n t e r r u p t sa r ee n a b l e da n dt h e nd i s a b l e d
: b yZ T i m e r O n .a n da r er e s t o r e db yZ T i m e r O f ft ot h es t a t et h e yw e r e
: i n when ZTimerOn was c a l l e d .
Code s e g m e nw
t o r dp u b l i c 'CODE'
assume
cs:Code.
ds:nothing
public ZTimerOn.ZTimerOff.
ZTimerReport
: Base a d d r e s so ft h e8 2 5 3t i m e rc h i p .
: T h ea d d r e s so ft h et i m e r 0 c o u n tr e g i s t e r si nt h e8 2 5 3 .
; T h ea d d r e s so ft h e mode r e g i s t e r i n t h e 8253.
: T h ea d d r e s so ft h eI n t e r r u p tR e q u e s tr e g i s t e ri nt h e8 2 5 9 PIC
: ( r e a do n l y .a n dr e a d a b l eo n l y when b i t 1 o f OCW3 - 1 and b i t 0
: o f OCW3 - 0).
I RR 20h equ
MPOPF macro
l o c a lp l . p2
j m ps h o r tp 2
i rp el :t jump t o pushedaddress & p o pf l a g s
push
p2:
cs c o n s t r u c tf a rr e t u r na d d r e s st o
c a pl l l t h en e x ti n s t r u c t i o n
endm
: Macro t o d e l a y b r i e f l y t oe n s u r et h a te n o u g ht i m eh a se l a p s e d
: b e t w e e ns u c c e s s i v e 1/0 accesses s o t h a t t h e d e v i c eb e i n ga c c e s s e d
: canrespond t ob o t ha c c e s s e se v e n ona v e r y f a s t PC.
DELAY macro
jmp $+2
jmp 5+2
jmp S+2
endm
36 Chapter 3
OriginalFlags db ? : s t o r a g ef o ru p p e rb y t eo f
FLAGS r e g i s t e r when
ZTimerOn c a l l e d
TimedCount dw ? : t i m e r 0 c o u n t when t h e t i m e r
i ss t o p p e d
Referencecount dw number o f c o u n t s r e q u i r e d t o
e x e c u t et i m e ro v e r h e a dc o d e
O v e r f l owFl ag db ? : used t o i n d i c a t e w h e t h e r t h e
t i m e ro v e r f l o w e dd u r i n gt h e
t i m i n gi n t e r v a l
: S t r i n gp r i n t e d t or e p o r tr e s u l t s .
: S t r i n gp r i n t e d t or e p o r tt i m e ro v e r f l o w .
db Odh. Oah
db ' * The t i m eor v e r f l o w e d , so t h ei n t e r v atli m e d was *'
db Odh. Oah
db ' * t oloo nfgot hr per e c i s i otni m etmor e a s u r e . *'
db Odh, Oah
db '* P l e a s pe e r f o r mt h tei m i n tge sat g a i wn i t thh e *'
db Odh. Oah
db t i m'e*r .l o n g - p e r i o d *.
Odh.
db Oah
db ......................................................
db Odh. Oah
db 't'
. ....................................................................
t i m i n sg t. a r t t o: *c aRl loeudt i n e *
. ....................................................................
ZTimerOn
proc
near
; Save t h ec o n t e x to ft h ep r o g r a mb e i n gt i m e d .
push
ax
pushf
POP ax g e t f l a g s so we cankeep
i n t e r r u p t s o f f when l e a v i n g
t h i sr o u t i n e
mov cs:[OriginalFlags].ah : remember t h e s t a t e o f t h e
Interruptflag
ah.0fdh
and s e tp u s h e di n t e r r u p tf l a g
to 0
push
ax
: T u r no ni n t e r r u p t s , s o t h et i m e ri n t e r r u p tc a no c c u r if it's
: pending.
sti
Assume Nothing 37
S e tt i m e r 0 o f t h e 8 2 5 3 t o mode2 ( d i v i d e - b y - N ) . t o cause
l i n e a rc o u n t i n gr a t h e rt h a nc o u n t - b y - t w oc o u n t i n g .A l s o
l e a v e st h e8 2 5 3w a i t i n gf o rt h ei n i t i a lt i m e r 0 c o u n tt o
b el o a d e d .
S e tt h et i m e rc o u n tt o 0. so we know we w o n ' tg e ta n o t h e r
t i m e ri n t e r r u p tr i g h t away.
N o t e :t h i si n t r o d u c e s a ni n a c c u r a c yo fu pt o 54 ms i n t h e s y s t e m
c l o c kc o u n te a c ht i m e i t i s executed.
DELAY
sub
a1
,a1
out TIMER-0-8253.al ;lsb
DELAY
out TIMER-0-8253.al
:msb
W a i tb e f o r ec l e a r i n gi n t e r r u p t st oa l l o wt h ei n t e r r u p tg e n e r a t e d
when s w i t c h i n g f r o m mode 3 t o mode2 t o b er e c o g n i z e d . The d e l a y
mustbe a t l e a s t 2 1 0n sl o n gt oa l l o wt i m ef o rt h a ti n t e r r u p tt o
o c c u r .H e r e ,1 0j u m p sa r eu s e df o rt h ed e l a yt oe n s u r et h a tt h e
d e l a yt i m e will bemorethanlongenoughevenon a v e r y f a s t PC.
r e p t1 0
jmp S+2
endm
D i s a b l ei n t e r r u p t st og e t a na c c u r a t ec o u n t .
cli
S e tt h et i m e rc o u n tt o 0 againtostartthetiminginterval.
mov al.00110100b ; s e t up t o l o a d i n i t i a l
out MODE-8253.al ; t i m e rc o u n t
DELAY
as lu. ba l
out TIMER-0-8253,al ; l o a dc o u n tl s b
DELAY
out TIMER-0-8253.al ; lcooaudn t msb
; R e s t o r et h ec o n t e x ta n dr e t u r n .
MPOPF ; k e e p si n t e r r u p t so f f
POP ax
ret
ZTimerOn
endp
.....................................................................
;* cRotgosium
aeutcnontaittipndonl. lge d *
.....................................................................
ZTimerO
p rnfofeca r
38 Chapter 3
: Save t h ec o n t e x t o f t h ep r o g r a mb e i n gt i m e d .
push
ax
push
cx
pushf
: L a t c ht h ec o u n t .
mov al,00000000b ; lt ai m
t cehr 0
out MODE-8253,al
: See i f t h et i m e rh a so v e r f l o w e db yc h e c k i n gt h e8 2 5 9f o r a pending
: t i m e ri n t e r r u p t .
: A l l o wi n t e r r u p t st o happenagain.
sti
: Read o u tt h ec o u n t we l a t c h e d e a r l i e r .
in al.TIMER_0-8253 ; l e a s ti g n i f i c a n
b ty t e
DELAY
mov ah.al
in a1 .TIMER-0-8253 ; m o ssti g n i f i c a nbty t e
xchg
ah.al
ax neg c o:ufcnrot dnmovw
e rnt
; r e m a i n i n gt oe l a p s e d
: count
mov cs:[TimedCountl.ax
: Time a z e r o - l e n g t hc o d ef r a g m e n t ,t og e t a r e f e r e n c e f o r how
; much o v e r h e a dt h i sr o u t i n eh a s .T i m e it 1 6t i m e sa n da v e r a g e it,
: f o ra c c u r a c y ,r o u n d i n gt h er e s u l t .
mov cs:[ReferenceCountl,O
mov cx.16
cli : ailnl ottew
or or uf fp t s a
: D r e c i s er e f e r e n c ec o u n t
RefLoop:
cRa lel f e r e n c e Z T i m e r D n
cRa lel f e r e n c e Z T i m e r O f f
1 oop Ref Loop
sti
addcs:[ReferenceCount].8 : total + ( 0.5 * 16)
mov c l .4
s hc rs : [ R e f e r e n c e C o u n t ] . c l : ( t o t a l ) / 16 + 0.5
: R e s t o r eo r i g i n a li n t e r r u p ts t a t e .
POP ax : r e t r i e v e f l a g s when c a l l e d
Assume Nothing 39
mov ch.~s:[OriginalFlags1 : g e tb a c kt h eo r i g i n a lu p p e r
b y t eo ft h e FLAGS r e g i s t e r
and
ch.not
Ofdh o n l yc a r ea b o u to r i g i n a l
interrupt flag ...
ah.0fdh
and ... keep all o t h e r f l a g s i n
t h e i rc u r r e n tc o n d i t i o n
or ah.ch make f l a g s w o r d w i t h o r i g i n a l
interruptflag
push
ax p r e p a r ef l a g st ob ep o p p e d
: R e s t o r et h ec o n t e x t o ft h ep r o g r a mb e i n gt i m e da n dr e t u r nt o it.
MPOPF : r e s t o r et h ef l a g sw i t ht h e
: o r i g i n a li n t e r r u p ts t a t e
POP cx
POP ax
ret
ZTimerOffendp
: C a l l e db yZ T i m e r O f f t os t a r tt i m e rf o ro v e r h e a dm e a s u r e m e n t s .
ReferenceZTimerOnproc near
: Save t h e c o n t e x t o f t h ep r o g r a mb e i n gt i m e d
push
ax
pushf : i n t e r r u patarsel r e a od fyf
: S e tt i m e r 0 o f t h e 8 2 5 3 t o mode 2 ( d i v i d e - b y - N ) , t o c a u s e
: l i n e a rc o u n t i n gr a t h e rt h a nc o u n t - b y - t w oc o u n t i n g .
mov al.00110100b : s e t up lt oo a d
out MODE-8253.al : i n i t ti ai ml ceoru n t
DELAY
: S e tt h et i m e rc o u n tt o 0.
a1,al
sub
out TIMER-0-8253,al : l o acdo u nl st b
DELAY
o Tu It M E R - 0 8 2 5 3 , a l : l o acdo u n t msb
: R e s t o r et h ec o n t e x to ft h ep r o g r a mb e i n gt i m e da n dr e t u r nt o it.
MPOPF
POP ax
ret
ReferenceZTimerOnendp
: C a l l e db yZ T i m e r O f ft os t o pt i m e ra n da d dr e s u l tt oR e f e r e n c e c o u n t
: f o ro v e r h e a dm e a s u r e m e n t s .
40 Chapter 3
near proc
ReferenceZTimerOff
: Save t h ec o n t e x t o ft h ep r o g r a mb e i n gt i m e d .
push
ax
push
cx
pushf
: L a t c ht h ec o u n ta n dr e a d it.
mov a1 .00000000b : l a t c ht i m e r 0
out MODEU3253,al
DELAY
in a1 .TIMER-0_8253 : lsb
DELAY
mov ah.al
in al.TIMER-OC8253 : msb
xchg ah.al
neg ax : c o n v e r tf r o mc o u n t d o w n
: r e m a i n i n gt o amount
: c o u n t e d down
add cs:[ReferenceCountl,ax
: R e s t o r et h ec o n t e x to ft h ep r o g r a mb e i n gt i m e da n dr e t u r n t o it.
MPOPF
POP cx
POP ax
ret
ReferenceZTimerOffendp
. ....................................................................
s*pui onR
rt;rei em l trgcosot a.ultliende *
. ....................................................................
Z T i m e nr Repear pro oc r t
pushf
push
ax
push
bx
push
cx
push
dx
push s i
push
ds
cs push : DOS f u n c t i o n s r e q u i r e t h a t DS p o i n t
POP ds : tt oe xt ot dbies p l a y e d on t shcer e e n
ds assume :Code
; Check f o r t i m e r 0 overflow.
cmp [ O v e r f l owFl a g l .O
jz PrintGoodCount
mov d x . o f f sOe tv e r f l o w S t r
mov ah.9
int 21h
jm
s hpoErnt d Z T i m e r R e p o r t
: C o n v e r tn e tc o u n tt od e c i m a l A S C I I i nm i c r o s e c o n d s .
Assume Nothing 41
Previous Home Next
PrintGoodCount:
mov ax.CTimedCount1
ax.[ReferenceCount]
sub
mov s i , o f f s eAt S C I I C o u n t E n d - 1
; C o n v e r tc o u n tt om i c r o s e c o n d sb ym u l t i p l y i n gb y. 8 3 8 1 .
mov dx.8381
mu1 dx
mov
db ixv
bx,
10000
:* .8381 -* 8381 / 10000
: C o n v e r tt i m ei nm i c r o s e c o n d st o 5 decimal A S C I I d i g i t s
mov bx. 10
mov cx.5
CTSLoop:
sub dx.dx
div bx
add d1:O‘
mov [sil.dl
dec si
1 oop CTSLoop
; P r i n tt h er e s u l t s .
mov ah.9
mov d x , o f f sO
e tu t p u t S t r
int 21h
EndZTimerReport:
POP ds
pop si
POP dx
POP cx
POP bx
POP ax
MPOPF
ret
ZTimerReport
endp
Code ends
end
42 Chapter 3
Starting the Zen Timer
ZTimerOn is called at the start of a segment of code to be timed. ZTimerOn saves
the contextof the calling code, disables interrupts, sets timer 0 of the 8253 tomode
2 (divide-by-N mode), sets the initial timer count to 0, restores the context of the
calling code, and returns. (I’dlike to note that while Intel’s documentation for the
8253 seems to indicate that timer
a won’t reset to 0 until it finishes counting down, in
actual practice, timers seem to reset to 0 as soon as they’re loaded.)
Two aspects of ZTimerOn are worth discussing further. One pointof interest is that
ZTimerOn disables interrupts. (ZTimerOff later restores interrupts to the state they
were in when ZTimerOn was called.) Were interrupts not disabled by ZTimerOn,
keyboard, mouse, timer, and other interrupts could occur during thetiming inter-
val, and thetime required to service those interrupts would incorrectly and erratically
appear to be part of the execution time of the code being measured. As a result,
code timed with the Zen timer should not expect any hardware interrupts to occur
during the interval between any call to ZTimerOn and the corresponding call to
ZTimerOff, and should not enable interrupts during that time.
Assume Nothing 43
Timer 2
To speaker
Output. b circuitry
From bit 0 * Gate
of port 61 h
Timer 1
44 Chapter 3
operation, timer 0 generates an output pulse that is lowfor about 27.5 msand high for
about 27.5 ms; this pulse is sent to the 8259 interrupt controller, and its rising edge
generates a timer interrupt onceevery 54.925 ms.
Square wave mode is not very usefulfor precision timing because it counts down by two
twice per timer interrupt, thereby rendering exact timings impossible. Fortunately,the
8253 offers another timer mode, mode 2 (divide-by-N mode), which is both a good
substitute for square wave mode and aperfect mode for precision timing.
Divide-by-Nmode counts down by one from the initial count. When the countreaches
zero, the timer turns over and starts counting down again without stopping, and a
pulse is generated for a single clock period. While the pulse is not held fornearly as
long as in square wave mode, it doesn’t matter, since the 8259 interrupt controller is
configured in thePC to be edge-triggered and hencecares only about theexistence
of a pulse from timer 0, not the durationof the pulse. As a result, timer 0 continues
to generate timer interrupts in divide-by-N mode, and thesystem clockcontinues to
maintain good time.
Why not use timer 2 instead of timer 0 for precision timing? After all, timer 2 has a
programmable gate input and isn’t used for anything but sound generation. The
problem with timer 2 is that its output can’t generate an interrupt; in fact, timer 2
can’t do anything but drive the speaker. We need the interrupt generated by the
output of timer 0 to tell us when the count has overflowed, and we will see shortly
that thetimer interrupt also makesit possible to time much longer periods than the
Zen timer shown in Listing 3.1 supports.
In fact, the Zen timer shown in Listing 3.1 can only time intervals of up to about 54
ms in length, since that is the periodof time that can be measured by timer 0 before
its count turns over and repeats. fifty-four ms maynot seem like a very long time, but
even a CPU as slow as the 8088 can perform more than 1,000 divides in 54 ms, and
division is the single instruction that the 8088 performs most slowly. If a measured
period turns out to be longer than 54 ms (that is, if timer 0 has counted down and
turned over), theZen timer will display a message to that effect. A long-period Zen
timer for use in such cases willbe presented later inthis chapter.
The Zen timer determines whether timer 0 has turned over by checking to seewhether
an IRQO interrupt is pending. (Remember, interrupts are off while the Zen timer
runs, so the timer interrupt cannot be recognized until the Zen timer stops and
enables interrupts.) If an IRQO interrupt is pending, then timer 0 has turned over
and generated atimer interrupt. Recall that ZTimerOn initially setstimer 0 to 0, in
order to allowfor thelongest possible period-about 54 ms-before timer 0 reaches
0 and generates the timer interrupt.
Now we’re ready tolook at theways in which the Zen timer can introduce inaccuracy
into thesystem clock. Since timer 0 is initially set to 0 by the Zen timer,and since the
system clock ticks only when timer 0 counts off 54.925 ms and reaches 0 again, an
average inaccuracy of one-half of 54.925 ms,or about27.5 ms, is incurred eachtime
Assume Nothing 45
the Zen timer is started. In addition, atimer interrupt is generated when timer 0 is
switched from mode 3 to mode 2, advancing the system clock by up to 54.925 ms,
although this only happens the first time the Zen timer is run after awarm or cold
boot. Finally, up to 54.925 ms canagain be lost when ZTimerOff is called, since that
routine again sets the timer count to zero. Net result: The system clock willrun upto
110 ms (about a ninthof a second) slow each time the Zen timer is used.
Potentially far greater inaccuracy can be incurred by timing code that takes longer
than about 110 ms to execute. Recall that all interrupts, including the timer inter-
rupt, aredisabled while timing code with the Zen timer.The 8259 interrupt controller
is capable of remembering at most one pending timer interrupt,so all timer inter-
rupts after the first one during any given Zen timing interval are ignored.
Consequently, if a timing interval exceeds 54.9 ms, the system clock effectivelystops
54.9 ms after the timing interval startsand doesn’t restart until the timing interval
ends, losing time all the while.
The effects on the system time of the Zen timer aren’t a matter for great concern, as
they are temporary, lasting only until the nextwarm or cold boot. Systems that have
battery-backed clocks, (AT-style machines; that is, virtually allmachines in common
use) automatically reset the correcttime whenever the computer is booted, and sys-
temswithout battery-backed clocks prompt for the correct datetime andwhenbooted.
Also, repeated use of the Zen timer usually makes the system clock slow by at most a
total of a few seconds, unless code thattakes much longer than54 ms to run is timed
(in which case the Zen timer will notify you that the codeis too long to time).
Nonetheless, it’s a good idea to rebootyour computer at the end of each session with
the Zen timer in order to make sure that thesystem clock iscorrect.
46 Chapter 3
One interesting aspect of ZTimerOff is the manner in which timer 0 is stopped in
order to read the timer count. We don’t actually have to stop timer 0 to read the
count; the 8253 provides a special latched read feature for the specific purpose of
reading the countwhile a time is running. (That’s a good thing,too; we’ve no docu-
mented way to stoptimer 0 if we wanted to, since itsgate input isn’t connected. Later
in this chapter, though,we’ll seethat timer 0 can be stopped after all.) We simply tell
the 8253 to latch the current count, and the 8253 does so without breaking stride.
Assume Nothing 47
stored in a buffer within the driver, to be dumped at a later time. (Credit for this
final approach goes to Michael Geary,and thanks go to David Millerfor passing the
idea on to me.)
You may well want to devise still other approaches better suited to your needs than
those I’ve presented. Go to it! I’ve
just thrown out afew possibilities toget you started.
48 Chapter 3
IBM machines, or that either absolute or relative code performance will be similar
even on different IBM models; in fact, quite the oppositeis true. For example, every
PS/2 computer, even the relatively slow Model 30, executes code much faster than
does a PC or XT. As another example, I set out to do thetimings for my earlier book
Zen of Assembly Language on an XT-compatible computer, only to find that thecom-
puter wasn't quite IBM-compatible regarding code performance. The differences
were minor, mind you, but my experience illustrates the risk of assumingthat a spe-
cific make ofcomputer will perform ina certain way without actually checking.
Not that this variation between models makes the Zen timer one whit less useful-
quite the contrary. The Zen timeris an excellent tool for evaluating code performance
over the entire spectrumof PC-compatible computers.
L i n kw i t h PZTIMER.ASM ( L i s t i n g3 . 1 ) . PZTEST.BAT ( L i s t i n g3 . 4 )
canbeused t o assembleand linkbothfiles. Code t o be
measuredmustbe i n t h e f i l e TESTCODE; L i s t i n g3 . 3 shows
a sample TESTCODE f i l e .
By M i c h a e A
l brash
m y sst ae cgkm
sp taearncatk 'STACK'
dup(?)
512db
ends
mystack
; D i s p l a yt h er e s u l t s .
c aZ lTl i m e r R e p o r t
; T e r m i n a t et h ep r o g r a m .
Assume Nothing 49
mov ah.4ch
int 21h
Start endp
Code ends
Se tnadr t
Listing 3.3 shows some sample code to be timed. This listing measures the time re-
quired to execute 1,000 loads of AL from the memory variable MemVar. Note that
Listing 3.3 calls ZTimerOn to start timing, performs 1,000 MOV instructions in a
row, and calls ZTimerOff to end timing. When Listing 3.2 is named TESTCODE and
included by Listing 3.3, Listing 3.2 calls ZTimerReport to display the executiontime
after the codein Listing 3.3 has been run.
MemVar db ?
Skip:
; S t a r tt i m i n g .
call ZTimerOn
r e p1 t0 0 0
mov a1 , [MemVarl
endm
: S t o pt i m i n g .
c aZ lTl i m e r O f f
It’s worth noting that Listing 3.3 begins by jumping around the memory variable
MemVar. This approach lets us avoid reproducing Listing 3.2in its entirety for each code
fragment we want to measure;by defining any needed data right in the code segment
and jumping around that data, each listing becomes selfcontained andcan be plugged
directly into Listing 3.2 as TESTCODE. Listing3.2 sets DS equal toCS before doing
anything else preciselyso that datacan be embeddedin code fragments being timed.
Note that only after the initial jump is performed in Listing 3.3 is the Zen timer
started, since we don’t want to include the execution time of start-up code in the
timing interval. That’s why the calls to ZTimerOn and ZTimerOff are in TESTCODE,
not in PZTESTMM; this way, wehave full control over whichportion of TESTCODE
is timed, and we can keep set-up code and thelike out of the timing interval.
50 Chapter 3
Listing 3.3 is used by naming it TESTCODE, assembling both Listing 3.2 (which
includes TESTCODE) and Listing 3.1 with TASM or MASM, and linking the two
resulting OBJ files together by way of the Borland or Microsoft linker. Listing 3.4
shows a batch file, PZTIME.BAT, which does all that; when run, this batch file gener-
ates and runs the executable file PZTEST.EXE. PZTIME.BAT (Listing 3.4) assumes
that thefile PZTIMER.ASM contains Listing 3.1, and thefile PZTEST.ASM contains
Listing 3.2. The command-line parameter to PZTIME.BAT is the name of the file to
be copied to TESTCODE and included intoPZTEST.ASM. (Note that TurboAssem-
bler can be substituted for MASM by replacing “masm”with “tasm”and “link”with
“tlink” in Listing 3.4. The same is true of Listing 3.7.)
Assume Nothing 51
Assuming that Listing 3.3 is named LST3-3.ASM and Listing 3.4 is named
PZTIME.BAT, the code in Listing 3.3 wouldbe timed with the command:
p z t i m e LST3-3.ASM
which performs all assemblyand linking, and reports the execution time of the code
in Listing 3.3.
When the above command is executed on an original 4.77 MHz IBM PC, the time
reported by the Zen timer is 3619ps, or about3.62 ps per load of AL from memory.
(While the exact number is 3.619 ps per load of AL, I’m going to round off that last
digit from now on. No matter how many repetitions of a given instruction are timed,
there’sjust too much noise in the timing process-between dynamic RAM refresh,
the prefetch queue,and the internal state of the processor at the start of timing-for
that last digit to have any significance.) Given the test PC’s 4.77 MHz clock, this
works out to about 17 cycles per MOV, which is actually a good bit longer than Intel’s
specified 10-cycle execution time for this instruction. (See the MASM or TASM docu-
mentation, or Intel’s processor reference manuals, for official execution times.) Fear
not, theZen timer is right-MOV AL,[MEMVAR] really does take 1’7cycles asused
in Listing 3.3. Exactlywhy that is so is just what this book is all about.
In orderto perform any ofthe timing tests in this book, enter Listing 3.1 and name
it PZTIMERMM,enter Listing 3.2and name it PZTESTASM, and enterListing 3.4
and name it PZTIME.BAT. Then simply enter thelisting you wishto run into the file
filename and enter thecommand:
p z t i m e< f i l e n a m e >
In fact, that’s exactly how I timed each of the listings in this book. Code fragments
you write yourself can be timed in just thesame way. If you wishto time code directly
in place in your programs, rather thanin the test-bed program of Listing 3.2, simply
52 Chapter 3
insert calls to ZTimerOn, ZTimerOff,and ZTimerReport in the appropriate places
and link PZTIMER to your program.
Assume Nothing 53
The long-period Zen timer has some of the same effects on thesystem time as does
the precision Zen timer, so it’s a good idea to reboot the system after a session with
the long-period Zen timer. The long-period Zen timer does not, however, have the
same potential for introducingmajor inaccuracy into thesystem clocktime during a
single timing run since it leaves interrupts enabled and thereforeallows the system
clock to update normally.
54 Chapter 3
method will work on all PGcompatible computers, but may occasionally produce re-
sults that are incorrect by 54 ms. The timer-stop approach avoids synchronization
problems, but doesn't work on all computers.
By MichaelAbrash
E x t e r n a l l yc a l l a b l er o u t i n e s :
ZTimerOn:Savesthe B I O S t i m eo fd a yc o u n ta n ds t a r t st h e
l o n g - p e r i o d Zen t i m e r .
Z T i m e r O f f :S t o p st h el o n g - p e r i o d Zen t i m e ra n ds a v e st h et i m e r
c o u n ta n dt h e BIOS t i m e - o f - d a yc o u n t .
Z T i m e r R e p o r t :P r i n t st h et i m et h a tp a s s e db e t w e e ns t a r t i n ga n d
s t o p p i n gt h et i m e r .
Note: I f e i t h e rm o r et h a na nh o u rp a s s e so rm i d n i g h tf a l l sb e t w e e n
c a l l s t o ZTimerOnandZTimerOff,anerror i sr e p o r t e d .F o r
t i m i n gc o d et h a tt a k e sm o r et h a n a f e wm i n u t e st oe x e c u t e ,
e i t h e r t h e OOS TIME command i n a b a t c h f i l e b e f o r e and a f t e r
e x e c u t i o no ft h ec o d et ot i m eo rt h eu s eo ft h e DOS
t i m e - o f - d a yf u n c t i o ni np l a c eo ft h el o n g - p e r i o d Zen t i m e r i s
morethanadequate.
Note:The P S / 2 v e r s i o ni sa s s e m b l e db ys e t t i n gt h es y m b o l PS2 t o 1.
PS2 m u s tb es e tt o 1 on P S / 2 computersbecausethe PS/Z's
t i m e r sa r en o tc o m p a t i b l ew i t h a nu n d o c u m e n t e dt i m e r - s t o p p i n g
f e a t u r eo ft h e8 2 5 3 :t h ea l t e r n a t i v et i m i n ga p p r o a c ht h a t
mustbeusedonPS/2computersleaves a s h o r tw i n d o w
d u r i n gw h i c ht h et i m e r 0 c o u n ta n dt h e B I O S t i m e rc o u n t may
n o tb es y n c h r o n i z e d . You s h o u l da l s os e tt h e PS2 symbol t o
1 i f y o u ' r eg e t t i n ge r r a t i co ro b v i o u s l yi n c o r r e c tr e s u l t s .
....................................................................
* I f y o uc ro m p u t ed ri s p l a yasnhyi noe tfr r a t bi ce h a v i o r *
* a f t e rt h el o n g - p e r i o d Zen t i m e ri su s e d s, u c ha st h ef l o p p y *
* d r i v fea i l i n tgo p e r a t pe r o p e r l yr,e b o ot th se y s t e ms, e t *
* PS2 t loe a1v ea n d i t t h a t way! *
..................................................................
Assume Nothing 55
: N o t e :E a c hb l o c ko fc o d eb e i n gt i m e ds h o u l di d e a l l yb er u ns e v e r a l
: t i m e sw, i t h a t l e a sttw os i m i l arre a d i n g rse q u i r e dt o
: e s t a b l i s h a t r u e measurement, i no r d e tr oe l i m i n a t e any
: v a r i a b i l ict ay u s ebi ndyt e r r u p t s .
: N o t e :I n t e r r u p t sm u s tn o tb ed i s a b l e df o rm o r et h a n 54 ms a t a
: s t r e t c dh u r i n tgh tei m i n ign t e r v a lB. e c a u s ien t e r r u p t s
: a reen a b l e dk,e y sm, i c ea,nodt h edre v i c etsh agte n e r a t e
: i n t e r r u p t s h o u l dn o t b ue s e d u r i n tgh tei m i n ign t e r v a l .
: Note: Any e x t r ac o d er u n n i n go f ft h et i m e ri n t e r r u p t( s u c ha s
: some m e m o r y - r e s i d e nut t i l i t i e s ) will i n c r e a stehtei m e
: measured
by
the Zen t i m e r .
: N o t e :T h e s er o u t i n e sc a ni n t r o d u c ei n a c c u r a c i e so f UD t o a few
t e n t h s o f a second i n t o t h e s y s t e m c l o c k c o u n t f o r e a c h
c o d es e c t i o nt i m e d .C o n s e q u e n t l y ,i t ' s a g o o di d e at o
r e b o o t a t t h ec o n c l u s i o no ft i m i n gs e s s i o n s .( T h e
b a t t e r y - b a c k e dc l o c k , i f any. i s n o t a f f e c t e d b yt h e Zen
timer.)
: Al r e g i s t e r s and a l lf l a g sa r ep r e s e r v e db ya l lr o u t i n e s .
S e t P S 2 t o 0 t o a s s e m b l ef o ru s e ona f u l l y8 2 5 3 - c o m p a t i b l e
system: when PS2 i s 0. t h er e a d i n g sa r em o r er e l i a b l e i f the
c o m p u t e rs u p p o r t st h eu n d o c u m e n t e dt i m e r - s t o p p i n gf e a t u r e ,
b u t may b eb a d l yo f f i f t h a tf e a t u r ei sn o ts u p p o r t e d .I n
f a c t , t i m e r - s t o p p i n g may i n t e r f e r e w i t h y o u r c o m p u t e r ' s
o v e r a l lo p e r a t i o nb yp u t t i n gt h e8 2 5 3i n t o an u n d e f i n e do r
i n c o r r e c ts t a t e . Use w i t hc a u t i o n ! ! !
PS2 equ 1
: B a s ea d d r e s so ft h e8 2 5 3t i m e rc h i p .
: T h ea d d r e s so ft h et i m e r 0 c o u n tr e g i s t e r si nt h e8 2 5 3 .
56 Chapter 3
; Theaddress ofthe B I O S t i m e rc o u n tv a r i a b l ei nt h e BIOS
: datasegment.
MPOPF macro
l o c a lp l .p 2
j m ps h o r tp 2
i rp el :t ;jump t o pushedaddress & p o pf l a g s
pushp2: cs : c o n srt erf autaurcdrtdnrteos s
cpal l l :ni ntehsxettr u c t i o n
endm
; Macro t o d e l a y b r i e f l y t o e n s u r e t h a t e n o u g h t i m e h a s e l a p s e d
: b e t w e e ns u c c e s s i v e 1 / 0 accesses s o t h a tt h ed e v i c eb e i n ga c c e s s e d
; canrespond t ob o t ha c c e s s e se v e no n a v e r y f a s t PC.
DELAY macro
jmp J+2
jmp J+2
jmp 6+2
endm
StartBIOSCountLowdw ? :BIOS c o u n tl o ww o r da tt h e
: s t a r to ft h et i m i n gp e r i o d
StartBIOSCountHigh dw ? :BIOS c o u nhti gwh o ratdht e
; s t a r to ft h et i m i n gp e r i o d
EndBIOSCountLow dw ? ;BIOS c o u nl ot w o ratdht e
: end o f t h et i m i n gp e r i o d
EndBIOSCountHigh dw ? :BIOS c o u n th i g hw o r da tt h e
; end o f t h e t i m i n g p e r i o d
EndTimedCount dw ? : t i m e r 0 c o u natttheen d of
: t h et i m i n gp e r i o d
Referencecount dw ? ;number oc fo u n tr se q u i r et do
: e x e c u t et i m e ro v e r h e a dc o d e
: S t r i n gp r i n t e d t or e p o r tr e s u l t s .
CurrentCountLow dw ?
C u r r e n t C o u n t H i g h dw ?
: Powers o f t e n t a b l e u s e d t o p e r f o r m d i v i s i o n by 10 when d o i n g
; d o u b l e w o r dc o n v e r s i o nf r o mb i n a r yt o ASCII.
Assume Nothing 57
100 dd
1000 dd
10000dd
100000
dd
1000000
dd
10000000
dd
100000000
dd
1000000000
dd
PowersOfTenEnd l a bweol r d
: S t r i n gp r i n t e dt or e p o r tt h a tt h eh i g hw o r do ft h e BIOS count
: c h a n g e dw h i l et i m i n g( a nh o u re l a p s e do rm i d n i g h t was c r o s s e d ) ,
: and s o t h e c o u n t i s i n v a l i d a n d t h e t e s t n e e d s t o b e r e r u n .
.....................................................................
m i n g .s t a r t to c:*
a l lRe od u t i n e *
.....................................................................
ZTimerOn
proc
near
Save t h ec o n t e x to ft h ep r o g r a mb e i n gt i m e d .
push
ax
pushf
S e tt i m e r 0 o f t h e 8253 t o mode 2 ( d i v i d e - b y - N ) . t o c a u s e
l i n e a rc o u n t i n gr a t h e rt h a nc o u n t - b y - t w oc o u n t i n g . Also stops
t i m e r 0 u n t i lt h et i m e rc o u n ti sl o a d e d ,e x c e p t onPS/2
computers.
S e tt h et i m e rc o u n tt o 0, so we know we w o n ' tg e ta n o t h e r
t i m e ri n t e r r u p tr i g h t away.
N o t e :t h i si n t r o d u c e s a ni n a c c u r a c yo fu pt o 54 ms i n t h e s y s t e m
c l o c kc o u n te a c ht i m e i t i s executed.
58 Chapter 3
DELAY
sub a1 .a1
out TIMERPOP8253.al :lsb
DELAY
out TIMER-0-8253,al :msb
: I n c a s ei n t e r r u p t sa r ed i s a b l e d ,e n a b l ei n t e r r u p t sb r i e f l yt oa l l o w
: t h ei n t e r r u p tg e n e r a t e d when s w i t c h i n gf r o m mode 3 t o mode 2 t o be
: r e c o g n i z e d .I n t e r r u p t sm u s tb ee n a b l e df o ra tl e a s t2 1 0n st oa l l o w
: t i m ef o rt h a ti n t e r r u p tt oo c c u r .H e r e , 10 j u m p sa r eu s e df o rt h e
: d e l a yt oe n s u r et h a tt h ed e l a yt i m e will b em o r et h a nl o n ge n o u g h
: evenon a v e r yf a s t PC.
pushf
sti
r e p t 10
jmp 1+2
endm
MPOPF
: S t o r et h et i m i n gs t a r t BIOS count.
: ( S i n c et h et i m e rc o u n t was j u s t s e t t o 0 . t h e B I O S c o u n t will
: s t a yt h e same f o rt h en e x t5 4 ms. s o we d o n ' t n e e d t o d i s a b l e
: i n t e r r u p t si no r d e rt oa v o i dg e t t i n g a h a l f - c h a n g e dc o u n t . )
push
ds
sub ax.ax
mov ds.ax
mov ax,ds:[TIMERPCOUNT+2]
mov cs:[StartBIOSCountHighl.ax
mov ax.ds:[TIMERPCOUNT]
mov cs:[StartBIOSCountLow],ax
POP ds
: S e tt h et i m e rc o u n tt o 0 a g a i nt os t a r tt h et i m i n gi n t e r v a l .
: R e s t o r et h ec o n t e x to ft h ep r o g r a mb e i n gt i m e da n dr e t u r nt o it.
MPOPF
POP ax
ret
ZTimerOn
endp
.....................................................................
:*c oRgt usioeamtnuctnotitadpn.iolngl e d *
.....................................................................
ZTimerO
p rfnof eca r
: Save t h ec o n t e x to ft h ep r o g r a mb e i n gt i m e d .
Assume Nothing 59
pushf
push
ax
push
cx
: I n c a s ei n t e r r u p t sa r ed i s a b l e d ,e n a b l ei n t e r r u p t sb r i e f l yt oa l l o w
: a n yp e n d i n gt i m e ri n t e r r u p tt ob eh a n d l e d .I n t e r r u p t sm u s tb e
: e n a b l e df o r a t l e a s t 210ns toallowtimeforthatinterruptto
: o c c u r .H e r e ,1 0j u m p sa r eu s e df o rt h ed e l a yt oe n s u r et h a tt h e
: d e l a yt i m e will bemorethanlongenougheven on a v e r y f a s t PC.
sti
r e p1 t0
jmp 9+2
endm
: L a t c ht h et i m e rc o u n t .
i f PS2
mov al,00000000b
out MODE-8253.al : tl ai mt cehr 0 count
: T h i s i s where a o n e - i n s t r u c t i o n - l o n gw i n d o we x i s t s on t h e PS/2.
: The t i m e rc o u n ta n dt h e B I O S c o u n tc a nl o s es y n c h r o n i z a t i o n :
: s i n c et h et i m e rk e e p sc o u n t i n ga f t e ri t ' sl a t c h e d , i t c a nt u r n
: overrightafterit'slatched andcausethe B I O S c o u n tt ot u r n
: o v e rb e f o r ei n t e r r u p t sa r ed i s a b l e d ,l e a v i n g us w i t h t h e t i m e r
: c o u n tf r o mb e f o r et h et i m e rt u r n e do v e rc o u p l e dw i t ht h e BIOS
: c o u n tf r o ma f t e rt h et i m e rt u r n e do v e r . The r e s u l t i s a c o u n t
: t h a t ' s 54 ms t o ol o n g .
else
: S e tt i m e r 0 t o mode2 ( d i v i d e - b y - N ) ,w a i t i n gf o r a 2 - b y t ec o u n t
: l o a d ,w h i c hs t o p st i m e r 0 u n t i lt h ec o u n ti sl o a d e d .( O n l yw o r k s
: on f u l l y8 2 5 3 - c o m p a t i b l ec h i p s . )
endi f
: Read t h e B I O S c o u n t .( S i n c ei n t e r r u p t sa r ed i s a b l e d ,t h e BIOS
: c o u n tw o n ' tc h a n g e . )
push
ds
ax.ax
sub
mov ds,ax
mov ax,ds:[TIMER_COUNT+2]
mov cs:[EndBIOSCountHighl,ax
mov ax,ds:[TIMERLCOUNT1
60 Chapter 3
mov cs:[EndBIOSCountLowl.ax
POP ds
; Read t h et i m e rc o u n ta n ds a v e it.
in a1 .TIMERpOp8253 :lsb
DELAY
mov ah.al
in a1 ,TIMERp0-8253
:msb
xchg
ah.al
rno m ; c o n v e r t ax neg
: r e m a i n i n gt oe l a p s e d
: count
mov cs:[EndTimedCountl.ax
: R e s t a r tt i m e r 0. w h i c hi ss t i l lw a i t i n gf o r an i n i t i a l c o u n t
: t o beloaded.
i f e PS2
DELAY
mov a1 .00110100b :mode 2 . w a i lt oit noagd a
: 2 - b y t ec o u n t
out MODEL8253,al
DELAY
sub a1 .a1
out TIMERpOp8253.al :lsb
DELAY
mov a1 ,ah
out TIMERpOp8253.al :msb
DELAY
endi f
: Time a z e r o - l e n g t hc o d ef r a g m e n t ,t og e t a r e f e r e n c ef o r how
: much o v e r h e a dt h i sr o u t i n eh a s .T i m e i t 16timesandaverage it,
: f o ra c c u r a c y ,r o u n d i n gt h er e s u l t .
mov cs:[ReferenceCountl.O
mov cx.16
cli a l l o w t o : i n toef rf r u p t s a
: p r e c i s er e f e r e n c ec o u n t
Ref Loop:
c a l l ReferenceZTimerOn
cRa lel f e r e n c e Z T i m e r O f f
1 oop Ref Loop
sti
casd:d[ R e f e r e n c e C o u n:ttlo. 8t a l + (0.5 * 16)
mov c l .4
s hcr s : [ R e f e r e n c e C o u n t l . c:l( t o t a l ) / 16 + 0.5
; R e s t o r et h ec o n t e x to ft h ep r o g r a mb e i n gt i m e da n dr e t u r nt o it.
POP cx
POP ax
MPOPF
ret
Assume Nothing 61
ZTimerOffendp
: C a l l e db yZ T i m e r O f ft os t a r tt h et i m e rf o ro v e r h e a dm e a s u r e m e n t s .
ReferenceZTimerOnproc
near
: Save t h ec o n t e x to ft h ep r o g r a mb e i n gt i m e d .
push
ax
pushf
: S e tt i m e r 0 o f t h e 8253 t o mode 2 ( d i v i d e - b y - N ) .t oc a u s e
: l i n e a rc o u n t i n gr a t h e rt h a nc o u n t - b y - t w oc o u n t i n g .
a1
mov .00110100b ;mode 2
out MODE-8253.al
: Set t h et i m e rc o u n tt o 0
DELAY
sub a 1 ,a1
out TIMER-0-8253.al :lsb
DELAY
out TIMERPOP8253.al
;msb
: R e s t o r et h ec o n t e x t o f t h ep r o g r a mb e i n gt i m e da n dr e t u r nt o it.
MPOPF
POP ax
ret
ReferenceZTimerOnendp
: C a l l e db yZ T i m e r O f f t os t o pt h et i m e r a n da d dt h er e s u l tt o
: Referencecountforoverheadmeasurements.Doesn'tneed t ol o o k
: a t t h e B I O S c o u n tb e c a u s et i m i n g a z e r o - l e n g t hc o d ef r a g m e n t
: i s n ' tg o i n gt ot a k ea n y w h e r en e a r5 4 ms.
ReferenceZTim
n peerarorOcf f
: Save t h ec o n t e x to ft h ep r o g r a mb e i n gt i m e d .
pushf
pushax
p u schx
: M a t c ht h ei n t e r r u p t - w i n d o wd e l a yi nZ T i m e r O f f
sti
rept 10
jmp $+2
endm
mov al.00000000b
out MODE-8253,al : l a t c ht i m e r
62 Chapter 3
: Read t h ec o u n ta n ds a v e it.
DELAY
in a1 ,TIMER_0_8253 ;lsb
DELAY
mov ah.al
in a1 .TIMER_0_8253 ;msb
x c hagh , a l
o wf rno m ; c o n v e r t ax neg
; remaining t o elapsed
: count
cs:[ReferenceCountl,ax
add
; R e s t o r et h ec o n t e x ta n dr e t u r n .
POP cx
POP ax
MPOPF
ret
ReferenceZTimerOffendp
.....................................................................
r et isrmeuipln;*
tosgr.t R
oc oa ul ltei nd e *
.....................................................................
Z T i m enr R
epaer rop co r t
pushf
push
ax
push
bx
push
cx
pushdx
push s i
p u sdhi
push
ds
push cs :DOS f u n c t i o n s r e q u i r e t h a t DS p o i n t
POP ds : totextto b ed i s p l a y e d on t h es c r e e n
ds assume :Code
; See i f m i d n i g h to rm o r et h a na nh o u rp a s s e dd u r i n gt i m i n g . I f so,
; n o t i f yt h eu s e r .
mov ax.[StartBIOSCountHighl
cmp ax.[EndBIOSCountHighl
jz C a l c B I O S T;i hmcoeouduri cnd htn a' tn g e ,
; s o e v e r y t h i n g ' sf i n e
aixn c
cmp ax.[EndBIOSCountHighl
j n zT e s t T o o L o n g: m i d n i g hot trw oh o u r
: b o u n d a r i e sp a s s e d , so t h e
: r e s u l t sa r en og o o d
mov ax.CEndBIOSCountLowl
cmp ax.[StartBIOSCountLowl
jb CalcBIOSTime single
:a
hour
boundary
; p a s s e d - - t h a t ' s OK. s o l o n ga s
: t h et o t a lt i m ew a s n ' tm o r e
; t h a n anhour
Assume Nothing 63
: O v e ra nh o u re l a p s e do rm i d n i g h tp a s s e dd u r i n gt i m i n g ,w h i c h
: r e n d e r st h er e s u l t si n v a l i d .N o t i f yt h eu s e r .T h i sm i s s e st h e
: casewhere a m u l t i p l e o f 24 h o u r sh a sp a s s e d ,b u tw e ' l lr e l y
: o nt h ep e r s p i c a c i t yo ft h e user t o d e t e c t t h a t c a s e .
TestTooLong:
mov ah.9
mov dx.offsT
e tu r n O v e r S t r
int 21h
jmp
short
ZTimerReportOone
: C o n v e r tt h e BIOS t i m et om i c r o s e c o n d s .
CalcBIOSTime:
mov ax.CEndBIOSCountLowl
ax.[StartBIOSCountLow]
sub
mov 54925
dx.
:number m iocfr o s e c oenadcsh
: BIOS c o u n tr e p r e s e n t s
mu1 dx
mov abs: sxi de. aet x BIOS c oi nu n t
mov cx.dx : microseconds
: C o n v e r tt i m e rc o u n tt om i c r o s e c o n d s .
: Add t i m e ra n d B I O S c o u n t st o g e t h e rt og e ta no v e r a l lt i m ei n
: microseconds.
add bx.ax
adc cx.0
: S u b t r a c tt h et i m e ro v e r h e a da n ds a v et h er e s u l t .
mov ax.[ReferenceCount]
mov s i ,8381 : c o n v e r tt h er e f e r e n c ec o u n t
mu1 si : t om i c r o s e c o n d s
mov
sdi i v
bx.ax
sub
s i , 10000
:* .E381 * 8381 / 10000 -
cx.0
sbb
mov [CurrentCountLowl.bx
mov [CurrentCountHigh].~~
: C o n v e r tt h er e s u l tt o anASCII s t r i n gb yt r i a ls u b t r a c t i o n s of
: powers o f1 0 .
64 Chapter 3
sbb dx.PowersOfTenCdi+2l
jc CTSNextPowerDown
bi nl c
mov CCurrentCountLowl.ax
mov [CurrentCountHigh].dx
jrnp CTSLoop
CTSNextPowerDown:
rnov [sil.bl
si ni c
s udbi .4
CjTnSs N e x t D i g i t
: P r i n tt h er e s u l t s .
mov ah.9
rnov d x , o f f sO
e tu t p u t S t r
int 21h
ZTirnerReportDone:
POP ds
pop di
pop si
POP dx
POP cx
POP bx
POP ax
MPOPF
ret
ZTimerReport
endp
Code
ends
end
Assume Nothing 65
If you do leave the PS2 equate at1 in Listing 3.5, you should repeat each code-timing
run several timesbefore relying on the results to beaccurate to more than 54 ms, since
variations may result from the possible lack of synchronization between the timer 0
count and the BIOS time-ofday count. Infact, it’s a good idea to time code more than
once no matter which versionof the long-period Zen timer you’re using, since inter-
rupts, which must beenabled 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/S computers. The PS/2 and 8253 considerations we’ve just discussed
apply only to the long-periodZen timer.
: L i n kw i t h LZTIMER.ASM ( L i s t i n g3 . 5 ) . LZTIME.BAT ( L i s t i n g3 . 7 )
: canbeused t o assembleand l i n kb o t hf i l e s . Code t ob e
: measuredmustbe i n t h e f i l e TESTCODE: L i s t i n g3 . 8 shows
: asample f i l e (LST3-8.ASM)whichshouldbe named TESTCODE.
: By M i c h a e A
l brash
mystack
segment
stack
para ‘STACK’
dup(?)
512
db
ends
mystack
66 Chapter 3
pop
ds : p o i n t D S t toh e code
segment.
: so d a t a a s w e l l ascodecan easily
: b ei n c l u d e di n TESTCODE
: Delay f o r 6 - 7s e c o n d s .t ol e tt h eE n t e rk e y s t r o k et h a ts t a r t e dt h e
: program come backup.
mov ah,2ch
int 21h : g e tt h ec u r r e n tt i m e
mov bh.dh : s e tt h ec u r r e n tt i m ea s i d e
Del ayLoop:
mov ah.2ch
push bx ; p r e s e r v es t a r tt i m e
int 21h : g e tt i m e
POP bx :retrievestarttime
cmp dh,bh : i s t h e new secondscount less t h a n
: t h es t a r ts e c o n d sc o u n t ?
CheckDelayTime
jnb :no
dh.60
add :yes. a m i n u t em u s th a v et u r n e do v e r ,
; so add one m i n u t e
CheckDelayTime:
s u b dh,bh : g e tt i m et h a t ' sp a s s e d
cmp dh.7 ;has i t beenmorethan 6 s e c o n d sy e t ?
jb Del
ayLoop ;notyet
: D i s p l a yt h er e s u l t s .
c aZ lTl i m e r R e p o r t
: T e r m i n a t et h ep r o g r a m .
mov ah.4ch
int 21h
S t a r t endp
Code ends
end Start
As with the precision Zen timer, the program inListing 3.6 is used by naming the file
containing the codeto be timed TESTCODE, then assembling both Listing 3.6 and
Listing 3.5 with MASM or TASM and linking the two files together byway 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 theexecutable file LZTEST.EXE.
LZTIME.BAT assumes that the file LZTIMER.ASM contains Listing 3.5 and the file
LZTEST.ASM contains Listing 3.6.
Assume Nothing 67
rem * named a st h ec o m m a n d - l i n ep a r a m e t e rL. i s t i n g3 . 5m u sbt e *
rem * named LZTIMER.ASM. and L i s t i3nm.g6ubset named *
rem * LZTEST.ASM. T toi m teh ce o d ieLn S T 3 - 8y, o u ' tdy p teh e *
rem * DOS command: *
rem * *
lst3-8 rem * l z t i m e *
rem * *
rem * N o t e t h a t MASM andLINKmustbe inthecurrentdirectoryor *
rem * o nt h ec u r r e n tp a t hi no r d e rf o rt h i sb a t c hf i l et ow o r k . *
rem * *
rem * T h i sb a t c hf i l ec a nb es p e e d e d up b ya s s e m b l i n g LZTIMER.ASM *
o vt hi n*egno n c e ,
l i n e s : trheemrem *
rem * *
rem * masm l z t i m e r : *
rem * i f e r r o r l e v ee lr r 1 o r ge on tdo *
rem * *
e. this rem * f r o m *
rem * *
brash Michael rem * By *
rem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
rem
remMake s u r e a f i l e t o t e s t was s p e c i f i e d .
rem
i f n o t x%l-x g o t oc k e x i s t
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
echo *s pPel ec ai fsye t e s t .t oa f i l e *
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
g o t oe n d
rem
remMake s u r e t h e f i l e e x i s t s .
rem
:ckexist
i f e x i s t %1 g o t od o c o p y
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
echo *s pT eh cefiifl iee,d "%1." d o ee xs ins'tt. *
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
g o t oe n d
rem
r e mc o p yt h ef i l et om e a s u r et o TESTCODE.
:docopy
copy %1t e s t c o d e
masm l z t e s t ;
i f e r r o r l e v e l 1 g o t oe r r o r e n d
masm l z t i m e r :
i f e r r o r l e v e l 1 g o t oe r r o r e n d
linklztest+lztimer:
i f e r r o r l e v e l 1 g o t oe r r o r e n d
1z t e s t
g o t oe n d
:errorend
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
echo * An e r r o r o c c u r r e d w h i l e b u i l d i n g t h e l o n g - p e r i o d Zen t i m e r . *
echo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
:end
68 Chapter 3
LISTING 3.8 LST3-8.ASM
: Measures t h ep e r f o r m a n c e o f 20.000 l o a d s o f AL from
: memory. ( U s e byrenaming t o TESTCOOE. w h i c h i s
; i n c l u d e db y LZTEST.ASM ( L i s t i n g 3 . 6 ) . LZTIME.BAT
: ( L i s t i n g 3 . 7 ) does t h i s ,a l o n gw i t ha l la s s e m b l y
: a n dT i n k i n g . )
: N o t e :t a k e sa b o u tt e nm i n u t e st oa s s e m b l e on a s l o w P C i f
; you a ur es i n g MASM
MemVar db ?
Skip:
: S t a r tt i m i n g .
call ZTimerOn
rept 20000
mov a1 , [MemVar]
endm
; S t o pt i m i n g .
cZ
a lTl i m e r O f f
When LZTIME.BAT is run ona PC with the following command line (assuming the
code in Listing 3.8 is the file LST3-8.ASM)
l z t i m el s t 3 - 8 . a s m
the result is 72,544 ps, or about 3.63 ps 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 commandcan take asmuch as 10 minutes to finish on a slow PC if you
are using MASM, with most of that time spent assembling Listing3.8. Why? Because
MASM is notoriously slow at assembling REPT blocks, and theblock in Listing 3.8 is
repeated 20,000 times.
Assume Nothing 69
(display timing results) routines can be called from C. There aretwo 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 timerfor linking toa small code model C program involves the follow-
ing steps:Change ZTimerOn to -ZTimerOn, change ZTimerOff to -ZTimerOff, change
ZTimerReport to -ZTiierReport, and change Code to -TEXT. Figure 3.2 shows the
line numbers and new states of all linesfrom Listing 3.1 that must be changed. These
changes convertthe code to use Cstyle external label namesand thesmall model C code
segment. (In C++, usethe “C” specifier,as in
e x t e r n “C” ZTimerOn(void);
when declaring thetimer routines extern, so that name-mangling doesn’t occur, and
the linker can find the routines’ C-style names.)
That’s all it takes; after doingthis, you’ll be able to use the Zen timer fromC, as, for
example, in:
ZTimerOn( :
f o r( i - 0 . x-0; i
< l
O Oi++)
;
x +- i;
ZTimerOff( ;
ZTimerReportO;
(I’m talking about the precision timer here. The long-period timer-Listing 3.5-
requires the same modifications, but todifferent lines.)
Line # Nw S t a t e
-
47 -TEXT ‘CODE’
s e g m ewn ot pr du b l i c
cs:-TEXT.
assume 4a ds:nothing
49 public -ZTimerOn.
-2TimerOff.
-2TimerReport
near
ZTimerOn
proc 140
210 ~ ZTimerOn
endp
ZnTei 2apm1reo6rcO f f
296 -ZTimerOff
endp
372 -Z T i m e r R e p oprrtn
o ec a r
assume 384 ds:-TEXT
437 -ZTimerReport endp
439 -TEXT ends
These are the lines in Listing 3.1 that must be changed for use with small code
model C, and the states of the lines after the changesare made.
70 Chapter 3
Altering the Zen timer for use in C’s large code model is a tad more complex, be-
cause in addition to the above changes, all functions, including the internal reference
timing routines that areused to calculate overhead so it can be subtracted out,must
be converted to far. Figure 3.3 shows the line numbers and new states of all lines
from Listing 3.1 that must be changed inorder to callthe Zen timer from large code
model C. Again, the line numbers are specific to the precision timer, but the long-
period timer is very similar.
The full listings for the C-callable Zen timers are presented in Chapter K on the
companion CD-ROM.
with
cs push
R e pf net receaanrl cl e Z T i m e r O n
L i n e 11 New S t a t e
-
47 PZTIMER-TEXT s e g m e nwt o r dp u b l i c ’CODE’
48 assume cs:PZTIMER-TEXT. ds:nothing
49 p u b l i c -ZTimerOn._ZTimerOff.-ZTimerReport
140 - Z T i m e r O np r o cf a r
210 -ZTimerOn endp
216 -Z T i m e r O f f p r o c f a r
267 c a l lf a rp t r ReferenceZTimerOn
268 c a l fl a pr t R
r eferenceZTimerOff
296 - ZTimerOff endp
302 R e f e r e n c e Z T i m e rpOrf nao rc
336 R e f e r e n c e Z T i m e r Opf fr of ca r
372 - Z T i m e r R e p o rpt r o fca r
384 assume ds:PZTIMER_TEXT
437 -ZTimerReportendp
439 PZTIMER-TEXT ends
These are the lines in Listing 3.1 that must be changed for use with large
code modelC, and the states of the lines after the changes are made.
Further Reading
For those of you who wish to pursue the mechanics of code measurement further,
one good article about measuring code performance with the 8253 timer is “Pro-
gramming Insight: High-Performance Software Analysis on the IBM PC,” by Byron
Sheppard, which appeared in the January, 1987 issue of Byte. For complete if some-
what cryptic information on the 8253 timer itself, I refer you to Intel’s Microsystem
Components Handbook, which is also a useful reference for a number of other PC
components, including the 8259 Programmable Interrupt Controller and the 8237
DMA Controller. For details about the way the 8253 is used in the PC, as well as a
great dealof additional information aboutthe PC’s hardware and BIOS resources, I
suggest you consult IBM’s series of technical reference manuals for the PC, XT, AT,
Model 30, and microchannel computers, such as the Models 50, 60, and 80.
For our purposes, however, it’s not critical that you understand exactly how the Zen
timer works. All you reallyneed to know is what the Zen timer can do andhow to use
it, and we’ve accomplished that in this chapter.
72 Chapter 3
Previous Home Next
be hard-pressed to manage two instructions in a microsecond). Another problem is
that thetiming code itself interferes with the state of the prefetchqueue andproces-
sor cache at the start of the code being timed, because the timing code is not
necessarily fetched and does not necessarily accessmemory in exactly the same time
sequence as the codeimmediately preceding thecode under measurement normally
does. This prefetch effect can introduce as much as 3 to 4 ps of inaccuracy. Similarly,
the state of the prefetch queue at the end of the code beingtimed affects how long
the code thatstops the timer takes to execute. Consequently, the Zen timer tends to
be more accurate for longer code sequences, since the relative magnitude of the
inaccuracy introduced by the Zen timer becomes less over longer periods.
Imperfections notwithstanding, the Zen timer is a good tool for exploring C code
and x86 family assemblylanguage, and it’s a tool we’ll use frequently for theremain-
der of this book.
Assume Nothing 73