Shop OBEX P1 Docs P2 Docs Learn Events
Bitwise Operator Help: Trying to build function that returns bits from a binary number using a mask — Parallax Forums

Bitwise Operator Help: Trying to build function that returns bits from a binary number using a mask

Hey guys,
Its been a while since I have messed around with binary operators, and I am having a difficult time wrapping my head around how to accomplish this. An explanation would be awesome as well.

So say I have a number like this: 1110_1010
I want to build a mask and have it return those bits, for example: 0000_1110
Since I have specified a 1 on bit position 1,2 and 3, then this would return those bit positions from the original number, in this case the answer would be: 101

So the function would be in this format: GetBits(binaryNumber,mask). You provide the binary number and mask, and it returns to you the answer.

I am assuming I need to use the bitwise shift operators, but I am just not sure.

I know if I do an & operation, e.g. "1110_1010 & 0000_1110" this would return 1010, so it seems I need to utilize the shift and & operator somehow.
Any help is greatly appreciated, thanks!

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-09-29 01:08
    y := (x >> 4) & %1111

    If x is a byte variable, you can skip the &.

    -Phil
  • SeairthSeairth Posts: 2,474
    edited 2015-09-29 01:58
    So, assuming you are looking to mask a value, then shift the result to remove the least-significant zeros, it would look something like this:

    (PASM)
    fbits           and value, mask wz     ' mask the desired bits in value
            if_z    jmp #fbits_ret         ' if the result is zero, jump to end
    :shift          shr value, #1 wc       ' otherwise, shift value one bit to the right (capturing LSB in C)
            if_nc   jmp #:shift            ' if the LSB wasn't 1, repeat shift operation
                    rcl value, #1          ' C=1, shift it back in (undo the last "shr")
    fbits_ret       ret                    ' value contanis the results
    		
    value           res 1
    mask            res 1
    

    (SPIN)
    result := value & mask
    
    if (result <> 0)
      repeat while (result & 1) <> 1
        result >>= 1
    

    There may be more clever ways of doing this, but these should clearly show your intent.
  • Why the shift by 4? Where's the mask?

    From your question, it appears you want the binaryNumber & mask, with the result shifted to the LSB.
    PUB GetBits(binaryNumber,mask)
      if mask <> 0 
        repeat while mask & 1 == 0
          mask >>= 1
          binaryNumber >>= 1
    
        result := binaryNumber & mask
    
  • kwinnkwinn Posts: 8,697
    edited 2015-09-29 02:18
    Mahonroy wrote: »
    Hey guys,
    Its been a while since I have messed around with binary operators, and I am having a difficult time wrapping my head around how to accomplish this. An explanation would be awesome as well.

    So say I have a number like this: 1110_1010
    I want to build a mask and have it return those bits, for example: 0000_1110
    Since I have specified a 1 on bit position 1,2 and 3, then this would return those bit positions from the original number, in this case the answer would be: 101

    So the function would be in this format: GetBits(binaryNumber,mask). You provide the binary number and mask, and it returns to you the answer.

    I am assuming I need to use the bitwise shift operators, but I am just not sure.

    I know if I do an & operation, e.g. "1110_1010 & 0000_1110" this would return 1010, so it seems I need to utilize the shift and & operator somehow.
    Any help is greatly appreciated, thanks!

    Do you want the result shifted based on the first high bit in the mask, the first high bit in the binary number, or the first high bit in the binary result?
  • kwinn wrote: »
    Do you want the result shifted based on the first high bit in the mask or the first high bit in the binary number?

    Heh. I noticed @Sapphire's answer differed from mine in exactly that way. :)

  • kwinnkwinn Posts: 8,697
    edited 2015-09-29 02:24
    Seairth wrote: »
    kwinn wrote: »
    Do you want the result shifted based on the first high bit in the mask or the first high bit in the binary number?

    Heh. I noticed @Sapphire's answer differed from mine in exactly that way. :)

    Yes, the answer to the question makes a difference.

    PS You're too fast. Got it before I edited it.

  • Man, I totally misread the OP's intent. Here's a routine that ought to work:
    PUB GetBits(binaryNumber, mask)
    
      return (binaryNumber & mask) >> (32 - >|(mask >< 32))
    

    -Phil

  • MahonroyMahonroy Posts: 175
    edited 2015-09-29 17:43
    Thanks a lot for all of the responses and help!
    kwinn wrote: »
    Do you want the result shifted based on the first high bit in the mask, the first high bit in the binary number, or the first high bit in the binary result?

    The result should be shifted based on the first high bit in the mask only.

    Seairth and Saphire, I think I am understanding this, thanks for the function. So this is basically trimming the end off both the number and the mask until a 1 is reached on the mask, then it returns this as the result? I think the problem is this will return bits after the mask as well.

    EDIT: I just re-read the function and noticed that you AND the binary number again with the mask as you are returning it... it looks like this would work. It would not work of the mask had any 0's in the middle... but thats probably fine.
    Man, I totally misread the OP's intent. Here's a routine that ought to work:
    PUB GetBits(binaryNumber, mask)
    
      return (binaryNumber & mask) >> (32 - >|(mask >< 32))
    

    -Phil

    So this is my interpretation of this, let me know if this is correct. You AND the binary number and mask together, which will return all of the bits of the binary number up to the MSB (most significant bit) of the mask. In this case using the example numbers I mentioned above, this would return "1010". It looks like the next goal is to shift the number over X amount of times until the LSB is reached in the mask is that right? So in this case, you are taking the first 32 bits and returning them in reverse order. It then looks like you are taking the number 32 and rotating it to the right by the reversed bits number..... I'm not following this part, can you explain please?
  • JonnyMacJonnyMac Posts: 9,105
    edited 2015-09-29 22:31
    >| returns a value, 0 to 32, of the highest bit set. If no bits are set 0 is the result. If bit 31 is set, 32 is the result.

    Phil used 32 (bits in a long) to flip your mask with ><. In your case %1110 becomes %01110000_00000000_00000000_00000000. Run this through >| and you get 31 (bit 30 is highest set). Subtract that from 32 and you get the number of bits to right shift for your original mask.

    As ever, Phil is a clever dude.
  • Ok this makes perfect sense, thanks!!
Sign In or Register to comment.