/** * Converte um valor hexadecimal para decimal com complemento de dois para numeros negativos * @param string $hex Valor hexadecimal * @return string Valor decimal na forma de string */ function converter_hex_dec($hex) { if (strlen($hex) % 2) { $hex = '0'.$hex; } // Obter os bytes na forma de vetor de inteiros // e usar o byte menos significativo (mais a direita) // simulando um tipo char da linguagem C $len = strlen($hex); $size = $len / 2; $bytes = array(); for ($i = 0; $i < $len; $i += 2) { $hex_byte = substr($hex, $i, 2); $byte = hexdec($hex_byte); $bytes[] = (int)$byte; } // Converter vetor de bytes para inteiro $dec = converter_bytes_dec($bytes); return $dec; } /** * Obtem um numero decimal de um vetor de bytes * @param array[int] $bytes Vetor de bytes representados por inteiros (byte menos significativo) * @return String Valor decimal representado por uma string */ function converter_bytes_dec($bytes) { // Numero negativo if ($bytes[0] & (1 << 7)) { // Complemento de 2 (inverter bits e somar 1) $bytes = complemento2($bytes); $sinal = '-'; // Numero positivo } else { $sinal = '+'; } $dec = '0'; $bit = '0'; for ($i = count($bytes) - 1; $i >= 0; --$i) { for ($j = 0; $j < 8; ++$j) { if ($bytes[$i] & (1 << $j)) { $dec = bcadd($dec, bcpow('2', $bit), 0); } $bit = bcadd($bit, '1'); } } return $sinal.$dec; } /** * Calcula o complemento de dois de um vetor de bytes * @param array[int] $bytes Vetor de bytes representados por inteiros (byte menos significativo) * @return array[int] Vetor de bytes convertidos */ function complemento2($bytes) { // Inverter bits $size = count($bytes); for ($i = $size - 1; $i >= 0; --$i) { $bytes[$i] = inverter_bits($bytes[$i]); } // Somar 1 for ($i = $size - 1; $i >= 0; --$i) { for ($j = 0; $j < 8; ++$j) { $bytes[$i] = $bytes[$i] ^ (1 << $j); if ($bytes[$i] & (1 << $j)) { break 2; } } } return $bytes; } /** * Inverte os bits de determinado byte * @param int $byte Byte representado por um inteiro (byte menos significativo) * @return int Byte com os bits invertidos (byte menos significativo) */ function inverter_bits($byte) { for ($i = 7; $i >= 0; --$i) { $byte = $byte ^ (1 << $i); } return $byte; }