CALL 'CALCTAX' USING WS-GROSS-PAY WS-TAX
ON EXCEPTION
DISPLAY 'CALCTAX IS NOT AVAILABLE'
END-CALL
A COBOL called subprogram receives control when the caller executes CALL. In this example, the calling program passes gross pay and tax fields by reference. The subprogram describes those arguments in its LINKAGE SECTION, names them in PROCEDURE DIVISION USING, calculates the tax, and returns control with GOBACK.
Complete calling-program example
The caller owns the actual storage for WS-GROSS-PAY and WS-TAX. Because BY REFERENCE is the default, CALCTAX can update the caller's tax field directly.
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYROLL1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-GROSS-PAY PIC S9(7)V99 COMP-3
VALUE +0025000.00.
01 WS-TAX PIC S9(7)V99 COMP-3
VALUE ZERO.
PROCEDURE DIVISION.
CALL 'CALCTAX' USING WS-GROSS-PAY WS-TAX
ON EXCEPTION
DISPLAY 'CALCTAX IS NOT AVAILABLE'
MOVE ZERO TO WS-TAX
END-CALL
DISPLAY 'GROSS PAY: ' WS-GROSS-PAY
DISPLAY 'TAX: ' WS-TAX
GOBACK.
The literal 'CALCTAX' names the target program. Whether a literal call is static or dynamic depends on compiler and link-edit choices such as DYNAM, NODYNAM, and DLL handling. This article keeps the focus on the source contract between the caller and callee; the COBOL static-call guide owns the binding and performance intent.
Complete called-subprogram example
IDENTIFICATION DIVISION.
PROGRAM-ID. CALCTAX.
DATA DIVISION.
LINKAGE SECTION.
01 LK-GROSS-PAY PIC S9(7)V99 COMP-3.
01 LK-TAX PIC S9(7)V99 COMP-3.
PROCEDURE DIVISION USING LK-GROSS-PAY LK-TAX.
COMPUTE LK-TAX ROUNDED = LK-GROSS-PAY * 0.20
GOBACK.
The LINKAGE SECTION describes the fields supplied by another program. It does not allocate storage for these arguments. At entry, PROCEDURE DIVISION USING maps the first caller argument to LK-GROSS-PAY and the second to LK-TAX. The names do not need to match across programs, but their positions and data descriptions must be compatible.
PIC S9(7)V99 COMP-3.How CALL USING maps arguments
| Position | Caller argument | Subprogram parameter | Required check |
|---|---|---|---|
| 1 | WS-GROSS-PAY | LK-GROSS-PAY | Same business value and compatible size, sign, scale, and USAGE. |
| 2 | WS-TAX | LK-TAX | Writable output passed BY REFERENCE with a compatible packed-decimal definition. |
COBOL associates the lists by position, not by data-name. Reversing the two arguments can produce a wrong calculation even though the statement compiles. A different length or USAGE can make the called program read the wrong bytes, overwrite adjacent storage, or raise a runtime condition.
Do not add a LINKAGE item to the PROCEDURE DIVISION USING list unless the caller supplies the matching position. Likewise, do not add a caller argument without updating the callee contract. When programs are maintained in separate source libraries, document the shared interface in a copybook or interface specification and rebuild every affected component.
BY REFERENCE, BY CONTENT, and BY VALUE
BY REFERENCE is assumed when no mode is coded. The called program works with the caller's storage, which is why CALCTAX can place the result in WS-TAX.
CALL 'CALCTAX'
USING BY REFERENCE WS-GROSS-PAY WS-TAX
END-CALL
BY CONTENT gives the subprogram a copy for that parameter. Changes to the corresponding callee data item do not change the caller's argument. Passing WS-TAX BY CONTENT would therefore lose the intended output when control returns.
BY VALUE passes a value rather than a reference to the sending field. It is common when the target follows a non-COBOL linkage convention, and COBOL-to-COBOL use requires compatible BY VALUE handling in the subprogram header. For the full comparison and syntax, use the COBOL CALL parameter modes guide.
Literal and identifier calls
01 WS-PROGRAM-NAME PIC X(8) VALUE 'CALCTAX'.
CALL WS-PROGRAM-NAME USING WS-GROSS-PAY WS-TAX
ON EXCEPTION
DISPLAY 'PROGRAM NOT FOUND: ' WS-PROGRAM-NAME
END-CALL
A CALL identifier chooses the program name at run time and is dynamic in Enterprise COBOL for z/OS. It is useful when configuration or record content selects one of several subprograms. Validate the identifier value before the call and ensure the resulting program object is available through the site's runtime search path.
Return control with GOBACK
In a called program, GOBACK returns control to the statement following the active CALL. EXIT PROGRAM also returns from a called program, while STOP RUN ends the run unit rather than performing an ordinary subprogram return.
A called program usually retains its WORKING-STORAGE state after GOBACK or EXIT PROGRAM. If a counter must start at zero on every invocation, initialize it explicitly, use LOCAL-STORAGE where suitable, or apply an approved INITIAL/CANCEL design. See Working Storage versus Local Storage and COBOL program termination and reentry for those separate lifecycle decisions.
Handle an unavailable dynamic subprogram
ON EXCEPTION handles a failure to make a dynamically called program available on its initial load. Typical checks include the program-name value, binder NAME or ALIAS, load-library concatenation, deployment member, and access to the library.
Common called-subprogram failures
| Symptom | Likely cause | Practical check |
|---|---|---|
| Output remains zero | Output passed BY CONTENT or callee never moved/computed it | Confirm BY REFERENCE and trace the matching callee parameter. |
| Numeric data exception or corrupted field | Caller and callee definitions disagree | Compare order, byte length, PICTURE, USAGE, sign, and scale. |
| ON EXCEPTION executes | Dynamic target cannot be made available | Check identifier value, binder name, load library, deployment, and access. |
| ON EXCEPTION does not catch an abend | Target loaded, then failed during execution | Read the Language Environment and system diagnostics for the actual failure. |
| Second call starts with old values | Subprogram WORKING-STORAGE retained its last-used state | Initialize state or review LOCAL-STORAGE, INITIAL, and CANCEL behavior. |
| Caller never resumes | Subprogram executes STOP RUN or branches incorrectly | Use GOBACK or EXIT PROGRAM for an ordinary return and trace the final path. |
Caller and subprogram checklist
- Define one clear interface and keep the CALL and PROCEDURE DIVISION USING lists in the same order.
- Match PICTURE, USAGE, sign, scale, and expected length for every position.
- Use BY REFERENCE for outputs that the callee must return through an argument.
- Use END-CALL to make the scope clear when ON EXCEPTION is present.
- Return from the subprogram with GOBACK or EXIT PROGRAM, not STOP RUN.
- Confirm how compiler and binder options resolve literal calls.
- Place dynamically called program objects in the approved runtime library.
- Test first-call and repeated-call behavior so retained state is visible.
The COBOL application-structure guide explains how main programs, subprograms, and the run unit fit together.
Official IBM references
- IBM: CALL statement
- IBM: LINKAGE SECTION
- IBM: Passing data between programs
- IBM: Dynamic calls with subprograms
- IBM: GOBACK statement
COBOL called subprogram FAQ
Does a COBOL called subprogram allocate storage for LINKAGE items?
No. LINKAGE SECTION entries describe data made available by the caller; they do not reserve storage for those arguments. The PROCEDURE DIVISION USING list establishes addressability when the subprogram is entered.
Must CALL USING arguments match PROCEDURE DIVISION USING parameters?
Yes. They correspond by position, so keep the count, order, size, PICTURE, USAGE, and sign compatible. A mismatch can corrupt data or cause a runtime failure even when both programs compile.
Is CALL BY REFERENCE the default in Enterprise COBOL?
Yes. When no passing mode is stated, BY REFERENCE is assumed. The called program works with the caller's storage, so changes to an output parameter are visible after control returns.
What does ON EXCEPTION handle on a dynamic CALL?
It handles failure to make the called program available on its initial load, such as when the program object cannot be located. It does not catch an abend or application error that occurs after the called program begins running.
When a CALL fails in production, compare the two parameter lists before changing program logic; one wrong position or data definition can explain the entire failure.