Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

218 lines
6.9 KiB

title "Compute Checksum"
;/*++
;
; Copyright (c) 1992 Microsoft Corporation
;
; Module Name:
;
; oldxsum.asm
;
; Abstract:
;
; This module implements a function to compute the checksum of a buffer.
;
; Author:
;
; David N. Cutler (davec) 27-Jan-1992
;
; Revision History:
;
; Who When What
; -------- -------- ----------------------------------------------
; mikeab 01-22-94 Pentium optimization
;
; Environment:
;
; Any mode.
;
; Revision History:
;
;--*/
LOOP_UNROLLING_BITS equ 5
LOOP_UNROLLING equ (1 SHL LOOP_UNROLLING_BITS)
.386
.model small,c
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
assume fs:nothing,gs:nothing
.xlist
include callconv.inc
include ks386.inc
.list
.code
;++
;
; ULONG
; ChkSum(
; IN ULONG cksum,
; IN PUSHORT buf,
; IN ULONG len
; )
;
; Routine Description:
;
; This function computes the checksum of the specified buffer.
;
; Arguments:
;
; cksum - Suppiles the initial checksum value, in 32-bit (two partial
; accumulators, one in each word) form.
;
; buf - Supplies a pointer to the buffer that is checksumed.
;
; len - Supplies the of the buffer in words.
;
; Return Value:
;
; The computed checksum in 32-bit two-partial-accumulators form, added to
; the initial checksum, is returned as the function value.
;
;--
cksum equ 12 ; stack offset to initial checksum
buf equ 16 ; stack offset to source address
len equ 20 ; stack offset to length in words
to_checksum_last_word:
jmp checksum_last_word
to_checksum_done:
jmp checksum_done
cPublicProc ChkSum,3
push ebx ; save nonvolatile register
push esi ; save nonvolatile register
mov ecx,[esp + len] ; get length in words
mov eax,[esp + cksum] ; get initial checksum
test ecx,ecx ; any words to checksum at all?
jz to_checksum_done ; no words to checksum
;
; Compute checksum in large blocks of dwords, with one partial word up front if
; necessary to get dword alignment, and another partial word at the end if
; needed.
;
;
; Compute checksum on the leading word, if that's necessary to get dword
; alignment.
;
mov esi,[esp + buf] ; get source address
sub edx,edx ; set up to load word into EDX
test esi,02h ; check if source dword aligned
jz short checksum_dword_aligned ; source is already dword aligned
mov dx,[esi] ; get first word to checksum
add esi,2 ; update source address
add eax,edx ; update partial checksum
dec ecx ; count off this word (zero case gets
; picked up below)
; ***doesn't change carry flag***
adc eax,0 ; add carry in
;
; Checksum as many words as possible by processing a dword at a time.
;
checksum_dword_aligned:
shr ecx,1 ; # of dwords to checksum
jz to_checksum_last_word ; no dwords to checksum
pushf ; remember if there's a trailing word
mov edx,[esi] ; preload the first dword
add esi,4 ; point to the next dword
dec ecx ; count off the dword we just loaded
jz checksum_dword_loop_done ; skip the loop if that was the only
; dword
mov ebx,ecx ; EBX = # of dwords left to checksum
add ecx,LOOP_UNROLLING-1 ; round up loop count
shr ecx,LOOP_UNROLLING_BITS ; convert from word count to unrolled
; loop count
and ebx,LOOP_UNROLLING-1 ; # of partial dwords to do in first
; loop
jz short checksum_dword_loop ; special-case when no partial loop,
; because the 0-offset instruction is
; only 2 bytes long (carry flag is
; cleared at this point, as required
; at loop entry)
lea esi,[esi+ebx*4-(LOOP_UNROLLING*4)]
; adjust buffer pointer back to
; compensate for hardwired displacement
; at loop entry point
; ***doesn't change carry flag***
jmp loop_entry[ebx*4] ; enter the loop to do the first,
; partial iteration, after which we can
; just do 64-word blocks
; ***doesn't change carry flag***
checksum_dword_loop:
DEFLAB macro pre,suf
pre&suf:
endm
TEMP=0
REPT LOOP_UNROLLING
deflab loop_entry_,%TEMP
adc eax,edx
mov edx,[esi + TEMP]
TEMP=TEMP+4
ENDM
checksum_dword_loop_end:
lea esi,[esi + LOOP_UNROLLING * 4] ; update source address
; ***doesn't change carry flag***
dec ecx ; count off unrolled loop iteration
; ***doesn't change carry flag***
jnz checksum_dword_loop ; do more blocks
checksum_dword_loop_done:
adc eax,edx ; finish dword checksum
adc eax,0
sub edx,edx ; prepare to load trailing word
popf ; get back trailing word status
;
; Compute checksum on the trailing word, if there is one.
; High word of EDX = 0 at this point
; Carry flag set iff there's a trailing word to do at this point
;
checksum_last_word label proc ; "proc" so not scoped to function
jnc short checksum_done ; no trailing word
mov dx,[esi] ;
add eax,edx ; add in the trailing word
adc eax,0 ;
checksum_done label proc ; "proc" so not scoped to function
pop esi ; restore nonvolatile register
pop ebx ; restore nonvolatile register
stdRET ChkSum
REFLAB macro pre,suf
dd pre&suf
endm
align 4
loop_entry label dword
dd 0
TEMP=LOOP_UNROLLING*4
REPT LOOP_UNROLLING-1
TEMP=TEMP-4
reflab loop_entry_,%TEMP
ENDM
stdENDP ChkSum
end