-------------CRC16.ASM----------------------
;By Charles Ader
;********************************************************************
;
; Compiled with MAPLAB 4.12.12
;
;********************************************************************

        LIST    p=16C54 ; PIC16C54 is the target processor

crc_hi	equ	00EH
crc_lo	equ	00FH
STATUS	equ	3	; STATUS register F3
CARRY	equ	0	; Carry bit in status register

;********************************************************************
;               CRC Test Program
;********************************************************************

	org	0h
start	clr	crc_hi
	clr	crc_lo

	mov	W, #080H	; crc_hi:crc_lo = 00 00
	call	CRC16

	mov	W, #075H	; crc_hi:crc_lo = A0 01
	call	CRC16

	mov	W, #08AH	; crc_hi:crc_lo = 27 A0
	call	CRC16

	mov	W, #00BH	; crc_hi:crc_lo = DF A6
	call	CRC16

	mov	W, #075H	; crc_hi:crc_lo = BD 1E
	call	CRC16

	mov	W, #0C7H	; crc_hi:crc_lo = EF FC
	call	CRC16

	mov	W, #0AAH	; crc_hi:crc_lo = D3 AE
	call	CRC16

	mov	W, #075H	; crc_hi:crc_lo = C3 D2
	call	CRC16

	mov	W, #0C7H	; crc_hi:crc_lo = BA 82
	call	CRC16

	mov	W, #055H	; crc_hi:crc_lo = F3 7B
	call	CRC16

	mov	W, #043H	; crc_hi:crc_lo = 1C 73
	call	CRC16

	mov	W, #01CH	; crc_hi:crc_lo = 14 1c
	call	CRC16

	mov	W, #014H	; crc_hi:crc_lo = 00 14
	call	CRC16

	jmp	start	; crc_hi:crc_lo = 00 00

;********************************************************************
;
; CRC-16  (x^16+x^15+x^2+x^0)
; No tables, No loops, No temporary registers used.
;
; Input:  W = Data byte for CRC calculation
;         crc_hi:crc_lo 16 bit CRC register
;
; Output: crc_hi:crc_lo updated.
;
; Notes:  CARRY is trashed.
;         DIGIT CARRY is trashed.
;         ZERO is trashed.
;         W is zero on exit.
;
; 30 instructions, 31 machine cycles per byte.
;
; Copyright (C) February 8, 2000. All Right Reserved.
; Charles Ader, PO Box 940 Pleasanton, California, USA.
;
; This code started out as an example program found in
; Dallas Semiconductor Application Note 27:
;
;   Understanding and Using Cyclic Redundancy Checks
;   with Dallas Semiconductor iButton(TM) Products.
;
; The application note shows an 8051 assembly language
; routine that calculates the same CRC as the hardware
; in the DS5001/2 secure micro.
;
;********************************************************************

CRC16	xor	W, crc_lo	;W = input XOR old crc_lo
	xor	W, crc_hi	;Swap old crc_hi with W
	xor	crc_hi, W	;
	xor	W, crc_hi	;new crc_hi = input XOR old crc_lo
	mov	crc_lo, W	;new crc_lo = old crc_hi
;
; Calculate parity of crc_hi, (input XOR old crc_lo),
; an place the result in carry.
;
; Save crc_hi in W and use crc_hi as a temp
; location so we can test bits.
;
; Note: We use INCF STATUS,F to compliment
;       carry. This is safe because the XORWF
;       will clear the zero flag if any of the
;	inc	instructions are going to execute.
;
;       The	inc	can be executed a maximum of
;       four times after the XORWF before the
;       bits to the left of zero in status will
;       be affected.
;
;       We use INCF at most three time here.
;
	mov	W, crc_hi	;Save crc_hi in W
	swap	crc_hi	;Trade nibbles
	xor	crc_hi, W	;XOR high half byte with low
	rr	crc_hi	;Initialize Carry
	snb	crc_hi.0
	inc	STATUS	;Compliment carry
	snb	crc_hi.1
	inc	STATUS	;Compliment carry
	snb	crc_hi.2
	inc	STATUS	;Compliment carry
	mov	crc_hi, W	;Restore crc_hi from W
;
; Use the parity of crc_hi, (input XOR crc_lo),
; to complete the CRC calculation.
;
	mov	W, #001H
	snb	STATUS.CARRY	; If carry
	xor	crc_lo, W	; flip bit 0 of crc_lo
	mov	W, #040H
	rr	crc_hi	; shift parity into crc_hi
	snb	STATUS.CARRY	; if shift out is one
	xor	crc_lo, W	; flip bit 6 of crc_lo
	mov	W, <<crc_hi	; unshift crc_hi into W
	xor	crc_hi, W	; combine them
	rr	crc_hi	; shift parity back into crc_hi
	mov	W, #080H
	snb	STATUS.CARRY	; if shift out is one
	xor	crc_lo, W	; flip bit 7 of crc_lo

	retw	#0

;********************************************************************
;               Power on reset
;********************************************************************

	org	01FFH
	jmp	start

        end

-------------End CRC16.ASM------------------

Here is the same CRC16 routine for the x86 and 8051

----------CRC16.C for x86 start------------------------
#include <stdio.h>


