1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
Bit Strings
Bits are the atoms in the memory world. Access to individual bits may have to be used either as a last resort or because it is the most convenient way to handle your data. Bit string (un)packing converts between strings containing a series of 0 and 1 characters and a sequence of bytes each containing a group of 8 bits. This is almost as simple as it sounds, except that there are two ways the contents of a byte may be written as a bit string. Let's have a look at an annotated byte:
7 6 5 4 3 2 1 0
+-----------------+
| 1 0 0 0 1 1 0 0 |
+-----------------+
MSB LSB
It's egg-eating all over again: Some think that as a bit string this should be written ``10001100'' i.e. beginning with the most significant bit, others insist on ``00110001''. Well, Perl isn't biased, so that's why we have two bit string codes:
$byte = pack( 'B8', '10001100' ); # start with MSB
$byte = pack( 'b8', '00110001' ); # start with LSB
It is not possible to pack or unpack bit fields - just integral bytes. pack always starts at the next byte boundary and ``rounds up'' to the next multiple of 8 by adding zero bits as required. (If you do want bit fields, there is vec in the perlfunc manpage. Or you could implement bit field handling at the character string level, using split, substr, and concatenation on unpacked bit strings.)
To illustrate unpacking for bit strings, we'll decompose a simple status register (a ``-'' stands for a ``reserved'' bit):
+-----------------+-----------------+
| S Z - A - P - C | - - - - O D I T |
+-----------------+-----------------+
MSB LSB MSB LSB
Converting these two bytes to a string can be done with the unpack template 'b16'. To obtain the individual bit values from the bit string we use split with the ``empty'' separator pattern which dissects into individual characters. Bit values from the ``reserved'' positions are simply assigned to undef, a convenient notation for ``I don't care where this goes''.
($carry, undef, $parity, undef, $auxcarry, undef, $zero, $sign,
$trace, $interrupt, $direction, $overflow) =
split( //, unpack( 'b16', $status ) );
We could have used an unpack template 'b12' just as well, since the last 4 bits can be ignored anyway. |
Partager