Microsoft KB Archive/62889

COBOL Program to Manipulate Bits: AND, OR, NOT, XOR (Complete)

PSS ID Number: Q62889 Article last modified on 06-24-1993

3.00 3.00a MS-DOS

Summary: Microsoft COBOL Compiler versions 3.00 and 3.00a for MS-DOS and MS OS/2 do not have built-in functions for performing bit manipulating operations (AND, OR, NOT, and XOR). These functions can be simulated, however, by writing a COBOL routine to get the status (on or off) of a bit in a data item. This routine can be used to compare the status of the corresponding bits in two data items. The result of the comparisons would determine (depending on the operation) which bits would be on or off in the resultant data item. The sample programs below show how this is done. This information applies to Microsoft COBOL Compiler versions 3.00 and 3.00a for MS-DOS and MS OS/2.

More Information: Bit manipulating refers to setting or reading the status of a bit in a data item, which may be required for decoding information returned by DOS interrupts or OS/2 functions. For example, the number 120, stored in a 1-byte-long data item, has the following binary format:

7  6   5   4   3   2   1   0   <--- bits +—+—+—+—+—+—+—+—+ | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | <— status (1=on, 0=off) +—+—+—+—+—+—+—+—+ 120 = 2^6 + 2^5 + 2^4 + 2^3 = 64 + 32 + 16 + 8 = 120

Suppose we want to find out if bit 4 is on. We first need to set all the other bits to 0, if they aren’t already. This involves shifting the value of bit 4 to the leftmost position in the data item, bit 7. Then we shift the value in bit 7 to the rightmost position, bit 0. When a bit value is shifted, the bits in front of it are cleared (set to 0). If the original bit 4 was on, bit 0 will now be on. This gives the data item a value of 1 (2^0 = 1). If bit 4 was originally off, bit 0 will be off. Note that shifting the bits of a data item involves multiplying (shift left) or dividing (shift right) the data item by a power of two. The power used is the number of bit positions to shift. The following is an illustration of the process:

7  6   5   4   3   2   1   0 +—+—+—+—+—+—+—+—+ | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +—+—+—+—+—+—+—+—+

Above is the number 120, unshifted. To get the value of bit 4 moved to bit 7, the bits of the data item must be shifted three positions to the left. In other words, multiply the data item by 2^3, as shown:

7  6   5   4   3   2   1   0 +—+—+—+—+—+—+—+—+ | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | +—+—+—+—+—+—+—+—+

The value in the original bit 4 position has now been shifted to bit 7. Note that the original values of bits 5, 6, and 7 have been lost (pushed left off the edge of the data item). The original value in bit 3 is still intact because it followed bit 4 leftward and is now in bit 6. To clear it, we must move the value in bit 7 to bit 0 (seven bit positions), pushing bits 0 through 6 off the right edge of the data item. This shift is accomplished by dividing the data item by 2^7, as follows:

7  6   5   4   3   2   1   0 +—+—+—+—+—+—+—+—+ | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | +—+—+—+—+—+—+—+—+

At this point, the value of bit 7 (which used to be in bit 4) is in bit 0. All the bits to the left and right of the original bit 4 have been cleared. Next we have to test if the data item equals 1 or 0. Since bit 4 was on, the data item will be 1 (2^0 = 1). We now have a way of testing whether a bit in a data item is on or off. We can write routines that compare the bits of two data items and determine (depending on whether we are performing an AND, OR, NOT, or XOR operation) what the status of the bits of the resulting data item will be. The following table illustrates the results of using each bit-manipulation operation on four combinations of a pair of bit statuses (note that the NOT operation uses only one bit status):

+———–+ | AND | +———–+—+—+—+—+ | Status #1 | 0 | 1 | 0 | 1 | +———–+—+—+—+—+ | Status #2 | 0 | 0 | 1 | 1 | +———–+—+—+—+—+ | Result | 0 | 0 | 0 | 1 | +———–+—+—+—+—+ +———–+ | OR | +———–+—+—+—+—+ | Status #1 | 0 | 1 | 0 | 1 | +———–+—+—+—+—+ | Status #2 | 0 | 0 | 1 | 1 | +———–+—+—+—+—+ | Result | 0 | 1 | 1 | 1 | +———–+—+—+—+—+ +——–+ | NOT | +——–+—+—+ | Status | 0 | 1 | +——–+—+—+ | Result | 1 | 0 | +——–+—+—+ +———–+ | XOR | +———–+—+—+—+—+ | Status #1 | 0 | 1 | 0 | 1 | +———–+—+—+—+—+ | Status #2 | 0 | 0 | 1 | 1 | +———–+—+—+—+—+ | Result | 0 | 1 | 1 | 0 | +———–+—+—+—+—+

For example, suppose we are performing an AND operation on the numbers 120 and 30. These numbers have the following binary format:

7  6   5   4   3   2   1   0 +—+—+—+—+—+—+—+—+ | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | <— 120 +—+—+—+—+—+—+—+—+ 7 6 5 4 3 2 1 0 +—+—+—+—+—+—+—+—+ | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | <— 30 +—+—+—+—+—+—+—+—+

