Operations with bits, bytes and shifts

Bitwise operations

Bitwise operations fundamentally deal with two bits at a time. There are three such operations. Bear in mind that a bit can have only two values, 0 and 1.

These can be interpreted in terms of logic. We sometimes think of 0 as representing "false" and 1 as representing "true". In that case, OR matches the way we use the ordinary word "or" in English: a compound statement "StatementA or StatementB" is regarded as true as long as at least one of the two is true. Likewise, AND matches the way we use the ordinary word "and" in English: a compound statement "StatementA and StatementB" is regarded as true only if both of the true are true. XOR corresponds to the "either-or" construction in English, that is, "one or the other but not both".

In our assembly language, there are four formats for bitwise instructions:

The fourth format is probably used more often the others.

What can we do with bitwise operations? There are several common uses.

Suppose I have a byte in which each bit is a separate piece of information. (For instance, there are LINUX programming situations in which we have an "attribute byte".) We may want to change the value of one bit at a time.

Example: Suppose we have

BYTE    DC  B'01110100'

and we would like to change the third bit of BYTE (counting from the left) to 0. We can do so with NI:

     NI  BYTE,B'11011111'

Likewise, if we would like to change the 7th bit of BYTE to 1, we can do so with OI:

     OI  BYTE,B'00000010'

(End of example)

There are two common uses of XOR. One is "XOR swapping", which looks lile this:

     XC    WORD1(10),WORD2
     XC    WORD2(10),WORD1
     XC    WORD1(1),WORD2

which has the effect of swapping the two values. (Try working through an example.)

The other common use of XOR is "XOR encryption", which looks like this: To encrypt, we use

     XC   MESSAGE(8),KEY

where MESSAGE and KEY are each (arbitrarily) 8 bytes long, and to decrypt, we use the same line of code. XOR encryption is so easy to code that is often used, although it is not regarded as an especially secure system


Shifts

We ran into shifts with packed decimal numbers, but here we are dealing with the bits in registers. There are several ways to do this.

How are the shifts encoded? The only novel feature here is the number N. It is encoded as if if is N(0,0).

Example: Suppose register 7 contains X'ABCD0123'. If we execute

     SLL   7,4

then register 7 will contain X'BCD01230.

If instead we execute

     SRL   7,8

then register 7 will contain X'00ABCD01'.

(End of example)


Inserting and storing individual bytes

We are familiar with Load and Store, which move 4 bytes at a time between a register and a fullword. Here we have some variations.

Example: Suppose register 7 contains X'EF019876' and a variable called OURDATA contains X'A0B1C2D3'.

If we execute

     IC   7,OURDATA

then register 7 will contain X'EF0198A0'.

If instead we execute

     ST   7,OURDATA

then OURDATA will contain X'76B1C2D3'.

If instead we execute

     ICM   7,B'0110',OURDATA

then register 7 will contain X'EFA0B176'.

If instead we execute

     STCM   7,B'1110',OURDATA

then OURDATA will contain X'EF0198D3'.

(End of example)


Comparing bytes

As with ICM and STCM, we are sometimes interested in just some of the bytes in a register. We can use Compare Logical Under Mask. The format for this is:

     CLM   R,M,D(B)

Here M and D(B) are as in ICM or STCM. As before, 1s in the mask indicate which bytes in the register are of interest. We compare indicated bytes in the register to consecutive bytes at D(B) and set the condition code as in any other comparison instruction.

Example: Suppose register 8 contains X'AA04BBDD' and a variable called YOURDATA contains X'04CC0123'.

If we execute

     CLM   8,B'0100',YOURDATA

then we are comparing X'04' to X'04', and the condition code will be 0.

If instead we execute

     CLM   8,B'0101',YOURDATA

then we are comparing X'04DD' to X'04CC', and the condition code will be 2.

(End of example)


Comparing bits

As mentioned above, we can use OI and NI to set the values of specific bits in a byte. Sometimes we may want to find out the value of a specific bit. We can use Test Under Mask. The format for this is:

     TM   D(B),I

Here the immediate byte I is treated as an 8-bit mask. The 1s in the mask indicate which bits in the byte at D(B) are of interest.

All TM does is set the condition code:

Example: Suppose a variable called BYTE contains B'11110000'.

If we execute

     TM   BYTE,B'00011000'

then the condition code will be 1.

If instead we execute

     TM   BYTE,B'11000000'

then the condition code will be 3.

(End of Example)

If I wanted to find out about the 4th bit of a byte, I could use a mask of B'00010000'.