2012-11-24 33 views
7

Tôi cần trích xuất các bit nhất định của một byte và bí mật các bit trích xuất trở lại giá trị hex.Perl: Làm thế nào để trích xuất các bit nhất định từ một byte và sau đó bí mật các bit này thành giá trị hex?

Ví dụ (giá trị của byte là 0xD2):

bit position 
11010010 is 0xD2 
  • Bit 0-3 xác định kênh đó là 0010b0x2
  • Bit 4-5 xác định bộ điều khiển 01b0x1
  • Bit 6-7 xác định cổng đó là 11b0x3

tôi bằng cách nào đó cần phải nhận được từ các byte là 0xD2 kênh là 0x2, bộ điều khiển là 0x1, cổng là 0x3

Tôi googled phân phối và tìm thấy các chức năng pack/unpack, vecsprintf. Nhưng tôi đang gãi đầu bằng cách sử dụng các chức năng để đạt được điều này. Bất kỳ ý tưởng làm thế nào để đạt được điều này trong Perl?

Trả lời

7

Định dạng ban đầu là gì?

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

Bạn muốn bắt đầu bằng cách chuyển đổi nó vào một số

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

Sau đó, bạn sử dụng thay đổi và mặt nạ.

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

(Bạn có thể sử dụng 0b1111, 0b110b11 cho các mặt nạ. Hầu hết mọi người làm việc trong hex.)

Hoặc hãy vec hình ra mặt nạ cho bạn.

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

Dưới đây là một ví dụ cho $controller:

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

(Một số zero bỏ qua cho rõ ràng.)

+0

Vâng, định dạng ban đầu là giá trị hex từ byte như vậy trong ví dụ trên 0xD2 không phải những gì tôi nêu trước đó. –

+0

Tôi rất vui vì tôi có thể giúp cải thiện câu trả lời này. :) – memowe

+1

Sau khi đọc: http://www.devshed.com/c/a/Perl/More-Perl-Bits/ Đồng xu giảm xuống :-) –

2

vec là một lựa chọn tốt. Tôi nghĩ rằng đây là khá đơn giản:

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

Output:

channel : channel_2 
controller : controller_1 
port  : port_3