• Welcome to Valhalla Legends Archive.
 

merging (joining?) bitfields within a 32-bit integer

Started by tA-Kane, May 31, 2004, 01:25 AM

Previous topic - Next topic

tA-Kane

I've written a function that "merges" multiple bitfields to a single bitfield (that is, taken the example bitmask 00111000110011001 and put it into 00000000011111111), in REALbasic (essentially VB). I was wondering how you guys might do (have done?) it, though?

The reason I'm doing this is that I've read that some PPC32 assembly instructions have operands that are spread across multiple bitfields (though, I have yet to come across such an instance), and figured it wouldn't be bad to try my hand at implementing such an occurance, since it could also have uses in encryption (even if it is weak encryption).

So, here's the "master" function (and required support) that creates the resulting value from the multiple bitfields:BitField As Object
 StartBit(-1) As Integer
 EndBit(-1) As Integer
End Object

Function GetMaskedMergedBitFieldsValue(Value As Integer, Field As BitField) As Integer
 'bit zero is leftmost bit
 'field.startbit (array) is the start bit for that field indice
 'field.endbit (array) is the end bit for that field indice
 'the bitfields don't have to be in order with this joining algorithm (eg, field 1 can precede field 0 in the bitwise order)
 Dim rVal, Buffer, BitCount, i, Bound As Integer
 
 If Field = Nil Then
   Return 0'Bad field object
 End If
 
 Bound = uBound(Field.StartBit)
 If Bound = -1 Then
   Return 0'No bitfield
 End If
 
 rVal = 0'For ease of porting to C... this isn't needed in RB though, since it's automatically initialized to 0
 For i = 0 To Bound
   Buffer = GetBitField(Field.StartBit(i), Field.EndBit(i))
   Buffer = BitwiseAnd(Value, Buffer)
   Buffer = UnsignedRightBitShift(Buffer, 31-Field.EndBit(i))'RB doesn't have bitshifting capabilities, so this is a plugin function that I wrote in C that simple returns the value sifted to the right X by bits
   BitCount = (Field.EndBit(i) - Field.StartBit(i)) + 1
   rVal = UnsignedLeftBitShift(rVal, BitCount)'similar to UnsignedRightBitShift()... need to move the return value to the left to allow room for the current field
   rVal = BitwiseOr(rVal, Buffer)'now, add the buffer to the return value
 Next
 
 Return rVal
End Function

Function GetBitField(StartBit As Integer, EndBit As Integer) As Integer
 Dim rVal, i, Bound As Integer
 
 rVal = 0'again, ease of porting to C
 For i = StartBit To EndBit
   rVal = BitwiseOr(rVal, GetBit(i))
 Next
 
 Return rVal
End Function

Function GetBit(BitNumber As Integer) As Integer
 Return UnsignedLeftBitShift(1, 31-BitNum)'bits numbered (left to right) 0 to 31
End Function


I'm testing the code right now (forgot to do that before I started typing this up), but does anyone have any comments?

Edit: Successfully tested! Try out this code:Dim Field As BitField

Field = New BitField
Field.StartBit.Append 0
Field.EndBit.Append 0
Field.StartBit.Append 2
Field.EndBit.Append 4
Field.StartBit.Append 29
Field.EndBit.Append 31
MsgBox Bin(GetMaskedMergedBitFieldsValue(&b10111000000000000000000000000111, Field))


Assuming VB has a Bin() function, and Bin() returns the binary form of an integer, you should see seven 1s in a message box. The first one is from the left-most bitfield (with a field length of 1 bit), the next 3 from the second bitfield (with a field length of 3 bits), and the last 3 from the last bitfield (with a field length of 3 bits).

Again, any comments would be appreciated.

* tA-Kane goes to play some more with this function
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com

Adron

8-bit bitfield merge in PIC assembler:



i       equ 0xc
mask    equ 0xd
value   equ 0xe
merged  equ 0xf


mergebits
       movlw 8
       movwf i
       clrf merged, f
shiftbits
       rlf value, f
       btfsc mask, 7
       rlf merged, f
       rlf mask, f
       decfsz i, f
       goto shiftbits
       return


Adron

C++ bit transpose:


struct bittransposition {
  int srcpos, dstpos, len;
};

typedef std::list<bittransposition> transpositionlist;

unsigned transposebits(unsigned input, transpositionlist &definition)
{
 unsigned value = 0;
 transpositionlist::iterator it;
 for(it = definition.begin(); it != definition.end(); it++) {
   value |= ((input >> it->srcpos) & ((1 << it->len) - 1)) << it->dstpos;
 }
 return value;
}




I number my bits right to left, because that seems most natural to me, and to the applications I've seen. Code not tested.

tA-Kane

Quote from: Adron on May 31, 2004, 08:37 AMI number my bits right to left, because that seems most natural to me, and to the applications I've seen.
I agree. However, bits in PPC instructions are numbered left to right, so I programmed accordingly. :-\
Macintosh programmer and enthusiast.
Battle.net Bot Programming: http://www.bash.org/?240059
I can write programs. Can you right them?

http://www.clan-mac.com
http://www.eve-online.com