Bytes & Bits ..

BlitzMax Forums/BlitzMax Programming/Bytes & Bits ..

mic_pringle(Posted 2010) [#1]
Hi,

If I define a variable as a byte, is it possible to read and set each of the 8 individual bits ?

If so, can someone please give me a quick example of how ?

Thanks

-Mic


GfK(Posted 2010) [#2]
This will set (for example) bit 5 and bit 8:
Strict

Local bit:Byte

bit:| (1 Shl 4)
bit:| (1 Shl 7)

Print Bin(bit)

Note that if you run this code, the output will show 32-bits. This is only because Bin() treats the given value as an int, not a byte.


mic_pringle(Posted 2010) [#3]
@Gfk

Thanks for this.

Could you explain what this code is doing exactly ? For instance what does the :| mean ?

Also, when I run this the output is 00000000000000000000000010010000 but I was only expecting 10010000. Why are there so many leading zeros ? Is this to do with the Bin command or is a byte in BlitzMax bigger than what I think it should be ?

Finally, how can I read a particular bit. For instance how would I determine if bit 5 has been set ?

(I hope you don't mind all the questions)

Thanks

-Mic


GfK(Posted 2010) [#4]
Could you explain what this code is doing exactly ? For instance what does the :| mean ?
In laymens terms it takes the value of 1 (%00000001 in binary form), and shifts the bits (shl) four places to the left, making it %00010000.

The bar (|) is bitwise AND. In other words, it takes whatever's already there and combines it with the new value. So if you have %10000000 and %00000001, then those two values combined with bitwise AND would result in %10000001.

The colon(:) is just shorthand. The longer version of the same code would be:
bit = bit | (1 Shl 4)

You can use this for all mathematical operations in Blitzmax, i.e.
A = A + 1
is the same as
A:+1


Also, when I run this the output is 00000000000000000000000010010000 but I was only expecting 10010000. Why are there so many leading zeros ? Is this to do with the Bin command or is a byte in BlitzMax bigger than what I think it should be ?
As I explained in my first post (which may not have been there when you read it, as I edited it shortly after) - Bin takes a 32bit integer as its value. So if you pass a byte to it, Bin will still parse it as if it were an Int.

Finally, how can I read a particular bit. For instance how would I determine if bit 5 has been set ?
Strict

Local bit:Byte = %00010000 'set bit 5

Print (bit & %00010000) Shr 4 'isolate bit 5, and shift it four places to the right (i.e. result will be %00000001)

Or you could also do this:
Print bit & %00010000
Which would result in 16. So obviously the bit is set. If it wasn't, you'd get 0. I prefer the first method for consistency when doing bit-level stuff but its personal preference.


mic_pringle(Posted 2010) [#5]
@Gfk

Thanks for this detailed response, it's really appreciated and it really has cleared things up.

-Mic


Brucey(Posted 2010) [#6]
Or with less digits :
Print bit & $10

The $ in front of the number indicates it is hexadecimal :
$001 = 1      = %00000001
$002 = 2      = %00000010
$004 = 4      = %00000100
$008 = 8      = %00001000
$010 = 16     = %00010000
$020 = 32     = %00100000
$040 = 64     = %01000000
$080 = 128    = %10000000

etc.


Shortwind(Posted 2010) [#7]
GFK: Good post, but the bar, |, is OR and the & is AND.

AND truth table: (0 = false, 1 = true)

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

AND can only be TRUE if both bits are true. (The order of the bits does not matter, I just showed them here to be more clear.)

OR truth table:

0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

OR can only be FALSE if both bits are false. (Again, the order of the bits don't matter, I just showed them to be more clear.)

:D

Just for completeness here is the XOR (Exclusive OR) truth table:

0 ~ 0 = 0
0 ~ 1 = 1
1 ~ 0 = 1
1 ~ 1 = 0

XOR can only be true if both bits are different.

(By the way, you can find this in the BlitzMax help under "Expressions")

Below are some simple fast functions for bit fiddling. (Basically the same idea as GFK and others, but put into functions for easier use.)

Strict
Local a:Int=0
Local b:Int=1
Local c:Int=0

Function SetBit:Int(x:Int, bit:Int) 'x=the Int with the value, bit is the bit to set, ie. 0-31
	Return x | (1 Shl bit)
End Function

Function ClearBit:Int(x:Int, bit:Int)
	Return x & ~(1 Shl bit)
End Function

Function ToggleBit:Int(x:Int, bit:Int)
	Return x ~ (1 Shl bit)
End Function

Function ReadBit:Int(x:Int, bit:Int) 'This function returns 0 or 1...
	If (x & (1 Shl bit)) Return 1
	Return 0 
End Function

Print "Original number= "+Bin(a)
a=setbit(a,b)
Print "Number after bit ("+b+") was set="+Bin(a)
a=clearbit(a,b)
Print "Number after bit ("+b+") was cleared="+Bin(a)
a=togglebit(a,6)
Print "Number after bit (6) is toggled="+Bin(a)
a=togglebit(a,6)
Print "Again, Number after bit (6) is toggled="+Bin(a)
Print
Print "To read bit 6, from the a variable, call the ReadBit Function:"
c=readbit(a,6)
Print "Bit 6 = "+c