2013-08-19 26 views
1

假设我有一个十六进制值0x78。我需要添加1到前4位,即3:0并添加2到最后4位,即。 [7:4]。此外,当我添加1到0xF它不应该滚动到下一个值,并应保持为0xF。同样适用于减法。到目前为止我曾尝试的方法是:如何在perl中对特定位执行操作

$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,因为它应该只以十六进制格式打印两个值。

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

+0

'unpack'bX''需要一串字节,但是你传递了一个数字。你很幸运,你得到了正确的答案,因为当你想要'78'的二进制文件时,你实际上得到了'37 38'(Unicode码点“7”和“8”)的二进制。 – ikegami

+0

二进制是一个数字的文本表示。你不想用二进制(文本)工作,你想使用数字。用'$ byte'使用按位运算符。 – ikegami

回答

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; 
0

可以使用oct功能:

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

打印:

hex2 = 08 
1

我们可以得到每个字节与运算:

$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”,因为$字节2“1000 ',当翻译成十六进制时,它是'0x3e8'。