in reply to Re: Decoding binary information
in thread Decoding binary information

Thanks liverpole.

The first and third integers are properly converted using hex as you suggested. However, the second number is actually a negative number:

F4EC9E = -725850

Any ideas on why?

Thank you very much for your help. You've already cleared up lots!

njcodewarrior

Replies are listed 'Best First'.
Re^3: Decoding binary information
by bart (Canon) on Feb 10, 2007 at 18:18 UTC
    You should sign-extend it, Perl isn't used to working with 24 bit integers.

    Perl can handle 32 bit integers just fine. You could append '00', pack it into a 4 byte structure (a long), and unpack it as a signed long; and finally divide by 256, for the 2 extra zeros you added.

    print unpack('l', pack 'L', hex 'F4EC9E00')/256;
    Or, maybe easier, subtract 2**24 if you see it's 2**23 or more.
    $n = hex 'F4EC9E'; if($n >= 2**23) { $n -= 2**24 } print $n;
Re^3: Decoding binary information
by liverpole (Monsignor) on Feb 10, 2007 at 18:11 UTC
    What version of Perl do you have, and what code exactly are you running?

    I could see where F4EC9E might be interpreted as a negative value, since the highest order bit is set.  What I don't understand is why it would evaluate as -725850, which should be represented by F4ECA6:
    use strict; use warnings; my $value; $value = -725850; printf "Hex value 0x%08lX = %ld (decimal)\n", $value, $value; $value = -725858; printf "Hex value 0x%08lX = %ld (decimal)\n", $value, $value __END__ # Output: Hex value 0xFFF4ECA6 = -725850 (decimal) Hex value 0xFFF4EC9E = -725858 (decimal)

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

      I'm running:

      This is perl, v5.8.5 built for x86_64-linux-thread-multi

      The translation program I'm running was written in C and is only compiled for win32. I'd be more than happy to post it along with the sample hex message if you want to look at it.

      So my reasons for looking further into this are 2-fold: 1) Port it to *nix as this is my native operating environment as well as to be able to run it on as a cronjob and 2) learning about data types and how they are represented on the machine.

      njcodewarrior

        Oh, well if you're looking at the values with a C program, that would explain why those with the high-order bit set are displaying as negative values. You did say the numbers were "3 byte signed integers".

        If you need to convert to negative values, I think bart's suggestion below (the second one) is the best (most simple).  Just subtract 2 ** 24 from any values which are greater than or equal to 0x800000 (2 ** 23).

        That would amend my original code to something like:

        use strict; use warnings; my @values = ( "05F9AD", "F4EC9E", "0005" ); foreach my $value (@values) { my $decval = hex($value); ($decval >= 0x800000) and $decval -= 0x1000000; printf "Hex value 0x%08lx = %ld (decimal)\n", $decval, $decval; } __END__ # Output: Hex value 0x0005f9ad = 391597 (decimal) Hex value 0xfff4ec9e = -725858 (decimal) Hex value 0x00000005 = 5 (decimal)

        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/