У меня есть данные в шестнадцатеричном дампе, но я не знаю кодировку. Например. 0x91 0x05 = 657 - PullRequest
0 голосов
/ 06 января 2019

У меня есть некоторые данные в шестнадцатеричном коде. левая рука - DEC, а правая - шестнадцатеричный код.

16 = 10
51 = 33
164 = A4 01
388 = 84 03
570 = BA 04
657 = 91 05
1025 = 81 08
246172 = 9C 83 0F

Как рассчитать любой hexdump в DEC? В Perl я пытался использовать команду ord (), но не работает.

Обновление Я не знаю, как это называется. Это похоже на данные 7 бит. Я пытаюсь построить формулу в Excel выглядеть следующим образом:

DEC = hex2dec(X) + (128^1 * hex2dec(Y-1)) + (128^2 * hex2dec(Z-1)) + ...

1 Ответ

0 голосов
/ 06 января 2019

То, что у вас есть, - это кодировка переменной длины. Длина кодируется с использованием формы значения часового: для каждого байта кодированного номера, кроме последнего, установлен старший бит. Остальные биты образуют кодирование числа с двумя дополнительными числами в порядке байтов с небольшим окончанием.

0xxxxxxx                   ⇒                   0xxxxxxx
1xxxxxxx 0yyyyyyy          ⇒          00yyyyyy yxxxxxxx
1xxxxxxx 1yyyyyyy 0zzzzzzz ⇒ 000zzzzz zzyyyyyy yxxxxxxx
etc

Для декодирования потока можно использовать следующее:

use strict;
use warnings;
use feature qw( say );

sub extract_first_num {
   $_[0] =~ s/^([\x80-\xFF]*[\x00-\x7F])//
      or return;

   my $encoded_num = $1;
   my $num = 0;
   for (reverse unpack 'C*', $encoded_num) {
      $num = ( $num << 7 ) | ( $_ & 0x7F );
   }

   return $num;
}

my $stream_buf = "\x10\x33\xA4\x01\x84\x03\xBA\x04\x91\x05\x81\x08\x9C\x83\x0F";
while ( my ($num) = extract_first_num($stream_buf) ) {
   say $num;
}

die("Bad data") if length($stream_buf);

Выход:

16
51
164
388
570
657
1025
246172
...