Perl:如何从一个字节中提取某些位然后将这些位转换为十六进制值?

Sie*_*epp 7 perl bit-manipulation bitmap text-parsing bit

我需要提取一个字节的某些位并将提取位转换回十六进制值.

示例(字节的值为0xD2):

76543210 bit position
11010010 is 0xD2
Run Code Online (Sandbox Code Playgroud)
  • 位0-3定义了信道,其是0010b0x2
  • 位4-5定义了控制器,其是01b0x1
  • 位6-7定义了端口,其是11b0x3

我不知何故需要从字节0xD2到通道是0x2,控制器是0x1,端口是0x3

我googled分配并找到了函数pack/ unpack,vecsprintf.但是我正在摸索如何使用这些功能实现这一目标.知道如何在Perl中实现这一点吗?

ike*_*ami 8

什么是初始格式?

my $chr = chr(0b11010010);  # A character  e.g. from read()
my $bin = '11010010';       # Binary
my $hex = 'D2';             # Hexadecimal
my $num = 0b11010010;       # A number.
my $num = 0xD2;             # A number.
Run Code Online (Sandbox Code Playgroud)

您想从将其转换为数字开始

my $num = ord($chr);
my $num = unpack('C', $chr);  # Alternative
my $num = oct("0b$bin");
my $num = hex($hex);
Run Code Online (Sandbox Code Playgroud)

然后你使用轮班和面具.

my $channel    = ($num >> 0) & 0xF;   # Or just: $num & 0xF
my $controller = ($num >> 4) & 0x3;
my $port       = ($num >> 6) & 0x3;   # Or just: $num >> 6
Run Code Online (Sandbox Code Playgroud)

(您可以使用0b1111,0b110b11为掩盖大多数人在十六进制的工作.)

或者让vec你为自己找出面具.

my $channel    = vec $num, 0, 4;
my $controller = vec $num, 4, 2;
my $port       = vec $num, 6, 2;
Run Code Online (Sandbox Code Playgroud)

这是一个例子$controller:

  11010010
      >> 4
  --------
      11010010
&       11
  --------
        01
Run Code Online (Sandbox Code Playgroud)

(为清楚起见,省略了一些零.)