Notes on BASIC Operators

The logical ('bit-wise') operators

The four operators AND, OR, EOR and NOT in BBC Basic are called the 'logical' or 'bit-wise' operators.

They are applied only to integer numbers, rather in a similar fashion to the arithmetic operators but with very much different results. The difference is that the logical operators act separately on each bit of the binary version of the integer numbers (and if you enter a real number, they will act only on the integer part of it).

AND needs two numbers and produces a single new number from them (it must not be confused with '+' sign, which gives a totally different result). AND compares the two numbers bit by bit ('bit-wise'). If both bits in a particular position are 1, the bit in the same position in the new number is 1 - otherwise it is 0. For example:

3 AND 5 produces the result 1.

3    %011
5    %101
------------------
1    %001

Only in the LSB ('bit 0') is there a 1 in the binary versions of both numbers 3 and 5 - so the result is &001. More closely, note that a 1 in any position on the bottom line of an AND operation will leave the bit in the same position in the top line unchanged - and a 0 in the bottom line always produces a 0 in the same position in the result, whatever the bit in the top line.

OR needs two numbers and produces a single new number from them. It again compares the two numbers bit by bit ('bit-wise'). If either bit (or both bits) in a particular position is 1, the bit in the same position in the new number is 1 - otherwise it is 0. For example:

17 OR 11 produces the result 27.

17   %10001
11   %01011
----------------------
27   %11011

Bit 2 is the only one which does not have a 1 in either (or both) positions, so the result is %11011 which is decimal 27. More closely, note that a 0 in any position on the bottom line of an OR operation leaves the bit in the same position in the top line unchanged, and a 1 in the bottom line produces a 1 in the same position in the result, whatever the bit in the top line.

EOR (called 'Exclusive OR') needs two numbers and produces a single new number from them. It also compares the two numbers bit by bit ('bit-wise'). If either bit (but not both) in a particular position is 1, the bit in the same position in the new number is 1 - otherwise it is 0. For example:

17 EOR 11 produces the result 26.

17   %10001
11   %01011
----------------------
26   %11010

This is similar to the previous example except that the LSB (bit 0) is 1 in both numbers, so the result is %11010, which is decimal 26. More closely, note that a 0 in any position on the bottom line of an EOR operation leaves the bit in the same position in the top line unchanged, and a 1 in the bottom line inverts the bit in the same position in the result.

NOT is the odd one out in that it acts on a single number only and produces a new number by simply changing every binary bit - all 32 of them, in fact! Every 0 is changed to a 1, and every 1 to a 0. This is called 'inverting' the number. (Note that inverting is not the same as the 'two's complement' - nor the same as 'putting a minus sign in front of it'.)

As NOT inverts all 32 bits (0-31), the numerical results are somewhat artificial because they are very much affected by Basic's 'two's complement' method of storing positive and negative integer numbers. For example:

NOT 3 produces the result -4

More important in practice is that NOT TRUE produces FALSE - and vice versa - because they are represented by -1 and 0 respectively. In fact, you are not likely to need NOT very much, except to reverse TRUE and FALSE.

Bit manipulation and 'masking'

It is probably obvious that the above logical operators are not a great deal of use for number manipulation. They come into their own for bit manipulation. In particular, they invaluable for extracting (or changing) parts of a multi-byte 'word', or just parts of single bytes - and this is often necessary, particularly in the Wimp environment.

For instance, if we wanted to ensure that any keyboard letter is converted to its upper case version - irrespective of the fact that either upper or lower case might have been generated by the keyboard itself - we simply AND the ASCII number of the keyboard press with 223. Thus, the sequence:

Letter%=GET
REM returns ASCII value of keypress
Letter$=CHR$(Letter% AND 223)
PRINT Letter$

will produce only the upper case versions of any keyboard letter pressed.

Why? Because the binary equivalent of 223 is %11011111, i.e. all bits except bit 5 are set. So, whatever number is substituted for Letter% in the expression:

Letter% AND 223

will produce a result with bit 5 definitely 'unset' and the others unchanged.

This means that the ASCII number for an upper case keypress (all in the range 65-90) will stay the same, but a lower case keypress (all in the range 97-122, i.e. 32 higher than upper case, by design) will have its bit 5 value changed from 1 to 0 and thus become its upper case equivalent (32 lower), i.e we have placed a 'mask' or 'sieve' over the binary version of the value of Letter% to change it.

Similarly, we often want to know the value of the number represented by, say, only the eight least significant bits of a 16-bit or 32-bit number. This can be extracted with:

Number% AND &FF

Remembering that &FF is %11111111, this operation will 'let through' (unaltered) bits 0-7 of <number>, but will change the value of all higher bits to 0. Thus, the result is a number equal to the contents of bits 0-7 of <number>.

EOR is very much used in graphics plotting, particularly when simulating the effect of a sprite object moving in front of (or behind) another.

The bit shift operators

Complementing the logical operators are the three operators '<<', ' >>' and '>>>' which are called the 'bit shift' operators. They are specifically designed to make binary bit manipulation easier, and they all operate on 32-bit integer numbers.

Their use is best described with examples:

Left-shift operator <<

Number% = 10 << 1 (or Number% = %1010 << 1 in binary)

will result in Number% being assigned with 20 (%10100 binary).
Number% = 10 << 3

will result in Number% being assigned with 80 (%1010000 binary).

Thus, the << operator shifts the values of all the bits in the preceding number (here, 10 (decimal) or %1010) to the left by the number of times specified by the following number (1 and 3 respectively here) - and a corresponding number of zeros are added to the righthand end afterwards.

In decimal, the effect of each left shift is to double the original number, as the examples show.

This operator is often used in Wimp programs to place particular values accurately into multi-bit parameters.

Right-shift operators >> and >>>

These both work in a similar fashion to the above but shifting the bit values to the right and 'dropping off' the original right-most bit value(s).

Thus the effect of one shift to the right:

Number%= 7 >> 1

is the same as:

Number%=7 DIV 2

and the result here will be 3.

The reason why two right-shift operators are needed stems from the point that all 32 bits are always involved. The particular way Basic stores integer numbers uses the left-most bit ('bit 31') to indicate positive or negative, so two operators are needed to provide a choice about how to deal with 'bit 31' after the right-shift has taken place, i.e. should the left-most bit be made a 0 or 1?

Hence, >>> shifts all 32 bit values to the right and introduces zeros at the left-most bit position - whereas >> shifts all bit values to the right and then makes 'bit 31' the same value as originally existed there.

For these reasons, >>> is called the "unsigned right-shift" and >> the "signed right-shift" (or "sign extended right-shift").

Thus, >> will retain the original positive or negative status of a number.

Accordingly, >>> is more often used to manipulate bit values in multi-bit parameters i.e. where the 32-bit 'number' is being used as a small 'parameter block' rather than as a normal number.


Source: Archive Magazine 12.12 - "Learners' Column"
Publication: Archive Magazine
Contributor: Ray Favre