betz@decvax.UUCP (06/21/83)
Many thanks to all who responded to my query about typecasting characters in C. Here is the CRC routine that I ended up with after various suggestions about how to get around the problem with unsigned characters. It seemed like the only real solution that was compatible with most compilers was to avoid using the type 'unsigned char' and instead 'and' the possibly signed character with 0xFF. This generates bad code on some machines, but it seems reasonable to recode a CRC routine in assembler for each machine anyway in order to gain efficiency. This routine will work in the interim until an assembler routine can be written. This is not the same algorithm that is used by the famous CP/M MODEM program. As far as I can tell, that program doesn't compute CRCs correctly, but I may be wrong. Anybody know if there are multiple ways to compute CRCs? This routine shifts new bits into the CRC from the left whereas the routine used in MODEM shifts them in from the right. This routine xors the CRC with the polynomial whenever the xor of the data bit and the bit shifted out of the right end of the CRC is one, the MODEM CRC routine xors the CRC with the polynomial whenever the bit shifted out of the left of the CRC is one. Well, this is getting a little verbose, so I guess I'll just end here. Probably some of you out there are groaning and muttering to yourselves about how completely uninformed about CRCs I must be to have posed all of these questions. You are right! Thanks for everyone's help, David Betz decvax!betz P.S. I am aware that this routine only implements CRC correctly for eight bit data bytes. ================= /* crc - compute the CRC for an array of 8 bit bytes */ /* This routine calculates CRCs using the same algorithm as the VAX-11/780 CRC instruction. */ /* the CRC polynomial */ #define POLY 0x8408 /* use X^16 + X^12 + X^5 + 1 */ /* crc - compute the CRC for an array of 8 bit bytes */ int crc(buf,len) char *buf; int len; { register char *bp; register unsigned int csum; register int j,i; /* initialize the buffer pointer */ bp = buf; /* initialize the CRC */ csum = 0xFFFF; /* compute the CRC */ for (i = len; i--; ) { csum ^= *bp++ & 0xFF; for (j = 8; j--; ) { if (csum & 1) { csum >>= 1; csum ^= POLY; } else csum >>= 1; } } return (~csum & 0xFFFF); }