home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-01-01 | 8.6 KB | 231 lines | [TEXT/ttxt] |
- #: 38344 S3/Mac Programming
- 27-Aug-86 21:42:45
- Sb: #38303-CRC's
- Fm: Bela Lubkin/Amiga Forum 73047,1112
- To: Jerry LeVan 76354,364
-
- These functions were written by Wayne Davison 76703,615 for my AmigaBinary
- spec. I don't know enough about Mac C or assembly to know how portable they
- will be to your application, but they look like decently generic C and 68K
- assembly. They implement the DDJ algorithm, and they definitely work. Use a
- starting CRC value of 0 to get the output you need for XMODEM...
- /*
- In Lattice/Aztec C, by Wayne Davison:
- */
- #define UWORD unsigned short /* 16 bits */
- UWORD compute_crc(crc,bufptr,len)
- UWORD crc;
- char *bufptr;
- short len;
- {
- int i;
- while (len--) {
- crc ^= (UWORD)(*bufptr++) << 8;
- for (i = 0; i < 8; ++i) {
- if (crc & 0x8000)
- crc = (crc << 1) ^ 0x1021;
- else
- crc <<= 1;
- }
- }
- return(crc);
- }
-
- *
- * In 68000 assembly language, by Wayne Davison:
- *
- ************
- compute_crc:
- ************
- * Entry:
- * A0 -> data buffer
- * D1 == length
- * D0 == CRC value
- * D0 == new CRC value
- * Changed:
- * D0,D1,D2,A0
- *
- bra crc_entry
- crc_loop:
- move.b (a0)+,d2 ; put char into d2
- asl.w #8,d2 ; shift it into high byte of word
- eor.w d2,d0 ; eor result into crc
- moveq #7,d2 ; set loop counter to 8 iters (7-0)
-
- crc_inner_loop:
- asl.w #1,d0 ; shift crc left 1 bit
- bcc next_crc ; skip eor if no carry
- eor.w #$1021,d0 ; eor in the magic number
- next_crc:
- dbf d2,crc_inner_loop ; loop for all 8 bits
- crc_entry:
- dbf d1,crc_loop ; continue if more chars
- rts
-
- - Bela
-
- *** Reading replies to 38303 ***
- *** More ***
-
-
- #: 38370 S3/Mac Programming
- 28-Aug-86 02:04:24
- Sb: #38303-CRC's
- Fm: Steve Brecher 70001,1011
- To: Jerry LeVan 76354,364
-
- Shift and xor, but at least fast shift and xor -- (I don't have a table lookup
- routine coded)...
-
- ; untested asm routines (MDS format local labels)
-
- ; function xmttedCRC(theData: datablock): integer;
- ; *** theData must start on a word boundary ***
- ; returns CRC to be transmitted (transmit high byte first)
- xmttedCRC:
- Move.L (SP)+,A1 ;return address
- Move.L (SP)+,A0 ;pointer to data
- Move.L D3,-(SP) ;preserve
- Move.L #$10210000,D0 ;constant in high word
- MoveQ #0,D1 ;init CRC result (in high word)
- MoveQ #128/2-1,D3 ;for Dbra outer loop
- @0 MoveQ #16-1,D2 ;for Dbra inner loop
- Move (A0)+,D1 ;two data bytes
- @1 Add.L D0,D0 ;shift data bytes and CRC left
- Bcc.S @2 ;br if bit shifted out of CRC was clear
- Eor.L D0,D1 ;was set: xor CRC with constant
- @2 Dbra D2,@1 ;end inner loop
- Dbra D3,@0 ;end outer loop
- Clr D1 ;two 0 bytes
- MoveQ #16-1,D2 ;update for two 0 bytes...
- @3 Add.L D1,D1 ;shift CRC left
- Bcc.S @4 ;br if bit shifted out of CRC was clear
- Eor.L D0,D1 ;was set: xor CRC with constant
- @4 Dbra D2,@3 ;end loop
- Move.L (SP)+,D3 ;restore
- Swap D1
- Move D1,(SP) ;result
- Jmp (A1) ;return
-
- *** Reading replies to 38303 ***
- *** More ***
-
- #: 38371 S3/Mac Programming
- 28-Aug-86 02:04:50
- Sb: #38303-CRC's
- Fm: Steve Brecher 70001,1011
- To: Jerry LeVan 76354,364
-
- ; function CheckCRC(rcvdCRC: integer; theData: datablock): boolean;
- ; *** theData must start on a word boundary ***
- ; returns true if rcvdCRC (high byte received first) is correct.
- CheckCRC:
- Move.L (SP)+,A1 ;return address
- Move.L (SP)+,A0 ;pointer to data
- Move.L D3,-(SP) ;preserve
- Move.L #$10210000,D0 ;constant in high word
- MoveQ #0,D1 ;init calculated CRC result in high word
- MoveQ #128/2-1,D3 ;for Dbra outer loop
- @0 MoveQ #16-1,D2 ;for Dbra inner loop
- Move (A0)+,D1 ;two data bytes
- @1 Add.L D1,D1 ;shift CRC and data bytes left
- Bcc.S @2 ;br if bit shifted out of calc CRC was clear
- Eor.L D0,D1 ;was set: xor calc CRC with constant
- @2 Dbra D2,@1 ;end inner loop
- Dbra D3,@0 ;end outer loop
- Move.L (SP)+,D3 ;restore
- Move (SP)+,D1 ;received CRC
- MoveQ #16-1,D2 ;update for two received CRC bytes...
- @3 Add.L D1,D1 ;shift calc CRC and received CRC bytes left
- Bcc.S @4 ;br if bit shifted out of calc CRC was clear
- Eor.L D0,D1 ;was set: xor calc CRC with constant
- @4 Dbra D2,@3 ;end loop
- Seq (SP) ;return (calculated result = 0)
- Jmp (A1) ;return
-
- *** Reading replies to 38303 ***
- *** More ***
-
- #: 38678 S3/Mac Programming
- 01-Sep-86 16:13:17
- Sb: #38658-CRC's
- Fm: Bela Lubkin/Amiga Forum 73047,1112
- To: Jerry LeVan 76354,364
-
- Well, I haven't programmed seriously in C for over 5 years, but I wrote the
- table routine in Pascal and converted it to C. This code compiles, but I
- don't
- guarantee that it'll run; also, it could probably be optimized a bit. The
- idea
- is to call the bit-shifting CRC routine 256 times to build a table, then use
- the table later. I call compute_crc with an "old CRC" of 0000...FF00, by
- 0100's, and tell it to CRC in a single byte (which is 0). Looking at the
- compute_crc routine, you can see that once the buffer byte has been XOR'd in,
- the rest of the computation is effectively an XOR of the low byte of the old
- CRC, shifted left 8, with a 16 bit value that is determined by the old high
- byte XOR'd with the buffer value. (whew). So by getting the CRC's of
- 0000..FF00, I get a table of those 16 bit XOR values.
- To compute a CRC using the table, I XOR the high byte of the old CRC with
- the
- buffer byte, as in the shifting method. Then I get the array value
- corresponding to that byte. XORing that with the old CRC's low byte, now
- moved
- into the high byte, gives the new CRC value.
- Late news: I dug up an old C compiler and made sure my code worked (and
- optimized it as well as I could). I can't be 100% sure because the compiler
- was really flaky, but I did get correct results out of it when I got anything
- at all...
-
- Code:
-
- unsigned short crc_table[256];
-
- setup_crc_tables()
- {
- int count;
- char zero=0;
-
- for (count=0; count<256; count++)
- crc_table[count]=compute_crc(count<<8,&zero,1);
- }
-
- unsigned short table_driven_crc(crc,bufptr,len)
- unsigned short crc;
- unsigned char *bufptr;
- short len;
- {
- while (len--)
- crc=crc_table[crc>>8^(*bufptr++)]|crc<<8;
- return(crc);
- }
-
- - Bela
-
- #: 39184 S3/Mac Programming
- 10-Sep-86 00:37:12
- Sb: #39164-CRC's
- Fm: Bela Lubkin 73047,1112
- To: Jerry LeVan 76354,364
-
- Draw a picture? Hmmm... Lemme try words. We'll start out by looking at
- compute_crc (actually, the contents of the while loop inside of compute_crc).
- Imagine that instead of "crc", there are two variables, crc_high and crc_low.
- By the time the inner loop is done, crc_high has been shifted entirely out of
- the picture. The new crc_high is the old crc_low, and the new crc_low is 0,
- both XORed up to 8 times in passing, by the polynomial value 0x1021. In the
- inner loop, 0x1021 is either XORed in, or not, depending on the value of a bit
- that will be shifted out of the picture by the time the loop is finished.
- Those 8 XORs can be "folded" into a single XOR, since XOR is transitive. The
- folded value is determined by the old crc_high XORed with the byte that is
- being CRCed. That value, the old crc_high XORed with the byte that's being
- CRCed, can only take 256 values (it's a byte, after all). So if we build a
- table of 256 values, one for each possible (old crc_high XOR
- byte_being_CRCed),
- then we can later build CRCs by using crc_high XOR byte_being_CRCed as an
- index
- into that table. That's what build_crc_table and table_driven_crc do.
- I'm afraid that's not terribly clear, but I hope that it will become clear
- after you've synthesized it with the actual code and a bit of deep (?)
- thinking... - Bela
-
-