Normal quotes

This commit is contained in:
James Gregory 2013-12-30 18:34:31 +11:00
commit 18011c595a
352 changed files with 6040 additions and 6040 deletions

View file

@ -2,17 +2,17 @@
[Previous](08-03.html) [Table of Contents](index.html) [Next](08-05.html)
------------------------ --------------------------------- --------------------
It’s hard to squeeze much more performance from this code by tweaking
It's hard to squeeze much more performance from this code by tweaking
it, as exemplified by Listing 8.3, a fine-tuned assembly version of
**FindIDAverage** that was produced by looking at the assembly output of
MS C/C++ and tightening it. Listing 8.3 eliminates all stack frame
access in the inner loop, but that’s about all the tightening there is
access in the inner loop, but that's about all the tightening there is
to do. The result, as shown in Table 8.1, is that Listing 8.3 runs a
modest 11 percent faster than Listing 8.1 on a 386. The results could
vary considerably, depending on the nature of the data set searched
through (average block size and frequency of matches). But, then,
understanding the typical and worst case conditions is part of
optimization, isn’t it?
optimization, isn't it?
**LISTING 8.3 L8-3.ASM**
@ -77,14 +77,14 @@ Table 8.1 Execution Times of FindIDAverage.
* * * * *
_FindIDAverage proc near
push bp ;Save caller’s stack frame
push bp ;Save caller's stack frame
mov bp,sp ;Point to our stack frame
push di ;Preserve C register variables
push si
sub dx,dx ;IDMatchSum = 0
mov bx,dx ;IDMatchCount = 0
mov si,[bp+BlockPointer] ;Pointer to first block
mov ax,[bp+SearchedForID] ;ID we’re looking for
mov ax,[bp+SearchedForID] ;ID we're looking for
; Search through all the linked blocks until the last block
; (marked with a NULL pointer to the next block) has been searched.
BlockLoop:
@ -102,7 +102,7 @@ Table 8.1 Execution Times of FindIDAverage.
NoMatch:
add di,DATA_ELEMENT_SIZE ;point to the next element
loop IntraBlockLoop
; Point to the next block and continue if that pointer isn’t NULL.
; Point to the next block and continue if that pointer isn't NULL.
DoNextBlock:
mov si,[si+NextBlock] ;Get pointer to the next block
and si,si ;Is it a NULL pointer?
@ -110,12 +110,12 @@ Table 8.1 Execution Times of FindIDAverage.
; Calculate the average of all matches.
sub ax,ax ;Assume we found no matches
and bx,bx
jz Done ;We didn’t find any matches, return 0
jz Done ;We didn't find any matches, return 0
xchg ax,dx ;Prepare for division
div bx ;Return IDMatchSum / IDMatchCount
Done: pop si ;Restore C register variables
pop di
pop bp ;Restore caller’s stack frame
pop bp ;Restore caller's stack frame
ret
_FindIDAverage ENDP
end
@ -125,7 +125,7 @@ mix. The loop is unrolled eight times, eliminating a good deal of
branching, and **SCASW** is used instead of **CMP [DI],AX.** (Note,
however, that **SCASW** is in fact slower than **CMP [DI],AX** on the
386 and 486, and is sometimes faster on the 286 and 8088 only because
it’s shorter and therefore may prefetch faster.) This advanced tweaking
it's shorter and therefore may prefetch faster.) This advanced tweaking
produces a 39 percent improvement over the original C code—substantial,
but not a tremendous return for the optimization effort invested.
@ -146,7 +146,7 @@ but not a tremendous return for the optimization effort invested.
.code
public _FindIDAverage
_FindIDAverage proc near
push bp ;Save caller’s stack frame
push bp ;Save caller's stack frame
mov bp,sp ;Point to our stack frame
push di ;Preserve C register variables
push si
@ -156,7 +156,7 @@ but not a tremendous return for the optimization effort invested.
sub dx,dx ;IDMatchSum = 0
mov bx,dx ;IDMatchCount = 0
mov si,[bp+BlockPointer] ;Pointer to first block
mov ax,[bp+SearchedForID] ;ID we’re looking for
mov ax,[bp+SearchedForID] ;ID we're looking for
; Search through all of the linked blocks until the last block
; (marked with a NULL pointer to the next block) has been searched.
BlockLoop:
@ -165,7 +165,7 @@ but not a tremendous return for the optimization effort invested.
; Search through all the DataElement entries within this block
; and accumulate data from all that match the desired ID.
mov cx,[si+BlockCount] ;Number of elements in this block
jcxz DoNextBlock ;Skip this block if it’s empty
jcxz DoNextBlock ;Skip this block if it's empty
mov bp,cx ;***stack frame no longer available***
add cx,7
shr cx,1 ;Number of repetitions of the unrolled
@ -202,7 +202,7 @@ but not a tremendous return for the optimization effort invested.
M_IBL 2
M_IBL 1
loop IntraBlockLoop
; Point to the next block and continue if that pointer isn’t NULL.
; Point to the next block and continue if that pointer isn't NULL.
DoNextBlock:
mov si,[si+NextBlock] ;Get pointer to the next block
and si,si ;Is it a NULL pointer?
@ -210,12 +210,12 @@ but not a tremendous return for the optimization effort invested.
; Calculate the average of all matches.
sub ax,ax ;Assume we found no matches
and bx,bx
jz Done ;We didn’t find any matches, return 0
jz Done ;We didn't find any matches, return 0
xchg ax,dx ;Prepare for division
div bx ;Return IDMatchSum / IDMatchCount
Done: pop si ;Restore C register variables
pop di
pop bp ;Restore caller’s stack frame
pop bp ;Restore caller's stack frame
ret
_FindIDAverage ENDP
end