home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pctchnqs
/
1990
/
number5
/
l6.asm
< prev
next >
Wrap
Assembly Source File
|
1990-09-30
|
3KB
|
68 lines
; Alternative optimized assembly language version of FindIDAverage
; that requires data organized as two arrays within each block rather
; than as an array of two-value element structures. This allows the
; use of REP SCASW for ID searching.
SearchedForID equ 4 ;passed parameter offsets in the
BlockPointer equ 6 ; stack frame (skip over pushed BP
; and the return address)
NextBlock equ 0 ;field offsets in struct BlockHeader
BlockCount equ 2
BLOCK_HEADER_SIZE equ 4 ;# of bytes in struct BlockHeader
.model small
.code
public _FindIDAverage2
_FindIDAverage2 proc near
push bp ;save caller's stack frame
mov bp,sp ;point to our stack frame
push di ;preserve C register variables
push si
mov di,ds ;prepare for SCASW
mov es,di
cld
mov si,[bp+BlockPointer] ;pointer to first block
mov ax,[bp+SearchedForID] ;ID we're looking for
sub dx,dx ;IDMatchSum = 0
mov bp,dx ;IDMatchCount = 0
;***stack frame no longer available***
; Search through all of the linked blocks until the last block
; (marked with a NULL pointer to the next block) has been searched.
BlockLoop:
; Search through all the DataElement entries within this block
; and accumulate data from all that match the desired ID.
mov cx,[si+BlockCount]
jcxz DoNextBlock ;skip this block if there's no data
; to search through
mov bx,cx ;we'll use BX to point to the
shl bx,1 ; corresponding value entry in the
; case of an ID match (BX is the
; length in bytes of the ID array)
; Point to the first DataElement entry within this block.
lea di,[si+BLOCK_HEADER_SIZE]
IntraBlockLoop:
repnz scasw ;search for the ID
jnz DoNextBlock ;no match, the block is done
inc bp ;we have a match; IDMatchCount++;
add dx,[di+bx-2] ;IDMatchSum += DataPointer->Value;
; (SCASW has advanced DI 2 bytes)
and cx,cx ;is there more data to search through?
jnz IntraBlockLoop ;yes
; 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?
jnz BlockLoop ;no, continue
; Calculate the average of all matches.
sub ax,ax ;assume we found no matches
and bp,bp
jz Done ;we didn't find any matches, return 0
xchg ax,dx ;prepare for division
div bp ;return IDMatchSum / IDMatchCount
Done: pop si ;restore C register variables
pop di
pop bp ;restore caller's stack frame
ret
_FindIDAverage2 ENDP
end