smknjoe has asked for the wisdom of the Perl Monks concerning the following question:
Hi all other monks,
I'm trying to write a hex to binary converter and found what I thought were the needed code nuggets towards the bottom of "perldoc perlpacktut" documentation in the Intel Hex section. It seemed fairly straightforward, but I found that when processing bytes of data that the upper nibble is being dropped during the conversion. The discovery only came by reverse-conversion of the binary output string. The data length is reported as being correct; the first data line has 16 bytes, and the second contains 14 bytes - note this format has 4 bytes of info at the beginning of the line and a checksum byte at the end.
Here is my test code:
#!/usr/bin/env perl use strict; use warnings; use utf8; #===================================================================== +========== # Set to "1" for additional debugging print statements. #===================================================================== +========== my $debug= 1; #===================================================================== +========== # Standard input while loop #===================================================================== +========== my $line; # Retrieve a line while ($line = <DATA>) { # chomp line chomp $line; # Does line begin with ":"? if (($line !~ /^\:/) || ($line =~ /^\$/)) { print "INVALID LINE, SKIPPING : $line\n" if $debug; next } else { # convert line to hex (and strip off ":") my $hexrec = pack( 'H*', substr( $line, 1 ) ); # calculate checksum, if error, die. my $chksum = unpack( "%C*", $hexrec ); print "checksum = $chksum\n" if $debug; die unless unpack( "%8C*", $hexrec ) == 0; # # process the line. get bytecount, address, record type, and d +ata # my( $bytecount, $address, $recordtype, $data ) = unpack( "C n +C X4 C x3 /a", $hexrec ); # note: no reason to print data, since it results in special, +unprintable chars printf ("bytecount = %d, address = %d, recordtype = %d\n", $by +tecount, $address, $recordtype) if $debug; # # terminator line # if ($recordtype == 1) { print "Conversion complete\n"; exit; } # # real data line # elsif ($recordtype == 0) { my $binarycount = $bytecount*8; my $datlength = length($data); print "Data length (should match bytecount) = $datlength\n +"; # convert to binary my $binaryval = unpack("B$binarycount", pack("H$bytecount" +, $data)); print "binary = $binaryval\n" if $debug; } } } # end of while __DATA__ :1004D0000A95E1F7E0E0F8E000E40BBF00E81791CF :0E04E0001D930A95E1F74CCE00E10883FDCE96 :00000001FF __END__
The results of running the Perl code is this:
checksum = 2816 bytecount = 16, address = 1232, recordtype = 0 Data length (should match bytecount) = 16 binary = 1010010100010111000000001000000000000100101111110000100001110 +001 checksum = 2304 + bytecount = 14, address = 1248, recordtype = 0 + Data length (should match bytecount) = 14 + binary = 11010011101001010001011101011110000000011000001111011110 + checksum = 256 + bytecount = 0, address = 0, recordtype = 1 + Conversion complete
If someone can shed some light on this and help me to understand pack/unpack a tiny bit better, it would be much appreciated.
Thanks,
Joe
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Pack or unpack dropping a nibble
by Eily (Monsignor) on Mar 19, 2018 at 18:16 UTC | |
|
Re: Pack or unpack dropping a nibble
by smknjoe (Beadle) on Mar 19, 2018 at 18:06 UTC |