VB.NET doesn't support bit level operations directly. Framework 1.1 (VB.NET 2003) introduced bit shift operators (**<<** and **>>**), but no general purpose way to manipulate individual bits is available. Bit operations *can* be very useful. For example, your program might have to interface with another system that requires bit manipulation. But in addition, there are a lot of tricks that can be done using individual bits.

This article surveys what can be done with bit manipulation using VB.NET.

You need to understand **bitwise operators** before anything else. In VB.NET, these are: ** **

- And
- Or
- Xor
- Not

Bitwise simply means that the operations can be performed on two binary numbers bit by bit. Microsoft uses **truth tables** to document bitwise operations. The truth table for **And** is:

1st Bit 2nd Bit Result

1 1 1

1 0 0

0 1 0

0 0 0

In my school, they taught **Karnaugh** maps instead. The Karnaugh map for all four operations are shown in the illustration below.

**--------Click Here to display the illustrationClick the Back button on your browser to return--------**

Here's a simple example using the **And** operation with two, four bit binary numbers:

The result of 1100 **And** 1010 is 1000.

That's because 1 **And** 1 is 1 (the first bit) and the rest are 0.

To begin with, let's take a look at the bit operations that *are* directly supported in VB.NET: **bit shifting**.

Although both left shift and right shift are available, they work the same way so only left shift will be discussed. Bit shifting is most often used in cryptography, image processing and communications.

VB.NET's bit shifting operations ...

- Only work with the four types of integers:
**Byte**,**Short**,**Integer**, and**Long**

- Are
**arithmetic**shifting operations. That means that bits shifted past the end of the result are thrown away, and the bit positions opened up on the other end are set to zero. The alternative is called circular bit shifting and the bits shifted past one end are simply added to the other. VB.NET doesn't support circular bit shifting directly. If you need it, you'll have to code it the old fashioned way: multiplying or dividing by 2. - Never generate an overflow exception. VB.NET takes care of any possible problems and I'll show you what that means. As noted, you can code your own bit shifting by multiplying or dividing by 2, but if you use the "code your own" approach, you have to test for overflow exceptions that can cause your program to crash.

A standard bit shifting operation would look something like this:

**Dim StartingValue As Integer = 14913080Dim ValueAfterShifting As IntegerValueAfterShifting = StartingValue << 50**

