Monday, July 20, 2026

Why Binary Fields Never Cause an S0C7 Abend, but Zoned Decimal and Packed Decimal Can

In Mainframe, usually numeric calculations are performed using Binary, Zoned-decimal and packed decimals

One interesting fact is that binary fields never cause an S0C7 data exception, whereas zoned decimal and packed decimal fields can. Let's explore why.
 
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            
 
The above code does NOT produce S0C7. Output of the above code snippet as follows
 
WS-BINARY: 50766788  
WS-BINARY: 50766789  
WS-BINARY: 69589118
WS-BINARY: 69589119  
 
Case 1: Value "ABCD"
 
'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.
 
 
Understanding Zoned Decimal and Packed Decimal
 
Before discussing how an S0C7 Data Exception occurs with decimal data, it is important to understand how zoned decimal and packed decimal values are stored internally.
 
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

 
Positive signs A, E and negative signs “B” are called non-preferred signs.
 
System always uses “C” for positive signs and “D” for negative signs, but still accepts A,B,E signs
 
When fields with signs A/B/E are involved in the calculations, ultimately sign will be converted to either “C” for positive and “D” for negative
 
Demonstrating Zoned Decimal Sign Handling
 
Let us see how different sign behaves for a zoned decimal field using the below code snippet.
 
WORKING-STORAGE SECTION.          
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'


Typical packed decimal declarations in COBOL are shown below:
 
01 WS-NUMBER1 PIC 9(5) COMP-3.     -> Unsigned packed decimal

01 WS-NUMBER1 PIC 9(5)V99 COMP-3.  -> Unsigned packed decimal
01 WS-NUMBER2 PIC S9(5)V99 COMP-3. -> Signed packed decimal

Internal representation of packed Decimal in Memory
 
In a packed decimal field:
  • 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
 
Moving Invalid Data into a Zoned Decimal Field
 
Let us know test moving junk values to a zoned decimal.
 
WORKING-STORAGE SECTION.                           
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.                                         
 
Output of the above code snippet as follows:

 
WS-ZONED-DECIMAL: ABCD 
WS-ZONED-DECIMAL: 1235 
WS-ZONED-DECIMAL: X'1A1B1C1D' 
CEE3207S The system detected a data exception (System Completion Code=0C7).
 
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. 
No validation occurs during the conversion itself.
 
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


When Does a Packed-Decimal (COMP-3) Field Cause an S0C7 Abend?

As discussed earlier, a packed-decimal field must conform to the valid packed-decimal format. If the field contains invalid digits or an invalid sign nibble and an arithmetic operation is attempted on it, the processor detects the invalid data and raises an S0C7 (Data Exception) abend.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.