checksum proc far
; ES:SI = Buffer
;    CX = length
         cld
         xor  ax, ax
         jcxz cs_x
cs_l:
         xor  bx, bx
         mov  bl, byte ptr es:[si]
         add  ax, bx
         inc  si
         loop cs_l
cs_x:
         ret
checksum endp

CRC16   proc far
; CRC16 = SUM = X^16+X^12+X^5+1
; Pass    - DS:SI = pointer to the buffer
;         - CX    = length of the buffer 
; Returns - DX    = CRC16 of the buffer  

         PUSH AX
         PUSH BX
         PUSHF
         CLD                      ; Move forward through the buffer

         ;SUB  DX,DX               ; CRC := 0000h 

C1:      LODSB                    ; AL := byte at DS:SI
         SUB  AH,AH

         XCHG AH,AL               ; AX := 256 * AL
         XOR  DX,AX               ; CRC := CRC xor AX

         PUSH CX
         MOV  CX,8

C2:      MOV  BX,DX
         SHL  DX,1

         AND  BX,8000h
         JZ   C3

         XOR  DX,1021h
C3:      LOOP C2
         POP  CX

         LOOP C1

         POPF
         POP  BX
         POP  AX
         RET
CRC16    endp

ethercrc32 proc    far
       mov  ecrcbyte, al
       mov  cx, 7
ethcrc32:
       mov  al, ecrcbyte
       xor  ah, ah
       xor  dx, dx
       les  di, dword ptr ethercrc
       xor  ax,es:[di]
       xor  dx,es:[di+2]
       and  ax,1
       and  dx,0
       cmp  dx,0
       jg   ecrc32_1
       jl   ecrc32_2            
       cmp  ax,0
       jbe  ecrc32_2            
ecrc32_1:
       les  di,dword ptr ethercrc
       mov  ax,es:[di]
       mov  dx,es:[di+2]
       mov  bx, ETHERPOLY
       xor  ax, bx
       mov  bx, ETHERPOLY2
       xor  dx, bx
       mov  es:[di], ax
       mov  es:[di+2], dx
       jmp  ecrc32_o
ecrc32_2:
       les  di,dword ptr ethercrc
       mov  ax,es:[di]
       mov  dx,es:[di+2]
       shr  dx, 1
       shr  ax, 1
       ; account for leftover bit
       xor  bx, bx
       jnc  ecrc32_p
       mov  bx, 80h
ecrc32_p:
       or   dx, bx
       mov  es:[di],ax
       mov  es:[di+2],dx
ecrc32_o:
       mov  al, ecrcbyte
       xor  ah, ah
       shr  ax, 1
;       cwd
       mov  ecrcbyte, al
       loop ethcrc32
       ret
ethercrc  dd  0
ecrcbyte  db  0
ETHERPOLY  EQU 0edb8h
ETHERPOLY2 EQU 8320h
ethercrc32 endp

; ===========================================================================
self_check proc far
; AX = start
; BX = end
; output : AX = CRC
;          CF = CY if failed self check
; ===========================================================================
     push ds
     mov  si, ax
     sub  ax, bx
     mov  cx, ax
     push cs
     pop  ds
     call cs:crc16
     mov  ax, dx
     pop  ds
     ret
self_check endp

