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

(eax & CACHE_LEVEL) >> 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:

>>> eax = 0x4004121  # Taken from a register after executing a CPUID instruction with leaf-4 indicated
>>> 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) -> Generator[int, None, None]:
    acc = 1 << start_index
    for _ in range(start_index, end_index + 1):
        yield acc
        acc <<= 1

def parse_out_bits(bit_field: int, start_index: int, end_index: int) -> int:
    mask = sum(bit_place_values(start_index, end_index))
    return (mask & bit_field) >> 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) -> int:
    mask = (1 << (end_index - start_index + 1)) - 1
    return (bit_field >> start_index) & 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.
  • \$\begingroup\$ Nice. But gosh, bit arithmetic is hard for me to read. (you've got it quite nice tho) \$\endgroup\$ – Peilonrayz Jun 3 '20 at 0:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.