2024-04-29

Navigation

Skip Navigation Links

Hash algorithms

Asymmetric Algorithms

Symmetric Cipher Algorithms

Encoding Algorithms

Compression Algorithms

Pseudo Random Number Algorithms

Steganography

Library Wrappers

String Comparison

Others

Syntax highlighting by Prism
PBCrypto.com Mirror

CRC-16

Algorithm creator(s)

n/a


PB author(s)

Marc Sven Schulte, Mark Pruitt


Description

Very fast algorithm that creates a 16-bit checksum.


Note

Marc Sven Schulte's assembly implentation and Mark Pruitt's PB version are included.


Source

https://forum.powerbasic.com/forum/user-to-user-discussions/source-code/24576-crc-16-routines?t=23940


See also

n/a


Source Code

Download source code file crc16.bas (Right-click -> "Save as ...")

'#####################################################################################
'CRC16, by Marc Sven Schulte, 19th October 2003.

FUNCTION CRC16(BYVAL Address AS DWORD, _
  BYVAL Length AS LONG, BYVAL Seed AS WORD) AS WORD
  #REGISTER NONE
  ! MOV BX, Seed
  ! MOV ESI, Length
  ! CMP ESI, 0
  ! JZ  QuitLoop
  ! MOV EDI, Address
  ! XOR EAX, EAX
  NextByte:
  ! MOV AL, BL
  ! XOR AL, [EDI]
  ! MOV CX, CrcTable[2*EAX]
  ! SHR BX, 8
  ! XOR BX, CX
  ! INC EDI
  ! DEC ESI
  ! JNZ NextByte
  QuitLoop:
  ! MOV FUNCTION, BX
  EXIT FUNCTION
  CrcTable:
  ! DW &H00000, &H0C0C1, &H0C181, &H00140, &H0C301, &H003C0, &H00280, &H0C241
  ! DW &H0C601, &H006C0, &H00780, &H0C741, &H00500, &H0C5C1, &H0C481, &H00440
  ! DW &H0CC01, &H00CC0, &H00D80, &H0CD41, &H00F00, &H0CFC1, &H0CE81, &H00E40
  ! DW &H00A00, &H0CAC1, &H0CB81, &H00B40, &H0C901, &H009C0, &H00880, &H0C841
  ! DW &H0D801, &H018C0, &H01980, &H0D941, &H01B00, &H0DBC1, &H0DA81, &H01A40
  ! DW &H01E00, &H0DEC1, &H0DF81, &H01F40, &H0DD01, &H01DC0, &H01C80, &H0DC41
  ! DW &H01400, &H0D4C1, &H0D581, &H01540, &H0D701, &H017C0, &H01680, &H0D641
  ! DW &H0D201, &H012C0, &H01380, &H0D341, &H01100, &H0D1C1, &H0D081, &H01040
  ! DW &H0F001, &H030C0, &H03180, &H0F141, &H03300, &H0F3C1, &H0F281, &H03240
  ! DW &H03600, &H0F6C1, &H0F781, &H03740, &H0F501, &H035C0, &H03480, &H0F441
  ! DW &H03C00, &H0FCC1, &H0FD81, &H03D40, &H0FF01, &H03FC0, &H03E80, &H0FE41
  ! DW &H0FA01, &H03AC0, &H03B80, &H0FB41, &H03900, &H0F9C1, &H0F881, &H03840
  ! DW &H02800, &H0E8C1, &H0E981, &H02940, &H0EB01, &H02BC0, &H02A80, &H0EA41
  ! DW &H0EE01, &H02EC0, &H02F80, &H0EF41, &H02D00, &H0EDC1, &H0EC81, &H02C40
  ! DW &H0E401, &H024C0, &H02580, &H0E541, &H02700, &H0E7C1, &H0E681, &H02640
  ! DW &H02200, &H0E2C1, &H0E381, &H02340, &H0E101, &H021C0, &H02080, &H0E041
  ! DW &H0A001, &H060C0, &H06180, &H0A141, &H06300, &H0A3C1, &H0A281, &H06240
  ! DW &H06600, &H0A6C1, &H0A781, &H06740, &H0A501, &H065C0, &H06480, &H0A441
  ! DW &H06C00, &H0ACC1, &H0AD81, &H06D40, &H0AF01, &H06FC0, &H06E80, &H0AE41
  ! DW &H0AA01, &H06AC0, &H06B80, &H0AB41, &H06900, &H0A9C1, &H0A881, &H06840
  ! DW &H07800, &H0B8C1, &H0B981, &H07940, &H0BB01, &H07BC0, &H07A80, &H0BA41
  ! DW &H0BE01, &H07EC0, &H07F80, &H0BF41, &H07D00, &H0BDC1, &H0BC81, &H07C40
  ! DW &H0B401, &H074C0, &H07580, &H0B541, &H07700, &H0B7C1, &H0B681, &H07640
  ! DW &H07200, &H0B2C1, &H0B381, &H07340, &H0B101, &H071C0, &H07080, &H0B041
  ! DW &H05000, &H090C1, &H09181, &H05140, &H09301, &H053C0, &H05280, &H09241
  ! DW &H09601, &H056C0, &H05780, &H09741, &H05500, &H095C1, &H09481, &H05440
  ! DW &H09C01, &H05CC0, &H05D80, &H09D41, &H05F00, &H09FC1, &H09E81, &H05E40
  ! DW &H05A00, &H09AC1, &H09B81, &H05B40, &H09901, &H059C0, &H05880, &H09841
  ! DW &H08801, &H048C0, &H04980, &H08941, &H04B00, &H08BC1, &H08A81, &H04A40
  ! DW &H04E00, &H08EC1, &H08F81, &H04F40, &H08D01, &H04DC0, &H04C80, &H08C41
  ! DW &H04400, &H084C1, &H08581, &H04540, &H08701, &H047C0, &H04680, &H08641
  ! DW &H08201, &H042C0, &H04380, &H08341, &H04100, &H081C1, &H08081, &H04040