/********************************************************************

  CRC-16  (x^16+x^15+x^2+x^0)
  No tables, No jumps.

  Input:  c = Data byte for CRC calculation
          usp_crc = pointer to 16 bit CRC register

  Output: CRC at pointer usp_crc is updated


  Copyright (C) February 11, 2000. All Right Reserved.
  Charles Ader, PO Box 940 Pleasanton, California, USA.

  This code started out as an example program found in
  Dallas Semiconductor Application Note 27:

    Understanding and Using Cyclic Redundancy Checks
    with Dallas Semiconductor iButton(TM) Products.

  The application note shows an 8051 assembly language
  routine that calculates the same CRC as the hardware
  in the DS5001/2 secure micro.

********************************************************************/
void crc16(unsigned short *usp_crc, unsigned char c)
{
unsigned short crc;     /* use a local temp so the compiler will */
                        /* handle all the x86 pointer crap.      */
    crc = *usp_crc;

    _asm {
        mov     al,c
        mov     cx,crc

        XOR     AL,CL
        MOV     CL,CH
        MOV     CH,AL

        LAHF
        NOT     AH
        RCR     AH,1
        RCR     AH,1
        AND     AH,1
        XOR     CL,AH

        RCR     AX,1
        SBB     AH,AH
        AND     AH,0x40
        XOR     CL,AH

        MOV     AH,AL
        XOR     AL,CH
        RCL     AH,1
        RCR     AL,1
        MOV     CH,AL
        RCR     AL,1
        AND     AL,0x80
        XOR     CL,AL

        mov     crc,cx
    }
    *usp_crc = crc;
}

/******************************************************
*         MAIN FUNCTION                               *
*******************************************************/

main()
{
unsigned int crc;
    while(1) {
        crc = 0;          /* crc = 0x0000 */
        crc16(&crc,0x80); /* crc = 0xA001 */
        crc16(&crc,0x75); /* crc = 0x27A0 */
        crc16(&crc,0x8A); /* crc = 0xDFA6 */
        crc16(&crc,0x0B); /* crc = 0xBD1E */
        crc16(&crc,0x75); /* crc = 0xEFFC */
        crc16(&crc,0xC7); /* crc = 0xD3AE */
        crc16(&crc,0xAA); /* crc = 0xC3D2 */
        crc16(&crc,0x75); /* crc = 0xBA82 */
        crc16(&crc,0xC7); /* crc = 0xF37B */
        crc16(&crc,0x55); /* crc = 0x1C73 */
        crc16(&crc,0x43); /* crc = 0x141C */
        crc16(&crc,0x1C); /* crc = 0x0014 */
        crc16(&crc,0x14); /* crc = 0x0000 */
    }
} /* end of main */
----------CRC16.C for x86 end  ------------------------

----------CRC16.A51 for 8051 start---------------------
;
; From Dallas Application note 27
;
; CRC-16  (x^16+x^15+x^2+x^0)
; No tables, No loops, No temporary registers used.
;
; This code is from Dallas Semiconductor Application Note 27:
;
;   Understanding and Using Cyclic Redundancy Checks
;   with Dallas Semiconductor iButton(TM) Products.
;
; This routine that calculates the same CRC as the hardware
; in the DS5001/2 secure micro.
;-----------------------------------------------------------------------
        NAME    CRC_test

?DT?CRC_test SEGMENT DATA
        rseg    ?DT?CRC_test
CRCH:   ds      1
CRCL:   ds      1


?CO?CRC_test    SEGMENT CODE
        RSEG    ?CO?CRC_test

        public  CRC_test

CRC_test:

        mov     CRCH,#0
        mov     CRCL,#0

        mov     A,#080H
	call	CRC16

        mov     A,#075H
	call	CRC16

        mov     A,#08AH
	call	CRC16

        mov     A,#00BH
	call	CRC16

        mov     A,#075H
	call	CRC16

        mov     A,#0C7H
	call	CRC16

        mov     A,#0AAH
	call	CRC16

        mov     A,#075H
	call	CRC16

        mov     A,#0C7H
	call	CRC16

        mov     A,#055H
	call	CRC16

        mov     A,#043H
	call	CRC16

        ljmp    CRC_test


;CALCULATE CRC16 IN PARALLEL TO THE GREATEST EXTENT PRACTICAL
;       INPUT:  BYTE TO BE INCUDED IN CRC CALCULATION IS IN ACC
;       OUTPUT: CRCH:CRCL UPDATED TO INCLUDE THE NEW BYTE
;
CRC16:
        PUSH    ACC                     ;save this in case the caller needs
it
        XRL     A,CRCL
        MOV     CRCL,CRCH               ;put the high byte of the crc in its
dest..
        MOV     CRCH,A                  ;save data xor low(crc) for later
        MOV     C,P
        JNC     CRC0
        XRL     CRCL,#001H

CRC0:
        RRC     A                       ;get the low bit in c
        JNC     CRC1
        XRL     CRCL,#040H

CRC1:
        MOV     C,ACC.7
        XRL     A,CRCH                  ;compute the results for bits P...U
        RRC     A                       ;shift them into place
        MOV     CRCH,A                  ;and save them
        JNC     CRC2
        XRL     CRCL,#080H

CRC2:
        POP     ACC                     ;and restore everything and return
        RET

        end

----------CRC16.A51 for 8051 end  ---------------------