I'm trying to write a program to calculate a 32-bit CRC from an imput file by emulating the hardware representation on pg. 195 of Data & Computer Communications (8th ed. Stallings). There's a problem in my program's logic in
one spot. Am I iterating an array in the wrong direction or popping when I should unshift?
#!/usr/bin/perl -w
use strict;
use warnings;
use String::CRC32;
# Poly: X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^
+1+1
# Gen: 100000100110000010001110110110111
my @msg;
my @bin_msg;
my @gen = qw(0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 1 1 0
+ 1 1 1);
my @crc = qw(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+ 0 0 0);
my $crc = 0;
my $old_crc = 0;
my $built_in_crc = 0;
get_input();
my_crc();
built_in_crc();
display();
sub get_input {
local $/ = undef;
my $file = <>;
my @file = split(/0x/, $file);
@msg = split(//, $file[0]);
if ($file[1]) { $old_crc = sprintf('0x%s', $file[1]); }
else { $old_crc = 0; }
$built_in_crc = built_in_crc($file[0]);
}
sub my_crc {
foreach (@msg) {
push(@bin_msg, split(//, sprintf('%08b', ord($_))));
}
print "\n";
while (@bin_msg) {
my $bit = shift(@bin_msg);
print "bit: $bit\t\t";
push(@crc, $bit);
shift(@crc);
if ($bit == 1) {
for (my $i = 0; $i < 32; $i++) {
if ($gen[$i] == 1) { $crc[$i] ^= 1; }
}
}
print @crc, "\n";
}
}
sub built_in_crc { my $tmp = $_[0] || warn "$!\n"; return crc32($tmp);
+ }
sub display {
my $x = '';
foreach (@crc) { $x .= $_; }
print "Msg:\t\t\'", @msg, "\'\n";
print "Gen:\t\t", @gen, "\n";
printf "Old CRC:\t%s\n", $old_crc;
printf "New CRC:\t%s", `python -c "print hex(0b$x)"`;
printf "Lib CRC:\t%#x\t(String::CRC32)\n\n", $built_in_crc;
}
And the output:
bit: 0 00000000000000000000000000000000
bit: 1 00000100110000010001110110110110
bit: 0 00001001100000100011101101101100
bit: 1 00010111110001010110101101101110
bit: 0 00101111100010101101011011011100
bit: 1 01011011110101001011000000001110
bit: 1 10110011011010000111110110101010
bit: 0 01100110110100001111101101010100
Msg: 'V'
Gen: 00000100110000010001110110110111
Old CRC: 0x500a1b4c
New CRC: 0x66d0fb54
Lib CRC: 0x500a1b4c (String::CRC32)
Old, New and Lib CRC should match...but my result (New CRC) doesn't.
Update: I worked out the same message 'V' by hand and got the same result as my program '0x66d0fb54'. This means that the program is doing exactly what I expected it to do. So my problem must be in my interpretation of the hardware's logic.
I think I should be feeding the bit-string representation of the message, MSB first into the crc array, if the current bit is a 1, then I iterate through the crc and gen arrays, xoring the the corresponding index in crc whenever I encounter a 1 in the gen array.
Any insights?