Basic was never designed to mess with bits. Sure, it has Xor, And, Or, and Not operators. In fact, it even has Eqv and Imp logical operators that you won’t find (or need) in most other languages. But it lacks unsigned integers, and its numeric type conversion facilities are extremely safe—excessively so for bit operations. As a result, the simplest operations turn out to be unexpectedly messy.
At the risk of boring some readers, let’s review what a 16-bit integer is to a computer, what it is to Basic, and what it is to the Windows API. To a computer, a 16-bit integer is simply a stream of 16 bits of data. A computer language can look at this stream of bits as a signed integer with a value in the range -32768 through 32767, as an unsigned integer ranging from 0 through 65535, or as 16 independent bits. (In a signed integer, the high bit signals negative numbers; in an unsigned integer, the high bit is just more numeric data.)
The Basic language simplifies matters by recognizing integers only as signed integers and, to a certain extent, as bit flags. As long as you stick with 16 bits, this is sufficient. When you mix 16-bit and 32-bit numbers, however, you get into trouble. The problem: Basic claims that 32768 is always a 32-bit number, although any assembly language programmer will assure you that it’s a perfectly valid 16-bit unsigned number. When you specify a number in hexadecimal (&HFFFF), as you tend to do when working with bits, it’s easy to forget that the high bit (&H8000) represents the negative sign.
Visual Basic version 4 added one more spice to this stew. The Byte type is actually an unsigned type representing values from 0 through 255. You can’t assign -25 to a Byte variable.
To clarify this discussion, we can use the low-level terminology of debuggers (which also happens to be the high-level terminology of Windows). An unsigned character is a Byte. An unsigned 2-byte integer is a Word. An unsigned 4-byte integer is a DWord.
The two most common bitwise operations are cramming Bytes into Words and Words into DWords, and ripping Bytes out of Words and Words out of Dwords. Let’s have a look.