If we AND them together, we get 24. The only bit statuses they have in common are bit 3 (2^3 = 8) and bit 4 (2^4 = 16):

01111000 00011110 ——– 00011000 = 24

The sample programs below demonstrate the four bit-manipulation operations. The main program (TWIDBITS.CBL) prompts you for an operation to perform and one or two numbers (one for the NOT operation) to perform the operation on. Each operation routine circulates through the bits of the data item(s) being operated on, calls another routine to test the status of each bit, and performs the appropriate comparisons. Finally, the result of the operation is displayed.

$SET ANS85 IDENTIFICATION DIVISION. PROGRAM-ID. TwidBits. DATA DIVISION. WORKING-STORAGE SECTION. * Boolean operation to perform on DataItem1 and DataItem2. 01 Operation   PIC 9(2) COMP-5. * Used to ACCEPT 3-digit numbers for DataItem1, DataItem2. 01 AcceptItem  PIC 9(3). * Data items to be operated on. 01 DataItem1   PIC 9(2) COMP-5. 01 DataItem2   PIC 9(2) COMP-5. * Result of boolean operation on DataItem1 and DataItem2. 01 Result      PIC 9(2) COMP-5. * Used to get next key (if any) from buffer. 01 AnyKey      PIC 9(2) COMP-X. PROCEDURE DIVISION. *   If user enters 5 for operation (QUIT), end program. PERFORM UNTIL Operation = 5 *      Clear screen and display menu. CALL X&quot;E4&quot; DISPLAY &quot;1=AND  2=OR   3=NOT   4=XOR   5=QUIT&quot; AT 0101 *      Get boolean operation to perform. DISPLAY &quot;Operation          : &quot;  AT 0301 ACCEPT Operation *      If &quot;QUIT&quot; not selected then proceed. IF Operation NOT = 5 THEN *         Get first (or only if Operation = 3) data item DISPLAY &quot;Data item 1 (0-255) : &quot; AT 0401 ACCEPT AcceptItem MOVE  AcceptItem TO DataItem1 *         Initialize result of operation to 0. MOVE 0 TO Result *         If operation = AND, OR or XOR, 2 data items are needed. IF Operation NOT = 3 THEN DISPLAY &quot;Data Item 2 (0-255) : &quot; AT 0501 ACCEPT AcceptItem MOVE  AcceptItem TO DataItem2 EVALUATE Operation WHEN 1 CALL &quot;ANDBits&quot; USING DataItem1, DataItem2, Result WHEN 2 CALL &quot;ORBits&quot; USING DataItem1, DataItem2, Result WHEN 4 CALL &quot;XORBits&quot; USING DataItem1, DataItem2, Result END-EVALUATE ELSE *            Only 1 data item needed to perform a NOT. CALL &quot;NOTBits&quot; USING DataItem1, Result END-IF *         Display result of boolean operation, prompt user. DISPLAY &quot;Result             = &quot;          AT 0601 DISPLAY Result DISPLAY &quot;Hit any key to continue&quot; AT 0801 *         Pause until a key is pressed. MOVE 0 TO AnyKey PERFORM UNTIL AnyKey NOT = 0 CALL X&quot;83&quot; USING AnyKey END-PERFORM END-IF END-PERFORM. *   Clear the screen and end the program. CALL X&quot;E4&quot;. STOP RUN. $SET ANS85 * ANDBits performs an AND operation on 2 data items passed to it. IDENTIFICATION DIVISION. PROGRAM-ID. ANDBits. DATA DIVISION. WORKING-STORAGE SECTION. * Bit of DataItem1 or DataItem2 to test. 01 Bit         PIC 9(2) COMP-5. * Receives status of a bit in DataItem1 : 1 = on, 0 = off. 01 BitStatus1  PIC 9(2) COMP-5. * Receives status of a bit in DataItem2 : 1 = on, 0 = off. 01 BitStatus2  PIC 9(2) COMP-5. LINKAGE SECTION. * Data items to be ANDed. 01 DataItem1   PIC 9(2) COMP-5. 01 DataItem2   PIC 9(2) COMP-5. * The result of ANDing DataItem1 and DataItem2. 01 Result      PIC 9(2) COMP-5 VALUE 0. PROCEDURE DIVISION USING DataItem1, DataItem2, Result. *   Circulate from bit 0 to bit 7. PERFORM VARYING Bit FROM 0 BY 1 UNTIL Bit > 7 CALL &quot;TestBit&quot; USING DataItem1, Bit, BitStatus1 CALL &quot;TestBit&quot; USING DataItem2, Bit, BitStatus2 IF (BitStatus1 = 1) AND (BitStatus2 = 1) THEN COMPUTE Result = Result + 2**Bit END-IF END-PERFORM. EXIT PROGRAM. -- $SET ANS85 * ORBits performs an OR operation on 2 data items passed to it. IDENTIFICATION DIVISION. PROGRAM-ID. ORBits. DATA DIVISION. WORKING-STORAGE SECTION. * Bit of DataItem1 or DataItem2 to test. 01 Bit         PIC 9(2) COMP-5. * Receives status of a bit in DataItem1 : 1 = on, 0 = off. 01 BitStatus1  PIC 9(2) COMP-5. * Receives status of a bit in DataItem2 : 1 = on, 0 = off. 01 BitStatus2  PIC 9(2) COMP-5. LINKAGE SECTION. * Data items to be ORed. 01 DataItem1   PIC 9(2) COMP-5. 01 DataItem2   PIC 9(2) COMP-5. * The result of ORing DataItem1 and DataItem2. 01 Result      PIC 9(2) COMP-5 VALUE 0. PROCEDURE DIVISION USING DataItem1, DataItem2, Result. *   Circulate from bit 0 to bit 7. PERFORM VARYING Bit FROM 0 BY 1 UNTIL Bit > 7 CALL &quot;TestBit&quot; USING DataItem1, Bit, BitStatus1 CALL &quot;TestBit&quot; USING DataItem2, Bit, BitStatus2 IF (BitStatus1 = 1) OR (BitStatus2 = 1) THEN COMPUTE Result = Result + 2**Bit END-IF END-PERFORM. EXIT PROGRAM. -- $SET ANS85 * NOTBits performs a NOT operation on 1 data item passed to it. IDENTIFICATION DIVISION. PROGRAM-ID. NOTBits. DATA DIVISION. WORKING-STORAGE SECTION. * Bit of DataItem to test. 01 Bit         PIC 9(2) COMP-5. * Receives status of a bit in DataItem : 1 = on, 0 = off. 01 BitStatus  PIC 9(2) COMP-5. LINKAGE SECTION. * Data item to be NOTted. 01 DataItem   PIC 9(2) COMP-5. * The result of NOTting DataItem. 01 Result      PIC 9(2) COMP-5 VALUE 0. PROCEDURE DIVISION USING DataItem, Result. *   Circulate from bit 0 to bit 7. PERFORM VARYING Bit FROM 0 BY 1 UNTIL Bit > 7 CALL &quot;TestBit&quot; USING DataItem, Bit, BitStatus IF BitStatus = 0 THEN COMPUTE Result = Result + 2**Bit END-IF END-PERFORM. EXIT PROGRAM. --- $SET ANS85 * XORBits performs a XOR operation on 2 data items passed to it. IDENTIFICATION DIVISION. PROGRAM-ID. XORBits. DATA DIVISION. WORKING-STORAGE SECTION. * Bit of DataItem1 or DataItem2 to test. 01 Bit         PIC 9(2) COMP-5. * Receives status of a bit in DataItem1 : 1 = on, 0 = off. 01 BitStatus1  PIC 9(2) COMP-5. * Receives status of a bit in DataItem2 : 1 = on, 0 = off. 01 BitStatus2  PIC 9(2) COMP-5. LINKAGE SECTION. * Data items to be XORed. 01 DataItem1   PIC 9(2) COMP-5. 01 DataItem2   PIC 9(2) COMP-5. * The result of XORing DataItem1 and DataItem2. 01 Result      PIC 9(2) COMP-5 VALUE 0. PROCEDURE DIVISION USING DataItem1, DataItem2, Result. *   Circulate from bit 0 to bit 7. PERFORM VARYING Bit FROM 0 BY 1 UNTIL Bit > 7 CALL &quot;TestBit&quot; USING DataItem1, Bit, BitStatus1 CALL &quot;TestBit&quot; USING DataItem2, Bit, BitStatus2 IF ((BitStatus1 = 1) AND (BitStatus2 = 0)) OR            ((BitStatus1 = 0) AND (BitStatus2 = 1)) THEN COMPUTE Result = Result + 2**Bit END-IF END-PERFORM. EXIT PROGRAM. - $SET ANS85 * TestBit returns the status of a bit in a data item. IDENTIFICATION DIVISION. PROGRAM-ID. TestBit. DATA DIVISION. WORKING-STORAGE SECTION. * Work area used to shift bits of DataItem. 01 ShiftArea  PIC 9(2) COMP-5. LINKAGE SECTION. * Data item containing bit to be tested. 01 DataItem   PIC 9(2) COMP-5. * Bit of DataItem to test. 01 Bit        PIC 9(2) COMP-5. * Returns status of bit : 1 = on, 0 = off. 01 BitStatus  PIC 9(2) COMP-5. PROCEDURE DIVISION USING DataItem, Bit, BitStatus. *   Shift all bits of DataItem to the right of and including *   Bit left so that Bit is now at the leftmost bit position. *   This will clear out all bits to the left of Bit. This *   value is copied to ShiftArea for further manipulation. COMPUTE ShiftArea = DataItem * (2**(7 - Bit)). *   Shift leftmost bit right to bit 0. This will clear out *   all bits to the right of Bit. COMPUTE ShiftArea = ShiftArea / (2**7). *   If Bit was set, ShiftArea will now equal 1. IF ShiftArea = 1 THEN MOVE 1 TO BitStatus ELSE MOVE 0 TO BitStatus END-IF. EXIT PROGRAM. Copyright Microsoft Corporation 1993.