20

I have a message which reads as 14 09 00 79 3d 00 23 27. I can extract each byte from this message by calling message[4], which will give me 3d for example. How do I extract the individual 8 bits from this byte? For example, how would I get bits 24-27 as as single message? How about just bit 28?

Aditya Salapaka
  • 305
  • 1
  • 2
  • 12
  • so are you asking how to represent a base 16 integer as base 2 in python, or are you asking how to extract certain bits of a number? or both, extract certain bits and display in binary? – jacoblaw Jul 20 '17 at 17:07
  • What's the data type of that message? Please provide a Python literal. – Stefan Pochmann Jul 20 '17 at 17:08

2 Answers2

44

To answer the second part of your question, you can get specific bit values using bitwise operations

# getting your message as int
i = int("140900793d002327", 16)

# getting bit at position 28 (counting from 0 from right)
(i >> 28) & 1

# getting bits at position 24-27
bin((i >> 24) & 0b111)
Neuron
  • 5,141
  • 5
  • 38
  • 59
Anis
  • 2,984
  • 17
  • 21
  • 1
    @StefanPochmann Presumably to shift the relevant bits to the start of the integer. `3B 00 00 00` would be more annoying to work with compared to `3B` – TemporalWolf Jul 20 '17 at 17:14
  • @TemporalWolf That's not what I meant. Check out the updated answer for what I meant. – Stefan Pochmann Jul 20 '17 at 17:17
  • @StefanPochmann that he's demonstrating two separate examples? – TemporalWolf Jul 20 '17 at 17:18
  • 1
    @TemporalWolf Huh? That's not what they changed. – Stefan Pochmann Jul 20 '17 at 17:19
  • Should be good now. Before I used two bit shifts, when only one is necessary. The reason was first I thought OP wanted the value of the int having a 1 at the position, which would be given by ```i & 1 << 28```. But then I realized it wasn't the case so I added the second bitshift.... which could be merged into one. Clear? – Anis Jul 20 '17 at 17:20
  • Thanks for the reply! I didn't quite understand what you mean by `24 & 0b111`, though. `0b111` is 7 in decimal. How did you get 24-27 with that? – Aditya Salapaka Jul 21 '17 at 17:13
  • 2
    The point is: I want to get the three bits values at positions 24 25 and 26, to do that, so, the idea is to do shift the bits so the positions become 0 1 and 2 and then do an AND operation with a number that has 1 to positions 0 1 2 and 0s elsewhere. I could have just done ```i>>24 & 7```, but I thought it would be clearer to write it in binary. – Anis Jul 21 '17 at 22:35
  • Oh that explains it! Thank you so much. :) If I had to get, say, 30-35, I would `i >> 30 & 0b111111` then? To get bits 30, 31, 32, 33, 34, 35? – Aditya Salapaka Jul 24 '17 at 18:02
  • You've got it :) – Anis Jul 25 '17 at 08:47
  • So why does `& 1` works like `[1]`? – Jing He Jan 23 '22 at 18:05
  • What if my hex message has a lot of leading zeros? – Jing He Jan 23 '22 at 18:32
5

The easiest way to do this is to use the & operator. Convert your message to an int using int(str_msg, 16). convert int to binary string using bin(myint)

To get bits 4-6 (from left) in a byte:

>> msg = int("10110111", 2) # or 0b10110111
>> extractor = int("00011100", 2) # or 0b10110111
>> result = msg & extractor
>> print bin(result)
00010100

If you want, you can bit shift result using result >> 2. Obviously you will want to make this more dynamic but this is a dumbed down example.

Ian Kirkpatrick
  • 1,861
  • 14
  • 33
  • 2
    Its probably easier to put in 28 in base 2 than base 10. With `0b11100` it's much clearer which bits you want – jacoblaw Jul 20 '17 at 17:16
  • Not sure whether the new version is better or even worse than the old version. Why not use what @jacoblaw showed? – Stefan Pochmann Jul 20 '17 at 17:21
  • I'ts just an example. The person wasn't asking how to get the input, just the result. How he gets the input is up to him. I'm sure he already knows that. – Ian Kirkpatrick Jul 20 '17 at 17:23
  • @IanKirkpatrick I'm just mentioning it because it seems like you didn't know about this way of entering binary in python, sorry if that's not the case I don't mean to offend you. But what I meant was not converting a string representation of the binary into an integer, but to do `msg = 0b10110111`. You can do a similar thing with hex, `test = 0xFF` for example. In some cases this makes code easier to understand – jacoblaw Jul 20 '17 at 17:27
  • 1
    @jacoblaw That `int("...", 2)` way is also less efficient, as that's a run-time calculation rather than compile-time. Might not matter, but still. It's just all-around worse. – Stefan Pochmann Jul 20 '17 at 18:10