As mentioned in the title, I came across a BEXTR (bit extract) instruction on x86 assembly but I cannot seem to wrap my head around how it works.
After looking online for some time, I even found a supposed C equivalent (src >> start) & ((1 << len) -1)
which I can't really seem to understand either.
Can anyone explain to me how BEXTR instruction works? How are the bits extracted?
CodePudding user response:
A picture might help. Say the starting bit is 5 and the length is 9. Then if we have
Input : 11010010001110101010110011011010 = 0xd23aacda
|-------|
\
\
\
v
|-------|
Output: 00000000000000000000000101100110 = 0x00000166
The desired block of bits goes to the least significant bits of the output, and the remaining bits of the output become 0.
CodePudding user response:
How are the bits extracted?
We don't really need to know how the bits are extracted, as that could vary between implementations. All we need to know is which bits are extracted.
In general, a bit field is a sequential set of bits potentially surrounded by unwanted bits before and after the bit field. So, the idea is to remove those unwanted bits and move the sequential bits of the bit field of interest to be right justified.
That C formula breaks down into components as follows:
First, src >> start
shifts bit start
to bit position 0, effectively right justifying the bit field of interest. This both moves the bit field of interest into the proper right justified position, as well as eliminating lower bits not of interest (bits of lessor significance, i.e. below the bit field wanted).
What remains to be done is to strip any unwanted bits from above the length
. To do this that formula creates what we call a mask. First, 1<<len
generates a power of two value by shifting 1 (the lowest power of 2) to the left. So, the number looks like 1 followed by len
number of zeros (e.g. for len=3, then ..001000). Subtracting one from a power of 2 makes a mask (e.g. 001000-1=000111) of consecutive 1's that here is len
bits of 1 in count. That mask is applied to the shifted result, to remove any unwanted high order bits (bits of higher significance) that are not in the bit field of interest.
Another approach in C, would be to shift left to left justify the bit field, then shift that right to right justify the bit field. This shifting eliminates any unwanted bits both high and low, while leaving the bit field right justified, since that is the last shift. This approach can also extract both signed and unsigned bit fields, by making the right shift arithmetic vs. logical.