-------------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 ---------------------