Jim Phillips (kittykat@spacestar.net) FIND 16-BIT CHECKSUM OF A FILE ------------------------------------------------------------------------------ ' PBCHKSUM.bas PowerBASIC demo program to find 16-bit checksum of a file. ' version 1.00 Written December 1999 for the public domain ' by Jim Phillips kittykat@spacestar.net ' ' This program is based on C + Assembly code in The Zen of Code Optimization ' by Michael Abrash, which I translated and revised for the PowerBASIC ' compiler. The BASIC part of the code isn't optimized to the max, but the ' Assembly code does most of the work, and that part is *fast*. On most ' files, the computer will spend more time opening and closing the file than ' finding the checksum. In other words, this code's speed is hardware ' dependent, so I'm fairly confident that further optimization won't gain you ' very much. Incidentally, I recommend the Abrash book no matter what ' language you work with. Some of his examples are real eye openers. ' '---A Few Compiler Metastatements; Change As You Wish------------------------ $COM 0 $COMPILE MEMORY $CPU 80386 $DEBUG MAP OFF $DEBUG PATH OFF $DEBUG PBDEBUG OFF $DEBUG UNIT OFF $DIM NONE $ERROR ALL OFF $EVENT OFF $FLOAT PROCEDURE $LIB COM OFF, LPT OFF $LIB GRAPH OFF, CGA OFF, EGA OFF, HERC OFF, VGA ON $LIB FULLFLOAT OFF, IPRINT OFF $OPTIMIZE SPEED $OPTION CNTLBREAK OFF $SOUND 1 $STACK 1536 $STRING 32 '(kbytes) '--------------------------------------------------------------------------- FLEXCHR$ = CHR$(0) 'Null, so padding won't affect checksum. DIM TempString AS STRING * 16384 'Fixed-length buffer is easier to tie 'into assembly portion. INPUT "Enter Path and File Name: ", PathFile$ MTIMER 'Just for testing speed.... OPEN PathFile$ FOR BINARY AS #1 CheckSum& = 0 asm push bp ;preserve value. asm push si ;preserve value. DO GET$ 1, 16384, TempString 'Get next chunk into buffer from file. Making 'buffer size a power of 2 reduces disk sector 'reads and gains some speed. 16kbytes seems a 'good compromise between old and new PC's, 'small and large files. asm cld ;tell lodsb to increment si. asm lea si, TempString ;put buffer's address offset into si. FOR Stepper = 1 TO 128 '128 in Stepper x 128 in cx = 16,384-byte buffer. asm mov cx, 128 ;initialize counter. asm mov ax, 0 ;initialize. asm mov dx, 0 ;initialize. 'Following is the loop that actually does the check-summing. CheckSumLoop: asm lodsb ;get next byte at ds:[si], put in al, incr si. asm add dx, ax ;add byte value to intermediate sum. asm loop CheckSumLoop ;continue until cx counter reaches 0. 'The intermediate sum in dx will roll over at 65,536 so pass it on to 'CheckSum& before rollover can happen, and re-initialize dx above. asm mov TempSum&, dx ;put dx value into TempSum&. CheckSum& = CheckSum& + TempSum& 'Update our intermediate total. NEXT Stepper LOOP UNTIL EOF(1) asm pop si ;restore pushed value. asm pop bp ;restore pushed value. CLOSE #1 'Must be sure to close the file.... ElapsedTime! = MTIMER/1000000 'For testing speed.... PRINT " Time:"; ElapsedTime!; "second(s)"; " Checksum:"; CheckSum& END