Parsing a sequence of bits out of a bit field For homework, I had to parse CPUID instruction output in C, which required a lot of specific bit-manipulation like:

(eax &amp; CACHE_LEVEL) &gt;&gt; 5


I calculated the mask CACHE_LEVEL and the amount that was needed to be right-shifted by hand. It was a pain, so I decided to write a couple Python functions to help with this.

For example:

&gt;&gt;&gt; eax = 0x4004121  # Taken from a register after executing a CPUID instruction with leaf-4 indicated
&gt;&gt;&gt; parse_out_bits(eax, 5, 7)  # Return the value at bits 5 to 7 (inclusive)
1  # This is an L1 cache


Indices are 0-based and inclusive.

Where eax is the following, and I want the value of the bits from S to E:

                        E S
100 0000 0000 0100 0001 0010 0001‬


I'd like notes on anything here, but specifically how this could be done better in terms of bit manipulation.

from typing import Generator

def bit_place_values(start_index: int, end_index: int) -&gt; Generator[int, None, None]:
    acc = 1 &lt;&lt; start_index
    for _ in range(start_index, end_index + 1):
        yield acc
        acc &lt;&lt;= 1

def parse_out_bits(bit_field: int, start_index: int, end_index: int) -&gt; int:
    mask = sum(bit_place_values(start_index, end_index))
    return (mask &amp; bit_field) &gt;&gt; start_index
This is not the kind of thing you should loop for. Just calculate a mask:

def parse_out_bits(bit_field: int, start_index: int, end_index: int) -&gt; int:
    mask = (1 &lt;&lt; (end_index - start_index + 1)) - 1
    return (bit_field &gt;&gt; start_index) &amp; mask


In English:


If you're getting bits 5-7, that's 3 bits
2^3 == 8, - 1 = 7 (or 111 in binary - that is your mask)
Shift the field right by 5 to put the bits of interest in the least-significant position
And-mask them to get the result.