我需要提取一个字节的某些位并将提取位转换回十六进制值。
示例(字节的值为0xD2):
76543210 bit position
11010010 is 0xD2
0010b
为0x2
01b
为0x1
11b
为0x3
我需要从字节0xD2
到频道为0x2
,控制器为0x1
,端口为0x3
我用谷歌搜索分配并找到函数pack
/ unpack
,vec
和sprintf
。但是我正在摸索如何使用这些功能实现这一目标。知道如何在Perl中实现这个目标吗?
答案 0 :(得分: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.
您想首先将其转换为数字
my $num = ord($chr);
my $num = unpack('C', $chr); # Alternative
my $num = oct("0b$bin");
my $num = hex($hex);
然后你使用轮班和面具。
my $channel = ($num >> 0) & 0xF; # Or just: $num & 0xF
my $controller = ($num >> 4) & 0x3;
my $port = ($num >> 6) & 0x3; # Or just: $num >> 6
(您可以使用0b1111
,0b11
和0b11
作为面具。大多数人都使用十六进制。)
或者让vec
为你找出面具。
my $channel = vec $num, 0, 4;
my $controller = vec $num, 4, 2;
my $port = vec $num, 6, 2;
以下是$controller
的示例:
11010010
>> 4
--------
11010010
& 11
--------
01
(为清楚起见省略了一些零。)
答案 1 :(得分:2)
vec
是个不错的选择。我认为这非常简单:
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my @channels = map "channel_$_" => 0 .. 15;
my @controllers = map "controller_$_" => 0 .. 3;
my @ports = map "port_$_" => 0 .. 3;
my $bits = 0b11010010;
my $channel = vec $bits, 0, 4;
my $controller = vec $bits, 4, 2;
my $port = vec $bits, 6, 2;
say "channel : $channels[$channel]";
say "controller : $controllers[$controller]";
say "port : $ports[$port]";
输出:
channel : channel_2
controller : controller_1
port : port_3