2012-11-24 5 views
7

Ich muss bestimmte Bits eines Bytes extrahieren und die extrahierten Bits zurück in einen Hexadezimalwert konvertieren.Perl: Wie extrahiere ich bestimmte Bits aus einem Byte und verberge diese Bits dann zu einem Hexadezimalwert?

Beispiel (der Wert des Byte ist 0xd2):

bit position 
11010010 is 0xD2 
  • Bit 0-3 des Kanal definiert, welche 0010b ist 0x2
  • Bit 4-5 der Controller definiert Das ist 01b ist 0x1
  • Bit 6-7 definiert den Port die 11b ist 0x3

ich irgendwie vom Byte erhalten müssen ist 0xD2 zu Kanal 0x2 ist, Controller ist 0x1, Port ist 0x3

Ich googeln zuzuteilen und fand die Funktionen pack/unpack, vec und sprintf. Aber ich kratze am Kopf, wie man die Funktionen benutzt, um das zu erreichen. Irgendeine Idee, wie man das in Perl erreicht?

Antwort

7

Was ist das Ausgangsformat?

my $chr = chr(0b11010010); # e.g. from read() 
my $bin = '11010010'; 
my $num = 0b11010010; 

Sie wollen, indem man sie auf eine Reihe

my $num = ord($chr); 
my $num = unpack('C', $chr); # Alternative 
my $num = oct("0b$bin"); 

Dann verwenden Sie Verschiebungen und Masken zu starten.

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

(Sie 0b1111 nutzen könnten, 0b11 und 0b11 für die Masken. Die meisten Menschen in hex arbeiten.)

Oder lassen vec Figur aus den Masken für Sie.

my $channel = vec $num, 0, 4; 
my $controller = vec $num, 4, 2; 
my $port  = vec $num, 6, 2; 

Hier ist ein Beispiel für $controller:

11010010 
     >> 4 
    -------- 
     11010010 
&  11 
    -------- 
     01 

(Einige Nullen weggelassen.)

+0

Ja, das ursprüngliche Format ist der Hex-Wert vom Byte so in obigem Beispiel 0xd2 nicht, was mich zuvor angedeutet. –

+0

Ich bin froh, dass ich helfen konnte, diese Antwort zu verbessern. :) – memowe

+1

Nach dem Lesen: http://www.devshed.com/c/a/Perl/More-Perl-Bits/ Die Münze fiel :-) –

2

vec eine gute Wahl ist. Ich denke, das ist ziemlich einfach:

#!/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]"; 

Ausgang:

channel : channel_2 
controller : controller_1 
port  : port_3 
Verwandte Themen