END FUNCTION

FUNCTION PBMAIN() AS LONG
  DIM buffer AS STRING, crc AS DWORD
  buffer = "1234567890"
  crc = CRC16(STRPTR(buffer), LEN(buffer), crc)
  MSGBOX "CRC16: " & HEX$(crc, 4) & " (should be: C57A)"
END FUNCTION



'#####################################################################################

    '**********************************************************************************************************************
    '   I needed these CRC-16 routines to calculate the CRC for each byte of data in a string, accumulate the value in
    '     CrcReg??, and then use the final value of CrcReg?? to calculte a final Block Check Character (two; one byte each).
    '     These may be useful to someone.  Should be easy to modify.  Kev Peel and Tom Hanlin (and possibly others) may
    '     remember helping me in translating some of these from C.  Thanks again.  Feel free to use/modify this code.
    '
    '   - CRC-16 Routines
    '   - Create a unique CRC-16 lookup table by changing the values of c%(0) through c%(7)
    '   - Calculate CRC value by passing data one byte at a time to  CalculateCRC16 as databyte? until all bytes are passed
    '       Can be used to calculate CRC16 for your transmit string, or to calculate the CRC16 of a received string
    '       Last two bytes of received string (for my purposes) are the Most Significant Byte and then Least Significant
    '       Byte of of the final Block Check Character - can be omitted if you don't need them.
    '   - Final BCC (Block Check Character) composed of two one byte pieces of data, BCC1?, and BCC2?
    '       Convert these to byte sized bit patterns with MKBYT$ before appending to end of string
    ' 
    '
    '
    '
    '********************************************************************************************************************** 
 
'create a 256 element look up table based on a unique mask/rule set
FUNCTION MakeLookUpTable () AS LONG 
    GLOBAL CrcReg??
    GLOBAL table?? ()
    LOCAL c% ()
    LOCAL d$
    LOCAL i&, j&, mask&
    REDIM table??(0 TO 255)
    REDIM c%(0 TO 7)         'these hex values create a unique look up table, change values to change the table
            c%(0) = &h1001
            c%(1) = &h2002
            c%(2) = &h4004
            c%(3) = &h8118
            c%(4) = &h1221
            c%(5) = &h2482
            c%(6) = &h48A4
            c%(7) = &h3AB8
    FOR i& = 0 TO 255
            table??(i&) = 0
            mask& = &h0001
                FOR j& = 0 TO 7
            IF(i& AND mask&) THEN table??(i&) = table??(i&) XOR c%(j&)
            SHIFT LEFT mask&, 1
            NEXT j&
            d$ = HEX$(table??(i&))
                NEXT i&
            FUNCTION = 0
    END FUNCTION
    '*************************************************************************************************************
FUNCTION ResetCRC ()  AS LONG
    CrcReg?? = 0    'reset CrcReg?? before calculating new string
    END FUNCTION
    '*************************************************************************************************************
' calculate the CRC-16; call this routine until all bytes of data have been passed to it, then call GetBCC1BisyncByte
FUNCTION CalculateCrc16 (databyte?)  AS LONG 
    LOCAL s??,  CrcCopy??
            CrcCopy?? = CrcReg??    'make a copy because SHIFT changes the value of CrcReg??
          s?? = 0
          SHIFT RIGHT CrcCopy??, 8
          s?? = (databyte? AND &h00ff) XOR (CrcCopy?? AND &h00ff) 'databye? is one byte of data extracted from data string
          SHIFT LEFT CrcReg??, 8
            CrcReg?? = (CrcReg??  XOR table??(s??))
    END FUNCTION
    '********************************************************************************************************************
    'get first block check character  (MSB(yte))
FUNCTION GetBCC1BisyncByte () AS LONG
    STATIC BCC1?
    LOCAL a$, CRC??
              CRC?? = CrcReg??      'make a copy of the value of CrcReg?? 
            SHIFT RIGHT CRC??, 8
              BCC1? = NOT (CRC?? AND 255)
                    CALL GetBCC2BisyncByte (BCC1?)
        END FUNCTION
'******************************************************************************************************************************
 'get second block check character (LSB(yte))
FUNCTION GetBCC2BisyncByte (BCC1?) AS LONG 
    STATIC BCC2?
    BCC2? = NOT(CrcReg?? AND 255)
        blockcheck$ =  MKBYT$(BCC1?) +  MKBYT$(BCC2?)    'blockcheck$ is a global variable declared elsewhere 
    END FUNCTION
'       ******************************************************************************************************************** 
------------------
' Mark Pruitt
' markspruitt@yahoo.com

'#####################################################################################

Mirror provided by Knuth Konrad