In words, this operation takes the binary value **0000 0000 1110 0011 1000 1110 0011 1000** (14913080 is the equivalent decimal value - notice that it's just a series of 3 0's and 3 1's repeated a few times) and shifts it 50 places left. But since an Integer is only 32 bits long, shifting it 50 places is meaningless.

VB.NET solves this problem by **masking** the shift count with a standard value that matches the data type being used. In this case, **ValueAfterShifting** is an **Integer** so the maximum that can be shifted is 32 bits. The standard mask value that works is 31 decimal or 11111.

**Masking** means that the value, in this case 50, is **And**ed with the mask. This gives the maximum number of bits that can actually be shifted for that data type.

In decimal:

**50 And 31** is **18** - The maximum number of bits that can be shifted

It actually makes more sense in binary. The high order bits that can't be used for the shifting operation are simply stripped away.

**110010 And 11111** is **10010**

When the code snippet is executed, the result is 954204160 or, in binary, 0011 1000 1110 0000 0000 0000 0000 0000. The 18 bits on the left side of the first binary number are shifted off and the 14 bits on the right side are shifted left.

The other big problem with shifting bits is what happens when the number of places to shift is a negative number. Let's use -50 as the number of bits to shift and see what happens.

**ValueAfterShifting = StartingValue << -50**

When this code snippet is executed, we get -477233152 or 1110 0011 1000 1110 0000 0000 0000 0000 in binary. The number has been shifted 14 places left. Why 14? VB.NET assumes that the number of places is an unsigned integer and does an **And** operation with the same mask (31 for Integers).

**1111 1111 1111 1111 1111 1111 1100 11100000 0000 0000 0000 0000 0000 0001 1111(And)----------------------------------0000 0000 0000 0000 0000 0000 0000 1110**

1110 in binary is 14 decimal. Notice that this is the reverse of shifting a positive 50 places.

On the next page, we move on to some other bit operations, starting with **Xor Encryption**!

I mentioned that one use of bit operations is encryption. Xor encryption is a popular and simple way to "encrypt" a file. In my article, Very Simple Encryption using VB.NET, I show you a better way using string manipulation instead. But Xor encryption is so common that it deserves to at least be explained.

Encrypting a text string means translating it into another text string that doesn't have an obvious relationship to the first one.

You also need a way to decrypt it again. Xor encryption translates the binary ASCII code for each character in the string into another character using the Xor operation. In order to do this translation, you need another number to use in the Xor. This second number is called the key.

Xor encryption is called a "symmetric algorithm". This means that we can use the encryption key as the decryption key too.

Let's use "A" as the key and encrypt the word "Basic". The ASCII code for "A" is:

**0100 0001 (decimal 65)**

The ASCII code for Basic is:

**B - 0100 0010a - 0110 0001s - 0111 0011i - 0110 1001c - 0110 0011**

The **Xor** of each of these is:

**0000 0011 - decimal 30010 0000 - decimal 320011 0010 - decimal 500010 1000 - decimal 400010 0010 - decimal 34**

This little routine does the trick:

**-- Xor Encryption --Dim i As ShortResultString.Text = ""Dim KeyChar As IntegerKeyChar = Asc(EncryptionKey.Text)For i = 1 To Len(InputString.Text) ResultString.Text &= _ Chr(KeyChar Xor _ Asc(Mid(InputString.Text, i, 1)))Next**

The result can be seen in this illustration:

**--------Click Here to display the illustrationClick the Back button on your browser to return--------**

To reverse the encryption, just copy and paste the string from the Result TextBox back into the String TextBox and click the button again.

Another example of something you can do with bitwise operators is to swap two Integers without declaring a third variable for temporary storage.

This is the kind of thing they used to do in assembly language programs years ago. It's not too useful now, but you might win a bet someday if you can find someone who doesn't believe you can do it. In any case, if you still have questions about how **Xor** works, working through this should put them to rest. Here's the code:

**Dim FirstInt As IntegerDim SecondInt As IntegerFirstInt = CInt(FirstIntBox.Text)SecondInt = CInt(SecondIntBox.Text)FirstInt = FirstInt Xor SecondIntSecondInt = FirstInt Xor SecondIntFirstInt = FirstInt Xor SecondIntResultBox.Text = "First Integer: " & _ FirstInt.ToString & " - " & _ "Second Integer: " & _ SecondInt.ToString**

And here's the code in action:

**--------Click Here to display the illustrationClick the Back button on your browser to return--------**

Figuring out exactly why this works will be left as "as an exercise for the student".

On the next page, we reach the goal: General Bit Manipulation

Although these tricks are fun and educational, they're still no substitute for general bit manipulation. If you really get down to the level of bits, what you want is a way to examine individual bits, set them, or change them. That's the real code that is missing from .NET.

Perhaps the reason it's missing is that it's not that hard to write subroutines that accomplish the same thing.

A typical reason you might want to do this is to maintain what is sometimes called a **flag byte**.

Some applications, especially those written in low level languages like assembler, will maintain eight boolean flags in a single byte. For example, a 6502 processor chip's status register holds this information in a single 8 bit byte:

**Bit 7. Negative flagBit 6. Overflow flagBit 5. UnusedBit 4. Break flagBit 3. Decimal flagBit 2. Interrupt-disable flagBit 1. Zero flagBit 0. Carry flag**

*(from Wikipedia)*

If your code has to work with this kind of data, you need general purpose bit manipulation code. This code will do the job!

**' The ClearBit Sub clears the 1 based, nth bit' (MyBit) of an integer (MyByte).Sub ClearBit(ByRef MyByte, ByVal MyBit) Dim BitMask As Int16 ' Create a bitmask with the 2 to the nth power bit set: BitMask = 2 ^ (MyBit - 1) ' Clear the nth Bit: MyByte = MyByte And Not BitMaskEnd Sub' The ExamineBit function will return True or False' depending on the value of the 1 based, nth bit (MyBit)' of an integer (MyByte).Function ExamineBit(ByVal MyByte, ByVal MyBit) As Boolean Dim BitMask As Int16 BitMask = 2 ^ (MyBit - 1) ExamineBit = ((MyByte And BitMask) > 0)End Function' The SetBit Sub will set the 1 based, nth bit' (MyBit) of an integer (MyByte).Sub SetBit(ByRef MyByte, ByVal MyBit) Dim BitMask As Int16 BitMask = 2 ^ (MyBit - 1) MyByte = MyByte Or BitMaskEnd Sub' The ToggleBit Sub will change the state' of the 1 based, nth bit (MyBit)' of an integer (MyByte).Sub ToggleBit(ByRef MyByte, ByVal MyBit) Dim BitMask As Int16 BitMask = 2 ^ (MyBit - 1) MyByte = MyByte Xor BitMaskEnd Sub**

To demonstrate the code, this routine calls it (parameters not coded on Click Sub):

**Private Sub ExBitCode_Click( ... Dim Byte1, Byte2 As Byte Dim MyByte, MyBit Dim StatusOfBit As Boolean Dim SelectedRB As String StatusLine.Text = "" SelectedRB = GetCheckedRadioButton(Me).Name Byte1 = ByteNum.Text ' Number to be converted into Bit Flags Byte2 = BitNum.Text ' Bit to be toggled ' The following clears the high-order byte & returns only the ' low order byte: MyByte = Byte1 And &HFF MyBit = Byte2 Select Case SelectedRB Case "ClearBitButton" ClearBit(MyByte, MyBit) StatusLine.Text = "New Byte: " & MyByte Case "ExamineBitButton" StatusOfBit = ExamineBit(MyByte, MyBit) StatusLine.Text = "Bit " & MyBit & _ " is " & StatusOfBit Case "SetBitButton" SetBit(MyByte, MyBit) StatusLine.Text = "New Byte: " & MyByte Case "ToggleBitButton" ToggleBit(MyByte, MyBit) StatusLine.Text = "New Byte: " & MyByte End SelectEnd SubPrivate Function GetCheckedRadioButton( _ ByVal Parent As Control) _ As RadioButton Dim FormControl As Control Dim RB As RadioButton For Each FormControl In Parent.Controls If FormControl.GetType() Is GetType(RadioButton) Then RB = DirectCast(FormControl, RadioButton) If RB.Checked Then Return RB End If Next Return NothingEnd Function**

The code in action looks like this:

Click Here to display the illustration

Click the Back button on your browser to return

--------