Binary fields will NEVER cause S0C7 abend
This is demonstrated using the below COBOL code.
WORKING-STORAGE SECTION.
01 JUNK PIC X(04).
01 WS-BINARY REDEFINES JUNK PIC 9(08) COMP.
PROCEDURE DIVISION.
MOVE 'ABCD' TO JUNK.
DISPLAY 'WS-BINARY: ' JUNK WS-BINARY
ADD 1 TO WS-BINARY
DISPLAY 'WS-BINARY: ' JUNK WS-BINARY
MOVE '#$%=' TO JUNK.
DISPLAY 'WS-BINARY: ' JUNK WS-BINARY
ADD 1 TO WS-BINARY
DISPLAY 'WS-BINARY: ' JUNK WS-BINARY
WS-BINARY: 50766789
WS-BINARY: 69589118
WS-BINARY: 69589119
'ABCD' is indirectly moved to WS-BINARY. The hexadecimal equivalent of 'ABCD' is X’C1C2C3C4’. If you put this HEX decimal value in calculator, you will get 3,250,766,788. Since picture clause of WS-BINARY is 9(8), the last 8 digit 50,766,788 is displayed in the first DISPLAY statement.
When you add 1 to this value(3,250,766,788), it become 3,250,766,789 and second DISPLAY statement displays last 8 digits which is 50,766,789.
Case 2: Value "#$%="
'#$%=' is indirectly moved to WS-BINARY. The hexadecimal equivalent of '#$%=' is X’7B5B6C7E’. If you put this HEX decimal value in calculator, you will get 2,069,589,118. Since picture clause of WS-BINARY is 9(8), the last 8 digit 69,589,118 is displayed in the third DISPLAY statement.
When you add 1 to this value(2,069,589,118), it become 2,069,589,119 and fourth DISPLAY statement displays last 8 digits which is 69,589,119.
Typical zoned decimal declarations in COBOL are shown below:
01 WS-NUMBER1 PIC 9(5). -> Unsigned zoned decimal
01 WS-NUMBER1 PIC 9(5)V99. -> Unsigned zoned decimal
01 WS-NUMBER2 PIC S9(5)V99. -> Signed zoned decimal
Internal representation of Zoned Decimal in Memory
In a zoned decimal field:
- Each decimal digit occupies one byte.
- Each byte has 2 nibbles, and each nibble has 4 bits.
- The high-order 4 bits (zone portion) of each byte will always have b’1111’ (hex F) except the last byte.
- The low-order 4 bits (decimal portion) contain the actual numeric digit (0–9).
- In the last byte, first 4 bits will store the sign and second 4 bits will store the last numeric digit.
|
Value |
Internal Hex Representation |
|
Unsigned 12345 |
X'F1F2F3F4F5' |
|
+12345 |
X'F1F2F3F4A5' X'F1F2F3F4C5' X'F1F2F3F4E5' |
|
-12345 |
X'F1F2F3F4B5' X'F1F2F3F4D5' |
Sign is stored in the zone portion (high-order 4 bits) of the last byte. Valid signs are given below
|
Sign |
Zone Nibble |
|
Unsigned |
F |
|
Positive |
A,C,E |
|
Negative |
B,D |
01 WS-9 PIC S9(05).
01 WS-X REDEFINES WS-9 PIC X(05).
PROCEDURE DIVISION.
PARA1.
MOVE X'F1F2F3F4F5' TO WS-X
PERFORM CHECK-SIGN
MOVE X'F1F2F3F4A5' TO WS-X
PERFORM CHECK-SIGN
MOVE X'F1F2F3F4C5' TO WS-X
PERFORM CHECK-SIGN
MOVE X'F1F2F3F4E5' TO WS-X
PERFORM CHECK-SIGN
MOVE X'F1F2F3F4B5' TO WS-X
PERFORM CHECK-SIGN
MOVE X'F1F2F3F4D5' TO WS-X
PERFORM CHECK-SIGN
GOBACK.
CHECK-SIGN.
IF WS-9 > 0
DISPLAY WS-9 ' POSITIVE'
ELSE
IF WS-9 = 0
DISPLAY WS-9 ' ZEROS'
ELSE
DISPLAY WS-9 ' NEGATIVE'
END-IF
END-IF.
ADD 1 TO WS-9
DISPLAY 'WS-X : ' WS-X.
|
Output of the program is given below |
Hex value for the number displayed |
|
12345 POSITIVE |
X'F1F2F3F4F5' |
|
WS-X : 1234F |
X'F1F2F3F4C6' |
|
1234v POSITIVE |
X'F1F2F3F4A5' |
|
WS-X : 1234F |
X'F1F2F3F4C6' |
|
1234E POSITIVE |
X'F1F2F3F4C5' |
|
WS-X : 1234F |
X'F1F2F3F4C6' |
|
1234V POSITIVE |
X'F1F2F3F4E5' |
|
WS-X : 1234F |
X'F1F2F3F4C6' |
|
1234§ NEGATIVE |
X'F1F2F3F4B5' |
|
WS-X : 1234M |
X'F1F2F3F4D4' |
|
1234N NEGATIVE |
X'F1F2F3F4D5' |
|
WS-X : 1234M |
X'F1F2F3F4D4' |
Internal representation of packed Decimal in Memory
- Each byte has two decimal digits except the last byte
- In the last byte, first 4 bits will store the numeric digit and second 4 bits will store the sign.
- If an odd number of digits exists, the unused high-order nibble is padded with zero.
|
Value |
Internal Hex Representation |
|
Unsigned 12345 |
X'12345F' |
|
+12345 |
X'12345A' X'12345C’ X'12345E’ |
|
-12345 |
X'12345B' X'12345D’ |
|
+123456 |
X’0123456C’ |
Similar to zoned decimal, system always uses “C” for positive signs and “D” for negative signs for packed decimals, but still accepts A,B,E signs
01 JUNK PIC X(04).
01 WS-ZONED-DECIMAL REDEFINES JUNK PIC 9(04).
PROCEDURE DIVISION.
MOVE 'ABCD' TO JUNK.
DISPLAY 'WS-ZONED-DECIMAL: ' WS-ZONED-DECIMAL
ADD 1 TO WS-ZONED-DECIMAL
DISPLAY 'WS-ZONED-DECIMAL: ' WS-ZONED-DECIMAL
MOVE X'1A1B1C1D' TO JUNK.
DISPLAY 'WS-ZONED-DECIMAL: ' WS-ZONED-DECIMAL
ADD 1 TO WS-ZONED-DECIMAL
DISPLAY 'WS-ZONED-DECIMAL: ' WS-ZONED-DECIMAL
GOBACK.
WS-ZONED-DECIMAL: 1235
WS-ZONED-DECIMAL: X'1A1B1C1D'
Code Explanation
Mainframe does not have any instruction to perform arithmetic operations on zoned decimals. So, it first converts zoned-decimals to packed-decimal and then performs arithmetic operations on the packed-decimal.
The first move indirectly populated ‘ABCD’(hex value X’C1C2C3C4’) to WS-ZONED-DECIMAL.
Before adding one to WS-ZONED-DECIMAL, Value X’C1C2C3C4’ need to be converted to packed-decimal.
How Zoned Decimal to Packed Decimal Conversion Works
During the conversion process:
- The digit portion of each zoned-decimal byte is treated as a numeric digit.
- The zone bits are ignored except in the rightmost byte.
- The zone bits of the last byte become the sign nibble.
- Digits are packed together from left to right.
- If the packed-decimal result contains an unfilled nibble, it is padded with zero on the left.
Example 1: ‘ABCD’ - X'C1C2C3C4'
Value X’C1C2C3C4’ becomes X‘01234C’ after zoned-decimal to packed-decimal conversion.
Therefore, the second DISPLAY statement shows 1235, because the temporary packed-decimal representation (X'01234C') was successfully incremented by one during the arithmetic operation.
Example 2: X'1A1B1C1D'
Value X'1A1B1C1D' becomes X‘0ABCD1’ after zoned-decimal to packed-decimal conversion.
Since X‘0ABCD1’ does not adhere to packed-decimal representation, when we tried to add one to it, system produced S0C7 abend