I would like to make a program that will do a CRC32 checksum of files.
I have some 16 bit code, but it does not work on large files.
Can this code be used to do that?
Would I need to calculate the file size with my code and then be able to use this?
Thanks.
I have some 16 bit code, but it does not work on large files.
Can this code be used to do that?
Would I need to calculate the file size with my code and then be able to use this?
Thanks.
;Courtesy of http://source.winehq.org/source/dlls/ntdll/rtl.c
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
include windows.inc
.const
;CRC polynomial 0edb88320h
CRCTable dd 000000000h,077073096h,0ee0e612ch,0990951bah,0076dc419h,0706af48fh,0e963a535h,09e6495a3h
dd 00edb8832h,079dcb8a4h,0e0d5e91eh,097d2d988h,009b64c2bh,07eb17cbdh,0e7b82d07h,090bf1d91h
dd 01db71064h,06ab020f2h,0f3b97148h,084be41deh,01adad47dh,06ddde4ebh,0f4d4b551h,083d385c7h
dd 0136c9856h,0646ba8c0h,0fd62f97ah,08a65c9ech,014015c4fh,063066cd9h,0fa0f3d63h,08d080df5h
dd 03b6e20c8h,04c69105eh,0d56041e4h,0a2677172h,03c03e4d1h,04b04d447h,0d20d85fdh,0a50ab56bh
dd 035b5a8fah,042b2986ch,0dbbbc9d6h,0acbcf940h,032d86ce3h,045df5c75h,0dcd60dcfh,0abd13d59h
dd 026d930ach,051de003ah,0c8d75180h,0bfd06116h,021b4f4b5h,056b3c423h,0cfba9599h,0b8bda50fh
dd 02802b89eh,05f058808h,0c60cd9b2h,0b10be924h,02f6f7c87h,058684c11h,0c1611dabh,0b6662d3dh
dd 076dc4190h,001db7106h,098d220bch,0efd5102ah,071b18589h,006b6b51fh,09fbfe4a5h,0e8b8d433h
dd 07807c9a2h,00f00f934h,09609a88eh,0e10e9818h,07f6a0dbbh,0086d3d2dh,091646c97h,0e6635c01h
dd 06b6b51f4h,01c6c6162h,0856530d8h,0f262004eh,06c0695edh,01b01a57bh,08208f4c1h,0f50fc457h
dd 065b0d9c6h,012b7e950h,08bbeb8eah,0fcb9887ch,062dd1ddfh,015da2d49h,08cd37cf3h,0fbd44c65h
dd 04db26158h,03ab551ceh,0a3bc0074h,0d4bb30e2h,04adfa541h,03dd895d7h,0a4d1c46dh,0d3d6f4fbh
dd 04369e96ah,0346ed9fch,0ad678846h,0da60b8d0h,044042d73h,033031de5h,0aa0a4c5fh,0dd0d7cc9h
dd 05005713ch,0270241aah,0be0b1010h,0c90c2086h,05768b525h,0206f85b3h,0b966d409h,0ce61e49fh
dd 05edef90eh,029d9c998h,0b0d09822h,0c7d7a8b4h,059b33d17h,02eb40d81h,0b7bd5c3bh,0c0ba6cadh
dd 0edb88320h,09abfb3b6h,003b6e20ch,074b1d29ah,0ead54739h,09dd277afh,004db2615h,073dc1683h
dd 0e3630b12h,094643b84h,00d6d6a3eh,07a6a5aa8h,0e40ecf0bh,09309ff9dh,00a00ae27h,07d079eb1h
dd 0f00f9344h,08708a3d2h,01e01f268h,06906c2feh,0f762575dh,0806567cbh,0196c3671h,06e6b06e7h
dd 0fed41b76h,089d32be0h,010da7a5ah,067dd4acch,0f9b9df6fh,08ebeeff9h,017b7be43h,060b08ed5h
dd 0d6d6a3e8h,0a1d1937eh,038d8c2c4h,04fdff252h,0d1bb67f1h,0a6bc5767h,03fb506ddh,048b2364bh
dd 0d80d2bdah,0af0a1b4ch,036034af6h,041047a60h,0df60efc3h,0a867df55h,0316e8eefh,04669be79h
dd 0cb61b38ch,0bc66831ah,0256fd2a0h,05268e236h,0cc0c7795h,0bb0b4703h,0220216b9h,05505262fh
dd 0c5ba3bbeh,0b2bd0b28h,02bb45a92h,05cb36a04h,0c2d7ffa7h,0b5d0cf31h,02cd99e8bh,05bdeae1dh
dd 09b64c2b0h,0ec63f226h,0756aa39ch,0026d930ah,09c0906a9h,0eb0e363fh,072076785h,005005713h
dd 095bf4a82h,0e2b87a14h,07bb12baeh,00cb61b38h,092d28e9bh,0e5d5be0dh,07cdcefb7h,00bdbdf21h
dd 086d3d2d4h,0f1d4e242h,068ddb3f8h,01fda836eh,081be16cdh,0f6b9265bh,06fb077e1h,018b74777h
dd 088085ae6h,0ff0f6a70h,066063bcah,011010b5ch,08f659effh,0f862ae69h,0616bffd3h,0166ccf45h
dd 0a00ae278h,0d70dd2eeh,04e048354h,03903b3c2h,0a7672661h,0d06016f7h,04969474dh,03e6e77dbh
dd 0aed16a4ah,0d9d65adch,040df0b66h,037d83bf0h,0a9bcae53h,0debb9ec5h,047b2cf7fh,030b5ffe9h
dd 0bdbdf21ch,0cabac28ah,053b39330h,024b4a3a6h,0bad03605h,0cdd70693h,054de5729h,023d967bfh
dd 0b3667a2eh,0c4614ab8h,05d681b02h,02a6f2b94h,0b40bbe37h,0c30c8ea1h,05a05df1bh,02d02ef8dh
.code
CRC32_Calculate proc dwInitial:DWORD, pData:PBYTE, iLen:SDWORD
LOCAL dwCRC:DWORD
push esi
push ebx
push ecx
mov eax, dwInitial
not eax
mov dwCRC, eax
mov esi, pData
mov ecx, iLen
.while ecx > 0
push ecx
;crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
mov eax, dwCRC
mov ebx, eax ;for the next step...
shr eax, 8
xor ebx, ;...next step is here :)
and ebx, 0ffh
mov ebx, ;4 == sizeof(DWORD)
xor ebx, eax
mov dwCRC, ebx
inc esi
pop ecx
dec ecx
.endw
pop ecx
pop ebx
pop esi
mov eax, dwCRC
not eax
ret
CRC32_Calculate endp
end
If you want just _A_ hash function, use Windows' Cryptography API (if you don't mind lack of portability). It's quite fast and quite easy to use (you call 3-4 functions and get MD5 or SHA). Unfortunately I'm not sure if it supports CRC32.
Windows claims a CRC32 but it isn't.
I found some C source code but didn't feel like converting it's 26K into assembly.
I may get a C compiler and do so.
Take care,
Andy
I found some C source code but didn't feel like converting it's 26K into assembly.
I may get a C compiler and do so.
Take care,
Andy
How can your 16-bit code fail to work? You port it to 32-bit correctly, right? Then you can feed data to it even bytewise.
The snippet you've quoted seems to be OK. Some slack can be cut, though.
You may as well write your own bit-wise version, or use Intel's slice-by-X approach. It's size vs. speed tradeoff.
Once you understand the idea of CRC, implementations are not hard to come by. Simple dword-byte-bit-wise solution can be:
Polynomials over GF(2) are simple if you catch the essentials. After that you can slice'n'dice them the way you like it.
The snippet you've quoted seems to be OK. Some slack can be cut, though.
You may as well write your own bit-wise version, or use Intel's slice-by-X approach. It's size vs. speed tradeoff.
Once you understand the idea of CRC, implementations are not hard to come by. Simple dword-byte-bit-wise solution can be:
CRC_POLYNOMIAL equ 0EDB88320h
PBYTE TYPEDEF PTR BYTE
Update_CRC32 PROC USES ebx, CRC32:DWORD, pBuffer:PBYTE, cbBuffer:DWORD
mov eax, CRC32
not eax
mov edx, pBuffer
mov ecx, cbBuffer
shr ecx, 2
jz byte_wise
;;; by dword
.REPEAT
xor eax,
add edx, 4
mov bl, 32
.REPEAT
shr eax, 1
.IF CARRY?
xor eax, CRC_POLYNOMIAL
.ENDIF
dec bl
.UNTIL ZERO?
.UNTILCXZ
byte_wise: mov ecx, cbBuffer
and ecx, 3
jz done
;;; by byte
.REPEAT
xor al,
inc edx
mov bl, 8
.REPEAT
shr eax, 1
.IF CARRY?
xor eax, CRC_POLYNOMIAL
.ENDIF
dec bl
.UNTIL ZERO?
.UNTILCXZ
done: not eax
ret
Update_CRC32 ENDP
Polynomials over GF(2) are simple if you catch the essentials. After that you can slice'n'dice them the way you like it.
Thanks.
This is my first attempt to convert the 16 bit code to 32 bit.
It isn't working.
I figured it's because going to 32 bit registers is going to require some changes.
I read up on les but could not figure out what it's doing in this code.
Andy
This is my first attempt to convert the 16 bit code to 32 bit.
It isn't working.
I figured it's because going to 32 bit registers is going to require some changes.
I read up on les but could not figure out what it's doing in this code.
Andy
; crc.asm - Performs a CRC on files specified in the command line.
;
.MODEL SMALL
.486
.stack 200h
.data
initcrc dd 0FFFFFFFFh ;Initial CRC value
filename db "intel.txt",0
crlf db 0Dh,0Ah,24h
hndl dw 0 ;File handle storage.
buf dd 0 ;Dynamic storage. Do not move!
;*****************************************************
; 32 bit reverse crc table for polynomial EDB88320h (Zmodem,PKZip)
; X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
crc32tab dd 000000000h, 077073096h, 0ee0e612ch, 0990951bah, 0076dc419h
dd 0706af48fh, 0e963a535h, 09e6495a3h, 00edb8832h, 079dcb8a4h
dd 0e0d5e91eh, 097d2d988h, 009b64c2bh, 07eb17cbdh, 0e7b82d07h
dd 090bf1d91h, 01db71064h, 06ab020f2h, 0f3b97148h, 084be41deh
dd 01adad47dh, 06ddde4ebh, 0f4d4b551h, 083d385c7h, 0136c9856h
dd 0646ba8c0h, 0fd62f97ah, 08a65c9ech, 014015c4fh, 063066cd9h
dd 0fa0f3d63h, 08d080df5h, 03b6e20c8h, 04c69105eh, 0d56041e4h
dd 0a2677172h, 03c03e4d1h, 04b04d447h, 0d20d85fdh, 0a50ab56bh
dd 035b5a8fah, 042b2986ch, 0dbbbc9d6h, 0acbcf940h, 032d86ce3h
dd 045df5c75h, 0dcd60dcfh, 0abd13d59h, 026d930ach, 051de003ah
dd 0c8d75180h, 0bfd06116h, 021b4f4b5h, 056b3c423h, 0cfba9599h
dd 0b8bda50fh, 02802b89eh, 05f058808h, 0c60cd9b2h, 0b10be924h
dd 02f6f7c87h, 058684c11h, 0c1611dabh, 0b6662d3dh, 076dc4190h
dd 001db7106h, 098d220bch, 0efd5102ah, 071b18589h, 006b6b51fh
dd 09fbfe4a5h, 0e8b8d433h, 07807c9a2h, 00f00f934h, 09609a88eh
dd 0e10e9818h, 07f6a0dbbh, 0086d3d2dh, 091646c97h, 0e6635c01h
dd 06b6b51f4h, 01c6c6162h, 0856530d8h, 0f262004eh, 06c0695edh
dd 01b01a57bh, 08208f4c1h, 0f50fc457h, 065b0d9c6h, 012b7e950h
dd 08bbeb8eah, 0fcb9887ch, 062dd1ddfh, 015da2d49h, 08cd37cf3h
dd 0fbd44c65h, 04db26158h, 03ab551ceh, 0a3bc0074h, 0d4bb30e2h
dd 04adfa541h, 03dd895d7h, 0a4d1c46dh, 0d3d6f4fbh, 04369e96ah
dd 0346ed9fch, 0ad678846h, 0da60b8d0h, 044042d73h, 033031de5h
dd 0aa0a4c5fh, 0dd0d7cc9h, 05005713ch, 0270241aah, 0be0b1010h
dd 0c90c2086h, 05768b525h, 0206f85b3h, 0b966d409h, 0ce61e49fh
dd 05edef90eh, 029d9c998h, 0b0d09822h, 0c7d7a8b4h, 059b33d17h
dd 02eb40d81h, 0b7bd5c3bh, 0c0ba6cadh, 0edb88320h, 09abfb3b6h
dd 003b6e20ch, 074b1d29ah, 0ead54739h, 09dd277afh, 004db2615h
dd 073dc1683h, 0e3630b12h, 094643b84h, 00d6d6a3eh, 07a6a5aa8h
dd 0e40ecf0bh, 09309ff9dh, 00a00ae27h, 07d079eb1h, 0f00f9344h
dd 08708a3d2h, 01e01f268h, 06906c2feh, 0f762575dh, 0806567cbh
dd 0196c3671h, 06e6b06e7h, 0fed41b76h, 089d32be0h, 010da7a5ah
dd 067dd4acch, 0f9b9df6fh, 08ebeeff9h, 017b7be43h, 060b08ed5h
dd 0d6d6a3e8h, 0a1d1937eh, 038d8c2c4h, 04fdff252h, 0d1bb67f1h
dd 0a6bc5767h, 03fb506ddh, 048b2364bh, 0d80d2bdah, 0af0a1b4ch
dd 036034af6h, 041047a60h, 0df60efc3h, 0a867df55h, 0316e8eefh
dd 04669be79h, 0cb61b38ch, 0bc66831ah, 0256fd2a0h, 05268e236h
dd 0cc0c7795h, 0bb0b4703h, 0220216b9h, 05505262fh, 0c5ba3bbeh
dd 0b2bd0b28h, 02bb45a92h, 05cb36a04h, 0c2d7ffa7h, 0b5d0cf31h
dd 02cd99e8bh, 05bdeae1dh, 09b64c2b0h, 0ec63f226h, 0756aa39ch
dd 0026d930ah, 09c0906a9h, 0eb0e363fh, 072076785h, 005005713h
dd 095bf4a82h, 0e2b87a14h, 07bb12baeh, 00cb61b38h, 092d28e9bh
dd 0e5d5be0dh, 07cdcefb7h, 00bdbdf21h, 086d3d2d4h, 0f1d4e242h
dd 068ddb3f8h, 01fda836eh, 081be16cdh, 0f6b9265bh, 06fb077e1h
dd 018b74777h, 088085ae6h, 0ff0f6a70h, 066063bcah, 011010b5ch
dd 08f659effh, 0f862ae69h, 0616bffd3h, 0166ccf45h, 0a00ae278h
dd 0d70dd2eeh, 04e048354h, 03903b3c2h, 0a7672661h, 0d06016f7h
dd 04969474dh, 03e6e77dbh, 0aed16a4ah, 0d9d65adch, 040df0b66h
dd 037d83bf0h, 0a9bcae53h, 0debb9ec5h, 047b2cf7fh, 030b5ffe9h
dd 0bdbdf21ch, 0cabac28ah, 053b39330h, 024b4a3a6h, 0bad03605h
dd 0cdd70693h, 054de5729h, 023d967bfh, 0b3667a2eh, 0c4614ab8h
dd 05d681b02h, 02a6f2b94h, 0b40bbe37h, 0c30c8ea1h, 05a05df1bh
dd 02d02ef8dh
.code
begin:
mov ax,@data
mov ds,ax
mov ax,03D00h ;Open for read.
lea dx,filename ;Filename in default DTA (PSP)
int 21h
;jc error2
mov word ptr ,ax
read:
mov ah,03Fh
mov bx,word ptr
mov edx,offset buf
mov ecx,0FFFFFFFFh ;Leave room in buffer for stack.
sub ecx,edx ;Maximum buffer size.
int 21h
;jc error3
; File size is in eax
or eax,eax ;End of file?
je exit
call UpdateCRC32 ;calculate CRC.
jmp read
exit:
xor word ptr ,0FFFFh ;Finish CRC calculation.
xor word ptr ,0FFFFh
mov eax,dword ptr
call bin2hex ;Print CRC to screen.
mov eax,dword ptr
call bin2hex
mov ax,0FFFFh
mov dword ptr,eax
mov dword ptr,eax
mov dx,offset CRLF ;linefeed
mov ah,09h
int 21h
close:
mov bx,word ptr
mov ah,3Eh ;close file.
int 21h
;
; mov ah,4Fh ;Do more files.
; int 21h
; jc toDOS
; jmp findnext
toDOS:
mov ax,04C00h ;Normal exit to DOS.
int 21h
bin2hex proc near
;Convert AX to HEX ASCII output
bin2he: mov cx,4 ;4 hex digits
mov bx,10h ;divisor
bin2h1: xor dx,dx ;zero DX for 16 bit divide
div bx ;leaves quotient in AX
add dl,'0' ;convert remainder to ASCII
cmp dl,'9'
jna bin2h2
add dl,'A'-'9'-1
bin2h2: push dx ;put on stack
loop bin2h1 ;repeat
mov cx,4
bin2h3: pop ax ;pop most significant digit first
mov dl,al
mov ah,02h
int 21h
loop bin2h3
ret
bin2hex endp
UpdateCRC32 proc near
; UpdateCRC32 takes an initial CRC value and updates it from
; data in 'buf'. The updated CRC is then stored in InitCRC.
mov si,offset buf
mov cx,ax
jcxz bye
les ax,
mov dx,ES
lo2:
xor bh,bh
mov bl,al
lodsb
xor bl,al
mov al,ah
mov ah,dl
mov dl,dh
xor dh,dh
shl bx,1
shl bx,1
les bx,
xor ax,bx
mov bx,ES
xor dx,bx
loop lo2
mov ,eax ; Store result in InitCRC
mov ,edx
bye:
ret
UpdateCRC32 endp
end begin
"When in doubt, RTFM".
LES does exactly what Intel manual says about it: loads far pointer (16:16 into es:bx in your case). Segment register hardly can be useful in this context.
Are you using DOS extender? Which one? Most of them use flat model, not small.
You're calling int21/3F DOS service with ds:edx pointing to single dword read buffer, buf (crc32tab immediately follows it), yet passing 0FFFFFFFFh-offset buf (not much less than 4GiB) as it's size. Comments about dynamic storage will not allocate it automagically. Even if DOS service successfully reads from that file, it will overwrite crc32tab and, possibly, your code.
What exactly are you trying to do? For example: write real-mode program with some 32-bit registers usage; write 32-bit flat-mode program for some DOS-extender; etc.
LES does exactly what Intel manual says about it: loads far pointer (16:16 into es:bx in your case). Segment register hardly can be useful in this context.
Are you using DOS extender? Which one? Most of them use flat model, not small.
You're calling int21/3F DOS service with ds:edx pointing to single dword read buffer, buf (crc32tab immediately follows it), yet passing 0FFFFFFFFh-offset buf (not much less than 4GiB) as it's size. Comments about dynamic storage will not allocate it automagically. Even if DOS service successfully reads from that file, it will overwrite crc32tab and, possibly, your code.
What exactly are you trying to do? For example: write real-mode program with some 32-bit registers usage; write 32-bit flat-mode program for some DOS-extender; etc.
"When in doubt, RTFM".
LES does exactly what Intel manual says about it: loads far pointer (16:16 into es:bx in your case). Segment register hardly can be useful in this context.
Are you using DOS extender? Which one? Most of them use flat model, not small.
You're calling int21/3F DOS service with ds:edx pointing to single dword read buffer, buf (crc32tab immediately follows it), yet passing 0FFFFFFFFh-offset buf (not much less than 4GiB) as it's size. Comments about dynamic storage will not allocate it automagically. Even if DOS service successfully reads from that file, it will overwrite crc32tab and, possibly, your code.
What exactly are you trying to do? For example: write real-mode program with some 32-bit registers usage; write 32-bit flat-mode program for some DOS-extender; etc.
This should be in the heap as it is 16 bit code. I'll post a reply there.
Andy