7

バイトの特定のビットを抽出し、抽出ビットを16進値に戻す必要があります。

例(バイトの値は0xD2です):

76543210 bit position
11010010 is 0xD2
  • ビット0〜3は、次のチャネルを定義します0010b0x2
  • ビット4-5は、次のコントローラーを定義します01b0x1
  • ビット6-7は、次のポートを定義します11b0x3

私はどういうわけかバイトから取得する必要があります0xD2チャネルは0x2、コントローラーは0x1、ポートは0x3

私はallotをグーグルで検索し、関数pack/ unpackvecおよびを見つけましたsprintf。しかし、私はこれを達成するための関数の使い方を頭の中でかじっています。Perlでこれを実現する方法はありますか?

4

2 に答える 2

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,0b110b11を使用できます。ほとんどの人は 16 進数で作業します。)

または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

(わかりやすくするために一部のゼロを省略しています。)

于 2012-11-24T16:52:26.447 に答える
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
于 2012-11-24T16:59:30.827 に答える