2012-11-24 13 views
7

Ho bisogno di estrarre alcuni bit di un byte e di nascondere i bit di estrazione a un valore esadecimale.Perl: come estrarre determinati bit da un byte e quindi coprire questi bit con un valore esadecimale?

Esempio (il valore del byte è 0xD2):

bit position 
11010010 is 0xD2 
  • bit 0-3 definisce il canale quali è 0010b è 0x2
  • bit 4-5 definisce il controllore che è 01b è 0x1
  • Bit 6-7 definisce la porta che è 11b è 0x3

io in qualche modo bisogno di ottenere dal byte è 0xD2 al canale è 0x2, controller è 0x1, porta è 0x3

I Googled assegnare ed ha trovato le funzioni pack/unpack, vec e sprintf. Ma sto grattando a testa come usare le funzioni per raggiungere questo obiettivo. Qualche idea su come ottenere questo in Perl?

risposta

7

Qual è il formato iniziale?

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

si desidera avviare convertendolo in un numero

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

quindi si utilizza turni e maschere.

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

(Si potrebbe usare 0b1111, 0b11 e 0b11 per le maschere. La maggior parte delle persone lavorano in esadecimale.)

o lasciare che vec figura fuori le maschere per voi.

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

Ecco un esempio per $controller:

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

(Alcuni zeri omessi per chiarezza.)

+0

Sì, il formato iniziale è il valore esadecimale dal byte così nell'esempio sopra 0xD2 non quello che in precedenza indicato. –

+0

Sono felice di poter aiutare a migliorare questa risposta. :) – memowe

+1

Dopo aver letto: http://www.devshed.com/c/a/Perl/More-Perl-Bits/ La moneta è caduta :-) –

2

vec è una buona scelta. Penso che questo sia abbastanza semplice:

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

uscita:

channel : channel_2 
controller : controller_1 
port  : port_3