HLASM with COBOL: Calling Assembler Routines from COBOL
HLASM with COBOL: Calling Assembler Routines from COBOL
Mixing HLASM and COBOL is extremely common in mainframe production systems. COBOL handles business logic; HLASM handles performance-critical routines, hardware-specific functions, and legacy code. This module explains how to write HLASM routines that COBOL programs can call.
Why Mix COBOL and HLASM?
- Performance: sorting algorithms, string manipulation, and mathematical routines run significantly faster in HLASM
- Hardware access: certain z/Architecture instructions (vector, crypto) are only accessible from assembler
- Legacy integration: existing HLASM routines are called by newer COBOL programs
- System services: some z/OS services are more naturally accessed from assembler
COBOL CALL Statement
COBOL calls an assembler routine with:
WORKING-STORAGE SECTION.
01 WS-INPUT-AMOUNT PIC 9(9)V99 COMP-3.
01 WS-OUTPUT-TEXT PIC X(15).
01 WS-RETURN-CODE PIC S9(8) COMP.
PROCEDURE DIVISION.
CALL 'FMTAMT' USING WS-INPUT-AMOUNT
WS-OUTPUT-TEXT
GIVING WS-RETURN-CODE.COBOL passes parameters by reference (addresses). Register 1 contains the parameter list address when the assembler routine is entered.
Writing the HLASM Routine
* FMTAMT: Format a packed decimal amount as printable text
* Parameters:
* Parm 1: 6-byte packed decimal amount (PIC 9(9)V99 COMP-3)
* Parm 2: 15-byte output text field
* Return code: 0=success, 8=invalid amount
*
FMTAMT CSECT
FMTAMT AMODE 31
FMTAMT RMODE ANY
*
R0 EQU 0
R1 EQU 1
R2 EQU 2
R3 EQU 3
R12 EQU 12
R13 EQU 13
R14 EQU 14
R15 EQU 15
*
STM R14,R12,12(R13)
LR R12,R15
USING FMTAMT,R12
LA R11,SAVEAREA
ST R13,4(R11)
ST R11,8(R13)
LR R13,R11
*
* Load parameter addresses from parameter list
L R2,0(R1) R2 -> packed decimal input (6 bytes)
L R3,4(R1) R3 -> output text field (15 bytes)
*
* Validate: check it's a valid packed decimal
TM 5(R2),X'0F' Check sign nibble of last byte
BZ BADSIGN Zero sign = invalid
*
* Unpack to zoned decimal for formatting
UNPK WORKZONE,0(6,R2) Unpack 6-byte packed to 11-byte zoned
OI WORKZONE+10,X'F0' Fix sign byte
*
* Format: insert decimal point and spaces
MVC 0(15,R3),=CL15' ' Clear output
MVC 0(9,R3),WORKZONE+2 Copy 9 integer digits (skip leading)
MVI 9(R3),C'.' Decimal point
MVC 10(2,R3),WORKZONE+9 Copy 2 decimal digits
*
SR R15,R15 Return code 0 = success
B RETURN
*
BADSIGN LA R15,8 Return code 8 = error
*
RETURN DS 0H
L R13,4(R13)
L R14,12(R13)
LM R0,R12,20(R13)
BR R14
*
WORKZONE DS ZL11
SAVEAREA DS 18F
END FMTAMTAMODE and RMODE Directives
MYROUTINE AMODE 31 Addressing mode: 31-bit (above the line)
MYROUTINE RMODE ANY Residency mode: can load above or below the lineFor routines called from modern COBOL (COBOL for z/OS), always use AMODE 31 and RMODE ANY. COBOL programs compiled with ARITH(EXTEND) or large data items require AMODE 31.
Accessing COBOL Data from HLASM
COBOL passes parameters by reference — register 1 contains a list of addresses. Load each address individually:
* Three-parameter call
L R2,0(R1) Address of parameter 1
L R3,4(R1) Address of parameter 2
L R4,8(R1) Address of parameter 3For COBOL COMP-3 (packed decimal) fields, the HLASM routine accesses them directly with CP, AP, etc.:
CP 0(6,R2),=P'0' Is amount zero?
BE ZEROAMTFor COBOL PIC X (character) fields:
MVC WORKBUF(80),0(R3) Copy 80 bytes of COBOL field to work areaFor COBOL COMP / COMP-4 (binary) fields:
L R5,0(R4) Load 4-byte binary (PIC S9(9) COMP)Returning Values to COBOL
COBOL's GIVING clause maps to register 15 after the call:
CALL 'MYROUTINE' GIVING WS-RETURN.Set register 15 to your return code before BR 14. COBOL stores register 15 in the GIVING field.
For returning data, modify the parameter's storage directly (you have its address in R2, R3, etc.):
MVC 0(15,R3),RESULT Copy result to output parameterFrequently Asked Questions
Q: Does my HLASM routine need to be compiled separately from the COBOL program? Yes. The HLASM routine is assembled separately with JCL invoking ASMA90, producing an object module. The object module is then link-edited with the COBOL object module (or stored in a load library that the COBOL program's JCL references). The CALL 'FMTAMT' in COBOL becomes an external reference resolved by the linkage editor.
Q: What happens if my HLASM routine changes a register that COBOL is using? COBOL expects the standard linkage convention: on return, registers 2–12 must be restored to their entry values. If your routine modifies a register without restoring it, the COBOL program receives corrupted register values and will likely abend (typically a 0C4 protection exception or 0C1 operation exception). Always use STM at entry and LM at exit to save and restore all registers.
Q: Can COBOL call a reentrant HLASM routine from multiple tasks simultaneously?
Yes, provided the HLASM routine is truly reentrant (no modification of static storage). Mark the routine with AMODE 31, RMODE ANY, and the RENT attribute in the linkage editor. Use GETMAIN for all writable work areas rather than static DS fields. IBM's Language Environment (LE) fully supports concurrent calls to reentrant assembler routines from multitasking COBOL programs.
Part of HLASM Mastery Course — Module 18 of 22.
