I would like to change this to your typical program with data declarations first then code so I don't have to have all those code segment overrides. I am adding more code later, this just checks if there has been any


; chksum.asm Masm code
; Checksum this file up to stored_value(4 bytes)
; Use checksum.exe to calculate the stored_value
; Autodin-II CRC-32 algorithmn
; Much help from Jeff


sseg segment para stack use16 'STACK'
dw 128 dup(?) ; reserve 256 bytes
sseg ends

assume cs:code

call setFree ; free unused DOS memory

mov ax, (32 * 1024) / 16 ; now request 32k of memory
call memAlloc ; for file buffer
mov cs:, ax ; save segment to variable
push cs
pop ds

lea dx, filename
mov ax, 03D00h ; Open for read.
int 21h

push cs
pop ds
jnc fileOk
jmp error2 ; file open error?

mov word ptr cs:, ax

; AH = 42h
; AL = origin of move
; 00h start of file
; 01h current file position
; 02h end of file
; BX = file handle
; CX:DX = (signed) offset from origin of new file position
;Return: CF clear if successful
; DX:AX = new file position in bytes from start of file
; CF set on error
; AX = error code (01h,06h) (see #01680 at AH=59h/BX=0000h)

; find the size of the file we want to CRC

xor cx, cx ; Read length of file
xor dx, dx ;
mov bx, cs: ; get file handle
mov ax, 4202h ; move to end of file
int 21h ; dx:ax has file size
; dx has # of 64k chunks
; we need # 32k chunks
shl dx, 1 ; so double it.
mov cs:, dx ; save counter
inc cs: ; make counter 1 based

sub ax, 4 ; don't do last 4 bytes

cmp ax, 32 * 1024 ; is leftover > 32k?
jb sizeOK ; add 1 to chunk counter
inc cs: ; and remove 32k from size
sub ax, 32 * 1024


mov cs:, ax ; save # of leftovers

xor cx, cx ; pos file back to start
xor dx, dx
mov bx, cs:
mov ax, 4200h
int 21h

mov cx, 32 * 1024 ; read 32k
cmp cs:, 1 ; is this the last 32k chunk?
jnz notLast ; yes,
mov cx, cs: ; then read the remainder

mov ah, 03Fh ; read function
mov bx, word ptr cs: ; get file handle
mov dx, cs: ; point DS:DX to file buffer
mov ds, dx ;
xor dx, dx ;
int 21h ; read bytes into memory
jc error3 ; ax=# of bytes read

xor si, si ; point DS:SI to buffer
call updateCRC32 ; do calculation
dec cs: ; decrement chunk counter
jnz read ; not finished? loop again

; complete file has been read

push cs ; set segments back to code
pop ds

xor word ptr cs:, 0FFFFh ; Finish CRC calculation.
xor word ptr cs:, 0FFFFh
mov bx, word ptr cs:
mov ah, 3Eh ; close file.
int 21h

; See if this file has been modified by
; doing a checksum and comparing to a stored checksum value

mov eax,cs:
mov ebx,cs:
cmp eax,ebx
jnz mod_made

exit: ;Instead of exiting, continue on with code for program

mov ah, 4Ch ; exit with errorlevel
int 21h

mov ah,9
lea dx,tamper
int 21h
mov al,1
jmp exit


mov ah, 09h
lea dx, errmsg2
int 21h
mov al, 2h ; Exit errorlevel 2.
jmp exit


mov ah, 09h
lea dx, errmsg3
int 21h
mov al, 3h ; Exit errorlevel 3.
jmp exit

; UpdateCRC32 takes an initial CRC value and updates it from
; data in file buffer. The updated CRC is then stored in InitCRC.
; input: DS:SI points to buffer to calculate
; AX=number of bytes to process

UpdateCRC32 proc near
mov cx, ax
jcxz bye
les ax, cs:
mov dx, ES
xor bh, bh
mov bl, al
xor bl, al
mov al, ah
mov ah, dl
mov dl, dh
xor dh, dh
shl bx, 1
shl bx, 1
les bx, cs:
xor ax, bx
mov bx, ES
xor dx, bx
loop lo2
mov word ptr cs:, ax ; Store result in InitCRC
mov word ptr cs:, dx
UpdateCRC32 endp

;-- SETFREE: Release memory not used ----------------
;-- Input : ES = address of PSP
;-- Output : none
;-- Register : AX, BX, CL and FLAGS are changed
;-- Info : Since the stack-segment is always the last segment in an
; EXE-file, ES:0000 points to the beginning and SS:SP
; to the end of the program in memory. Through this the
; length of the program can be calculated
; call this routine once at the beginning of the program to free up memory
; assigned to it by DOS.

setfree proc near

mov bx,ss ;first subtract the two segment addresses
mov ax,es ;from each other. The result is
sub bx,ax ;number of paragraphs from PSP
;to the beginning of the stack
mov ax,sp ;since the stackpointer is at the end of
mov cl,4 ;the stack segment, its content indicates
shr ax,cl ;the length of the stack
add bx,ax ;add to current length
inc bx ;as precaution add another paragraph

mov ah,4ah ;pass new length to DOS
int 21h
ret ;back to caller

setfree endp

memalloc proc

; input: AX = # of paragraphs required
; output: AX = segment of block to use
push bx
mov bx, ax
mov ah, 48h
int 21h
pop bx
memalloc endp

; 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

initcrc dd 0FFFFFFFFh ;Initial CRC value

errmsg2 db 'Error 2, cannot open file.',0Dh,0Ah,24h
errmsg3 db 'Error 3, cannot read file.',0Dh,0Ah,24h
tamper db 'File has been altered !!'

crlf db 0Dh,0Ah,24h
fileBufSeg dw 0 ; storage for file buffer seg
hndl dw 0 ; File handle storage.
chunks dw 0 ; # of 32k chunks in file
remainder dw 0 ; # of bytes leftover
filename db "chksum.exe",0

; checksum is done on file up to here
stored_value dd 0203605DEh

End Start
Posted on 2004-03-30 06:54:17 by skywalker
hihihi ...

Call exorcism()

just joking ...
Posted on 2004-03-30 07:36:15 by BogdanOntanu
You are already setting DS equal to CS. All DOS file functions return with DS unchanged, so you only have to set it once at the beginning and once after you read form the file. You can do away with the CS: prefixes and it will work fine.
Btw, I sense some bloat in the code, like setting DX equal to and then not using it. And I suggest you change the code right after the call to get the file size to the following:
sub ax,4

sbb dx,-1
add ax,ax
rcl dx,1
shr ax,1
mov [chunks],dx
mov [remainder],ax
This ensures that it won't pick up the prison soap when the low byte of the file size is less than 4.
You might also want to rearrange the reading loop somewhat and make the counter 0 based.
Posted on 2004-03-31 11:49:40 by Sephiroth3
You could also generate the CRC32 table at program startup, instead of hardcoding the large table in your app.
Posted on 2004-03-31 11:50:42 by f0dder

You could also generate the CRC32 table at program startup, instead of hardcoding the large table in your app.

Could you help me with that. It sounds like it would save some bytes.

Posted on 2004-03-31 13:27:19 by skywalker
A little board search and googling turned up this:
http://www.asmcommunity.net/board/index.php?topic=17782&highlight=crc32 - 32bit asm CRC32 & tableinit
http://search.cpan.org/src/PMQS/Compress-Zlib-1.33/zlib-src/crc32.c - C CRC32 & tableinit
http://www.bsdg.org/swag/CRC/0010.PAS.html - pascal CRC32 & tableinit

There's bound to be a LOT of code around, and probably ready-to-use 16bit tableinit as well, but google is your friend there - I only returned some quick hits :)
Posted on 2004-03-31 13:45:59 by f0dder
Since you are interested in 16-bit coding, I suggest you to try the linker from Digital Mars. It creates MZ signed executables with smaller file header.

Posted on 2004-04-02 04:16:56 by Vortex

Since you are interested in 16-bit coding, I suggest you to try the linker from Digital Mars. It creates MZ signed executables with smaller file header.


I found a C and C++ compiler but no separate linker. How much smaller a file header is it capable of.

Posted on 2004-04-02 06:36:55 by skywalker
Vortex, does the DM linker support 16bit execytables, though?
Posted on 2004-04-02 07:00:52 by f0dder

Yes, the DM linker supports 16-bit executables, you can check the attachment.


You can download the C/C++ compiler package including the linker from:


A simple hello world application linked with DM linker : 79 bytes
MS 16-bit linker : 543 bytes
Posted on 2004-04-03 02:53:33 by Vortex