Question

I've used lsl and lsr a bit in THUMB (an instruction set for ARM), and the way they worked was tied to the number of bits in the registers.

In my particular case, it happened to be 16bit registers, but that's not overly important, and for the purposes of example, I'm going to pretend that they were only 4bit.

Basically, their behavior is this:

mov r0, #0x1011
lsl r0, #0x1

The mov would set r0 to 1000, and then the lsl would shift them, but because the number inside r0 is already 4bits, and, as I said earlier we're pretending we're working with 4bit registers, that bit is lost, and r0 would become #0x0110.

Basically what happens is, to lsl something by n bits, the n most significant bits are lost, the rest of the value is shifted as expected, and 0s are added to fill in the least significant bits.

This probably has a name, sorry, I don't know what it is, but hopefully what I'm referring to is clear enough.

I'm working with the << operator in Python, and I need this to happen. Practically, I need to split up a 16bit number into it's most significant 3 bits, next most significant 2 bits, etc.

Is there a simple way to handle this that's already built into Python? I know a way to do it, but rather than bothering with that, I figured it'd be worth asking if such a feature was built in.

Thanks.

Was it helpful?

Solution

The least troublesome way to do this is probably with explicit bitmasks, e.g.

a = (sixteen_bit_val & 0xE000) >> 13
b = (sixteen_bit_val & 0x1800) >> 11
# ... and so on ..

Not tested, shift quantities may be off by one or two.

OTHER TIPS

If you're finding bit manipulation in terms of shifting and masking difficult, you may want to wrap it up in familiar terms—e.g., with a class that acts like a sequence of bits, and can be sliced, etc.

Or, even better, you may want to get a wrapper that does that for you, like bitarray or bitstring.

Then you can write code like this:

>>> bin[13:16]
bitarray('010')
>>> bin[11:13]
bitarray('11')

… etc. Under the covers it's probably still shifting and masking integers (although for all you care it could be in C rather than Python), but you don't have to think in those terms.

While we're at it, you didn't mention anything about endianness. If you want it to be native-endian, or explicitly big-endian, or something like that, that's pretty implicit when you're doing manual shift and mask operations; it might be better to make it explicit by converting the number to a bytes string, then turning that into a bit string. For example:

n = int(input())
b = struct.pack('!H', n) # explicitly network-endian
bb = bitarray(16) # explicitly 16 bits
bb.frombytes(b)
bb[13:16]

If you only want to retain a set number of bits, use a mask to and those bits.

>>> bin((0b1011 << 1) & 0b1111)
'0b110'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top