System abend

S0C9: Fixed-point divide exception

An S0C9 abend means a binary (fixed-point) divide failed, usually because the divisor was zero, or because the quotient was too large for the register. A CONVERT TO BINARY instruction given a decimal value too large for the register raises the same exception.

Other names for this code

Also written as 0C9, SOC9, abend 0C9, system abend 0C9, S0C9-9, fixed-point divide exception, fixed point divide.

What it means

Binary divide instructions such as D, DR, DL and DSG divide one signed or unsigned integer by another in general registers. Before they store the result, the processor checks that the divisor isn't zero and that the quotient fits in the register. If either check fails, it raises a fixed-point divide exception, program interruption code 9, and z/OS ends the task with system completion code 0C9 and reason code 9.

The CONVERT TO BINARY instructions (CVB, CVBY and CVBG) raise the same exception. They turn a packed decimal number into a binary integer, and if the number is too large for the 32-bit or 64-bit result, the processor treats it as a fixed-point divide exception.

Unlike fixed-point overflow (S0C8), this exception can't be switched off with the program mask. A zero binary divisor always ends the step unless a recovery routine or ON SIZE ERROR deals with it first.

In COBOL, a DIVIDE or COMPUTE on binary fields (COMP, COMP-4, COMP-5 or BINARY) can be compiled to binary divide instructions. A zero divisor there gives S0C9. The same mistake with packed decimal fields gives S0CB.

Common causes

  • A binary divisor is zero, for example an average taken over a count of zero records, or a rate divided by a quantity that was never set.
  • A divisor read from input or from a table is zero because the record or table entry is incomplete.
  • A COBOL DIVIDE or COMPUTE has no ON SIZE ERROR clause, so nothing catches the zero divisor.
  • In assembler, a CVB or CVBG is given a packed number too large for the register, such as a value above 2,147,483,647 converted with CVB.
  • In assembler, the dividend in the even-odd register pair isn't set up correctly, so the quotient doesn't fit even though the divisor isn't zero.

How to find the problem

  1. Find CEE3209S (Language Environment) or the IEA995I symptom dump in the job log. Note the program name and the offset.
  2. Match the offset to the compiler listing (LIST or OFFSET option). It points to a DIVIDE, a COMPUTE that divides, or a conversion to binary.
  3. Check the divisor in the dump or a debugger. A binary zero is all X'00' bytes. For a CVB, look at the packed field being converted.
  4. Trace where the divisor got its value. Look at the record being processed, the table entry, or the counter that should have been added to.

How to fix it

  • Test the divisor before dividing, for example IF WS-COUNT NOT = ZERO, and decide what the result should be when it is zero.
  • Add ON SIZE ERROR to DIVIDE and COMPUTE statements so the program handles a zero divisor instead of abending.
  • Use a 64-bit field and CVBG, or check the value first, when a packed number might not fit in 32 bits.
  • If the zero came from bad input or an incomplete table, fix the data and rerun from the failed step.

What it looks like

IEA995I SYMPTOM DUMP OUTPUT
  SYSTEM COMPLETION CODE=0C9  REASON CODE=00000009
IEF450I BILLRUN3 STEP020 - ABEND=S0C9 U0000 REASON=00000009

IBM documentation

IBM z/OS: 0Cx program interruptions. Use the documentation for your installed release.

Report a correction to WND Software.

Questions

What is the difference between S0C9 and S0CB?

S0C9 is a failed binary divide, and S0CB is a failed packed decimal divide. In COBOL, which one you get depends on whether the fields in the division are binary or packed.

Does ON SIZE ERROR catch division by zero?

Yes. COBOL treats division by zero as a size error, so the ON SIZE ERROR statements run and the step carries on.

Can S0C9 be masked off like S0C8?

No. Only fixed-point overflow, decimal overflow, exponent underflow and significance can be masked. A fixed-point divide exception always interrupts the program.