如何在perl中对特定位执行操作

时间:2013-08-19 23:06:30

标签: perl binary

假设我有一个十六进制值0x78。我需要将1添加到前4位,即3:0,并将2添加到最后4位,即。 [7:4]。此外,当我添加1到0xF时,它不应该翻转到下一个值,并应保持为0xF。同样适用于减法。我到目前为止尝试的方法是:

$byte=0x78;
$byte2 = unpack('b4', $byte);
print "byte2 = $byte2 \n";

- >这里的输出是1000,所以我试图提取前4位,同样我可以右移并提取最后4位并执行操作。 但是为了执行加法或减法,我想将1000转换回十六进制格式,这样我就可以做0x8 +/- 1.为此,我尝试了:

$hex2 = sprintf('%02x', $byte2);
print "hex2 = $hex2 \n";

- >输出为3e8。我不明白为什么我得到3e8而不是8或08,因为它应该只以十六进制格式打印2个值。

在我手动输入时的上述命令中 $ hex2 = sprintf('%02x',0b1000);我得到了正确的结果。所以perl将它作为字符串而不是数值。有什么方法可以将该字符串转换为二进制数字吗?任何其他更简单的方法或方法都会有所帮助。

3 个答案:

答案 0 :(得分:1)

我们可以通过ANDing和shift来获取每个字节:

$byte1 = $byte & 0xf;
$byte2 = ($byte & 0xf0) >> 4;
printf "byte1: 0x%x\n", $byte1;
printf "byte2: 0x%x\n", $byte2;

# prints
byte1: 0x8
byte2: 0x7

使用您列出的特殊条件的加法/减法可以在这些字节上完成,新值可以通过移位和加法重建:

($byte1 < 0xf) ? ($byte1 += 1) : ($byte1 = 0xf);
($byte2 < 0xe) ? ($byte2 += 2) : ($byte2 = 0xf);
# or do subtraction stuff.

$new_val = ($byte2 << 4) + $byte1;
printf "new val: 0x%x\n", $new_val;

# prints
new val: 0x99

你得到'3e8'因为$ byte2是'1000',当翻译成十六进制时是'0x3e8'。

答案 1 :(得分:0)

我认为你最好用以下的东西:

sub byte_to_two_nibbles($) {
    my $byte = shift;
    return int($byte / 16), ($byte % 16);
}

sub two_nibbles_to_byte($$) {
    return $_[0] * 16 + $_[1];
}

my ($msn, $lsn) = byte_to_two_nibbles 0x78;
$msn += 1; $msn = 15 if $msn > 15;
$lsn += 2; $lsn = 15 if $lsn > 15;
my $result = two_nibbles_to_byte $msn, $lsn;

答案 2 :(得分:0)

您可以使用oct功能:

$byte2 = oct("0b$byte2");
my $hex2 = sprintf('%02x', $byte2);
print "hex2 = $hex2 \n";

打印:

hex2 = 08