khilles
asked on
Dword and Qword in PHP
I'm working on an application to decode a BigEndian transmission used for GPS tracking. The problem is that I need to convert a Hex string to a Dword Decimal.
For instance, the following is received in Hex: "CD 26 BC A7" and I need to create a PHP function to convert it to "-853099353".
You can do this in Windows Calculator by:
- Click on View -> Programmer
- Click on Hex
- Enter "CD26BCA7"
- Click on Dec
- Click on Dword
I can get PHP to convert to the Decimal part (3441867943) using HEXDEC but can't do the last step to convert it to Dword.
The calculator implies that I could do it by prepending 8 "F"s in the front but that doesn't seem to work.
Any ideas?
Thanks so much!!
For instance, the following is received in Hex: "CD 26 BC A7" and I need to create a PHP function to convert it to "-853099353".
You can do this in Windows Calculator by:
- Click on View -> Programmer
- Click on Hex
- Enter "CD26BCA7"
- Click on Dec
- Click on Dword
I can get PHP to convert to the Decimal part (3441867943) using HEXDEC but can't do the last step to convert it to Dword.
The calculator implies that I could do it by prepending 8 "F"s in the front but that doesn't seem to work.
Any ideas?
Thanks so much!!
This gets closer.
<?php // RAY_temp_khilles.php
error_reporting(E_ALL);
// TEST DATA
$hex = 'CD26BCA7';
$dwo = '-853099353';
// TRY A DIFFERENT WAY
$hex = 'FFFFFFFF' . $hex;
// CONVERT THE DATA USING INTVAL
$num = intval(hexdec($hex));
var_dump($num); // PRINTS -853098496
// THIS DOES NOT PRINT
if ($num == $dwo) echo "SUCCESS";
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Very Awesome, works great. Thanks so much!!!
You're welcome and thanks for the points. Here is the generalized teaching example. All the best, ~Ray
<?php // RAY_twos_complement.php
error_reporting(E_ALL);
echo "<pre>";
// A FUNCTION TO GET THE TWO'S COMPLEMENT INTEGER DECIMAL VALUE FROM A HEX STRING
// THE ZERO-POSITION BIT IN THE HEX STRING IS USED AS THE SIGN BIT
function hexDword($hex, $len=8)
{
// ENSURE WE HAVE A USABLE INPUT
$num = hexdec($hex);
$int = intval($num);
if ($num !== $int) return "ERROR: VALUES OUT OF RANGE";
if (strlen($hex) > $len) return "ERROR: INCOMPATIBLE LENGTH";
if ($len > 16) return "ERROR: LENGTH MUST BE 16 OR LESS";
// COMPUTE THE MAX VALUE FOR A HEX STRING OF THIS LENGTH
$str = str_pad('7', $len, 'F', STR_PAD_RIGHT);
$max = hexdec($str);
// PAD TO THE CORRECT NUMBER OF HEX DIGITS
$hex = str_pad($hex, $len, '0', STR_PAD_LEFT);
// DETERMINE THE SIGN BIT
$bin = base_convert($hex, 16, 2);
$bin = str_pad($bin, $len*4, '0', STR_PAD_LEFT);
$arr = str_split($bin);
$neg = FALSE;
if ($arr[0] == '1') $neg = TRUE;
// RESET THE SIGN BIT TO ZERO
unset($arr[0]);
$bin = '0' . implode(NULL, $arr);
// CONVERT TO DECIMAL
$ans = base_convert($bin, 2, 10);
// IF NEGATIVE, USE TWOS-COMPLEMENT
if ($neg)
{
$ans = $ans - $max - 1;
}
return $ans;
}
// GENERALIZED TEST CASES
$hexs
= array
( '7FFFFFFF'
, '9'
, '10'
, '111'
, 'C'
, 'FFFFFFFD'
, 'FFFFFFFF'
, '0'
)
;
foreach ($hexs as $hex)
{
$new = hexDword($hex);
echo PHP_EOL . "$hex = $new";
}
// ANOTHER TEST WITH SHORT HEX STRINGS
$hexs
= array
( '7F'
, 'FF'
, 'FE'
, 'FD'
, '80'
, '10'
, 'C'
, '0'
)
;
foreach ($hexs as $hex)
{
$new = hexDword($hex, 2);
echo PHP_EOL . "$hex = $new";
}
// ANOTHER TEST WITH MEDIUM HEX STRINGS
$hexs
= array
( '7FFF'
, 'FFFF'
, 'FFFE'
, 'FFFD'
, '8000'
, '10'
, 'C'
, '0'
)
;
foreach ($hexs as $hex)
{
$new = hexDword($hex, 4);
echo PHP_EOL . "$hex = $new";
}
I'll see if I can figure something out.
Open in new window