COBOL对位(bit)进行操作
记得有人说过COBOL不能对位进行操作,可能是某位师兄。其实想一下还是可以的,只不过麻烦了点。
一、先说一下思路:
1.操作的对象是BYTE A(使用工具程序BITTOOL能改变其中8位任意一位的值)。首先把A的每一位的值(0或1)
保存到一个8BYTE的B的每一个BYTE上。然后改变你想要改变的地方。最后根据B得到结果的一个BYTE的C。
2.两个重点是从一个BYTE的八个BYTE的转换和从八个BYTE到一个BYTE的转换。从一个BYTE的八个BYTE的转换:
如果A大于等于128(10000000),则第一位是‘1’,否则为‘0’;A减去128,如果A大于等于64(01000000),
则第二位是‘1’,否则为‘0’ ;如此类推。
代码:
BIT-TO-BYTES.
MOVE 0 TO WK-HWORD-BINARY
MOVE 1 TO WK-IX
MOVE 128 TO WK-FACTOR
MOVE BTS-PASS-BIT TO WK-HWORD-02
PERFORM 8 TIMES
IF WK-HWORD-BINARY = WK-FACTOR
OR WK-HWORD-BINARY > WK-FACTOR THEN
MOVE '1' TO BTS-PASS-BYTES(WK-IX:1)
COMPUTE WK-HWORD-BINARY = WK-HWORD-BINARY
- WK-FACTOR
ELSE
MOVE '0' TO BTS-PASS-BYTES(WK-IX:1)
END-IF
COMPUTE WK-FACTOR = WK-FACTOR / 2
COMPUTE WK-IX = WK-IX + 1
END-PERFORM
.
BIT-TO-BYTES-EXIT.
EXIT.
3.从八个BYTE到一个BYTE的转换:如果B的第一个BYTE是1,C加上128(10000000),否则什么都不做;
如果B的第二个BYTE是1,C加上64(01000000),否则什么都不做;如此类推。
代码:
BYTES-TO-BIT.
MOVE 0 TO WK-HWORD-BINARY
MOVE 1 TO WK-IX
MOVE 128 TO WK-FACTOR
PERFORM 8 TIMES
IF BTS-PASS-BYTES(WK-IX:1) = '1'
COMPUTE WK-HWORD-BINARY = WK-HWORD-BINARY
+ WK-FACTOR
ELSE
IF BTS-PASS-BYTES(WK-IX:1) NOT = '0'
DISPLAY '8-BYTE STRING MUST BE ZEROES OR ONES...'
ADD 8 TO WK-IX
ADD 8 TO BTS-PASS-RESULT
END-IF
END-IF
COMPUTE WK-FACTOR = WK-FACTOR / 2
COMPUTE WK-IX = WK-IX + 1
END-PERFORM
MOVE WK-HWORD-02 TO BTS-PASS-BIT
.
BYTES-TO-BIT-EXIT.
EXIT.
二、下面是完整的代码,已测试通过,包括CALL时用到的COPYBOOK(CPBIT),工具程序BITTOOL,测试程序BITTEST。
CPBIT:
*===============================================================*
* INTERFACE FOR BIT PROCESS *
* BY ICESCUT FOR TEST *
*===============================================================*
01 BTS-PASS-AREA.
05 BTS-PASS-REQUEST PIC X(1).
88 BTS-PASS-TOBYTES VALUE 'Y'.
88 BTS-PASS-TOBIT VALUE 'I'.
05 BTS-PASS-RESULT PIC S9(9) BINARY.
88 BTS-PASS-SUCCESS VALUE 0.
05 BTS-PASS-RECORD.
10 BTS-PASS-BIT PIC X.
10 BTS-PASS-BYTES PIC X(8).
BTS-PASS-REQUEST是一个FLAG,指示进行转换为BYTES还是BITS。
BITTOOL:
IDENTIFICATION DIVISION.
PROGRAM-ID. BITTOOL.
******************************************************************
* BIT CONVERSION TOOL *
* BY ICESCUT *
******************************************************************
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WK-AREA.
05 WK-HWORD.
10 WK-HWORD-01 PIC X.
10 WK-HWORD-02 PIC X.
05 WK-HWORD-BINARY REDEFINES WK-HWORD
PIC S9(4) BINARY.
05 WK-IX PIC 99 VALUE 1.
05 WK-FACTOR PIC S9(5) VALUE 128.
05 WK-TEXT PIC X(80).
LINKAGE SECTION.
*<< LINK AREA >>*
COPY CPBIT.
PROCEDURE DIVISION USING BTS-PASS-AREA.
*-----------------------------------------------------------------
* MAIN ROUTINE
*-----------------------------------------------------------------
MAIN-ROUTION.
EVALUATE TRUE
WHEN BTS-PASS-TOBIT
PERFORM BYTES-TO-BIT
THRU BYTES-TO-BIT-EXIT
WHEN BTS-PASS-TOBYTES
PERFORM BIT-TO-BYTES
THRU BIT-TO-BYTES-EXIT
WHEN OTHER
PERFORM INVALID-REQUEST
THRU INVALID-REQUEST-EXIT
END-EVALUATE
.
MAIN-ROUTION-EXIT.
GOBACK.
*-----------------------------------------------------------------
* CONVERT BIT TO BYTES
*-----------------------------------------------------------------
BIT-TO-BYTES.
MOVE 0 TO WK-HWORD-BINARY
MOVE 1 TO WK-IX
MOVE 128 TO WK-FACTOR
MOVE BTS-PASS-BIT TO WK-HWORD-02
PERFORM 8 TIMES
IF WK-HWORD-BINARY = WK-FACTOR
OR WK-HWORD-BINARY > WK-FACTOR THEN
MOVE '1' TO BTS-PASS-BYTES(WK-IX:1)
COMPUTE WK-HWORD-BINARY = WK-HWORD-BINARY
- WK-FACTOR
ELSE
MOVE '0' TO BTS-PASS-BYTES(WK-IX:1)
END-IF
COMPUTE WK-FACTOR = WK-FACTOR / 2
COMPUTE WK-IX = WK-IX + 1
END-PERFORM
.
BIT-TO-BYTES-EXIT.
EXIT.
*-----------------------------------------------------------------
* CONVERT BYTES TO BIT
*-----------------------------------------------------------------
BYTES-TO-BIT.
MOVE 0 TO WK-HWORD-BINARY
MOVE 1 TO WK-IX
MOVE 128 TO WK-FACTOR
PERFORM 8 TIMES
IF BTS-PASS-BYTES(WK-IX:1) = '1'
COMPUTE WK-HWORD-BINARY = WK-HWORD-BINARY
+ WK-FACTOR
ELSE
IF BTS-PASS-BYTES(WK-IX:1) NOT = '0'
DISPLAY '8-BYTE STRING MUST BE ZEROES OR ONES...'
ADD 8 TO WK-IX
ADD 8 TO BTS-PASS-RESULT
END-IF
END-IF
COMPUTE WK-FACTOR = WK-FACTOR / 2
COMPUTE WK-IX = WK-IX + 1
END-PERFORM
MOVE WK-HWORD-02 TO BTS-PASS-BIT
.
BYTES-TO-BIT-EXIT.
EXIT.
*-----------------------------------------------------------------
* HANDLE INVALID REQUEST
*-----------------------------------------------------------------
INVALID-REQUEST.
DISPLAY 'INVALID REQUEST ' BTS-PASS-REQUEST
MOVE 9 TO BTS-PASS-RESULT
.
INVALID-REQUEST-EXIT.
EXIT.
*-----------------------------------------------------------------
END PROGRAM BITTOOL.
BITTEST:
IDENTIFICATION DIVISION.
PROGRAM-ID. BITTEST.
******************************************************************
* BIT CONVERSION TEST
* BY ICESCUT
******************************************************************
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
*<< LINK AREA >>*
COPY CPBIT.
77 WK-PGM-BITTOOL PIC X(8) VALUE 'BITTOOL '.
01 WK-AREA.
05 WK-HEX.
* BINARY NUMBER '01010101'
10 WK-HEX-55 PIC X(1) VALUE X'55'.
* BINARY NUMBER '11010101'
10 WK-HEX-D5 PIC X(1) VALUE X'D5'.
* BINARY NUMBER '11110010'
10 WK-HEX-F2 PIC X(1) VALUE X'F2'.
05 WK-CHAR.
10 WK-CHAR-1 PIC X(1) VALUE '1'.
10 WK-CHAR-0 PIC X(1) VALUE '0'.
PROCEDURE DIVISION.
*-----------------------------------------------------------------
* MAIN ROUTINE
*-----------------------------------------------------------------
MAIN-ROUTINE.
PERFORM TEST-01
THRU TEST-01-EXIT
PERFORM TEST-02
THRU TEST-02-EXIT
.
MAIN-ROUTINE-EXIT.
STOP RUN.
*-----------------------------------------------------------------
* TEST1 BINARY NUMBER '01010101' TO '11010101'
*-----------------------------------------------------------------
TEST-01.
MOVE WK-HEX-55 TO BTS-PASS-BIT
SET BTS-PASS-TOBYTES TO TRUE
CALL WK-PGM-BITTOOL USING BTS-PASS-AREA
MOVE WK-CHAR-1 TO BTS-PASS-BYTES(1:1)
SET BTS-PASS-TOBIT TO TRUE
CALL WK-PGM-BITTOOL USING BTS-PASS-AREA
IF BTS-PASS-BIT = WK-HEX-D5 THEN
DISPLAY 'SUCCESS'
ELSE
DISPLAY 'FAILURE'
END-IF
.
TEST-01-EXIT.
EXIT.
*-----------------------------------------------------------------
* TEST2 BINARY NUMBER '11110010' TO '11100010'
*-----------------------------------------------------------------
TEST-02.
MOVE WK-HEX-F2 TO BTS-PASS-BIT
SET BTS-PASS-TOBYTES TO TRUE
CALL WK-PGM-BITTOOL USING BTS-PASS-AREA
MOVE WK-CHAR-0 TO BTS-PASS-BYTES(4:1)
SET BTS-PASS-TOBIT TO TRUE
CALL WK-PGM-BITTOOL USING BTS-PASS-AREA
* '11100010' -> X'E2' -> S
DISPLAY BTS-PASS-BIT
.
TEST-02-EXIT.
EXIT.
*-----------------------------------------------------------------
END PROGRAM BITTEST.
对BITTOOL使用的步骤(以TEST-02为例):
1.首先SET BTS-PASS-TOBYTES为TRUE,CALL BITTOOL把WK-HEX-F2转换成8个BYTE的BTS-PASS-BYTES。
2.然后对BTS-PASS-BYTES进行操作(第四位置0)。
3.接着SET BTS-PASS-TOBIT为TRUE,CALL BITTOOL把BTS-PASS-BYTES转换为一个BYTE的BTS-PASS-BIT,
也就是我们想要的结果。
三、其实后来想过,用COMP-5 REDEFINES之后,用加减操作来对位进行操作也是一种办法。