Linking, Libraries, and the HLASM Build Process on z/OS

Linking, Libraries, and the HLASM Build Process on z/OS
Writing HLASM source is only the beginning. Before your program can run on z/OS, it must pass through a multi-stage build pipeline: assembly with ASMA90, linking with the BINDER, and loading into virtual storage by the z/OS program loader. Understanding this pipeline — and how libraries, macro definitions, and object modules fit together — is essential for any serious HLASM developer.
The Three-Stage Build Pipeline
The journey from HLASM source to an executing program involves three distinct tools:
HLASM Source (.asm / JCL in-stream)
│
▼
ASMA90 Assembler
│ produces
▼
Object Deck (SYSLIN / SYSGO)
│
▼
BINDER / Linkage Editor
│ produces
▼
Load Module in a PDS/PDSE
│
▼
z/OS Program Loader → ExecutionEach stage has a specific role and produces a specific output. Problems in any stage produce diagnostics that point back to your source.
Stage 1: The ASMA90 Assembler
ASMA90 is the IBM High Level Assembler program. You invoke it via JCL using the program name ASMA90 (or the alias IFOX00 on older systems).
What ASMA90 Does
- Reads your HLASM source statements sequentially.
- Expands macro calls by fetching macro definitions from the SYSLIB concatenation.
- Assigns addresses to labels (relative to the start of each CSECT).
- Encodes each instruction into its binary machine code representation.
- Produces a relocatable object deck — machine code with unresolved external references noted.
- Writes an assembly listing (SYSPRINT) showing source, generated code, and diagnostics.
A Minimal Assembly JCL Step
//ASMSTEP EXEC PGM=ASMA90,PARM='OBJECT,NODECK,LIST'
//SYSPRINT DD SYSOUT=*
//SYSLIN DD DSN=&&OBJSET,DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(2,1))
//SYSIN DD DSN=MY.HLASM.SOURCE(MYPROG),DISP=SHR
//SYSLIB DD DSN=SYS1.MACLIB,DISP=SHR
// DD DSN=SYS1.MODGEN,DISP=SHR
// DD DSN=MY.SHOP.MACLIB,DISP=SHRKey DD names:
- SYSIN — your HLASM source code.
- SYSPRINT — the assembly listing output. Always review this for error messages.
- SYSLIN / SYSGO — where the object deck is written (to a temporary dataset for passing to the BINDER step).
- SYSLIB — the macro library concatenation. ASMA90 searches these in order when it encounters a macro call.
- SYSUT1 — a work file that ASMA90 needs for internal processing.
ASMA90 Options (PARM)
The PARM string controls assembler behaviour. Common options:
| Option | Meaning |
|---|---|
OBJECT | Produce an object deck in SYSLIN |
NODECK | Do not produce a card-image object deck |
LIST | Include generated object code in the SYSPRINT listing |
XREF(FULL) | Cross-reference all symbols in the listing |
RENT | Check for reentrance violations |
AMODE(31) | Set default addressing mode |
RMODE(ANY) | Allow residence above or below the 16 MB line |
DBCS | Enable double-byte character set support |
Stage 2: The BINDER (Linkage Editor)
The BINDER (program IEWBLINK, formerly IEWL for the older linkage editor) takes one or more object decks and produces a load module — an executable that can be loaded and run by z/OS.
What the BINDER Does
- Reads object decks from SYSLIN.
- Resolves external references — if program A calls program B, the BINDER locates B's object deck and links them together.
- Assigns final virtual addresses to each CSECT (Control Section).
- Applies relocation — updates address constants that were left relative in the object deck.
- Writes the load module to the output PDS/PDSE specified by SYSLMOD.
- Optionally includes members from existing load libraries (SYSLIB for the BINDER).
A Minimal BINDER JCL Step
//LNKSTEP EXEC PGM=IEWBLINK,PARM='MAP,LIST,XREF'
//SYSPRINT DD SYSOUT=*
//SYSLIN DD DSN=&&OBJSET,DISP=(OLD,DELETE)
// DD *
INCLUDE SYSLIB(MYROUTINE)
/*
//SYSLIB DD DSN=MY.LOAD.LIBRARY,DISP=SHR
//SYSLMOD DD DSN=MY.LOAD.LIBRARY(MYPROG),DISP=SHR
//SYSUT1 DD UNIT=SYSDA,SPACE=(CYL,(2,1))Key points:
- SYSLIN receives the object deck from the assembly step (passed via a temporary dataset).
- SYSLMOD is the output PDS/PDSE member where the linked load module is stored.
- SYSLIB for the BINDER contains existing load modules that can be INCLUDEd.
INCLUDE SYSLIB(MYROUTINE)is a BINDER control statement that pulls in an existing load module member.
BINDER Control Statements
BINDER control statements are inline JCL records that give the linker instructions:
NAME MYPROG(R) -- name the output module MYPROG, replace if exists
INCLUDE SYSLIB(SUBROUT1) -- include SUBROUT1 from the SYSLIB library
ENTRY MYPROG -- set MYPROG as the entry point
ALIAS MYPROG2 -- create an alias entry for the module
MODE AMODE(31),RMODE(ANY) -- set addressing mode attributesStage 3: The z/OS Program Loader
When a program is executed (via EXEC PGM=MYPROG in JCL, or an ATTACH/LINK macro call), the z/OS program loader:
- Locates the load module in the specified STEPLIB, JOBLIB, or LINKLIST library concatenation.
- Brings the module into virtual storage.
- Applies any remaining relocation fixups.
- Sets the PSW instruction address to the module's entry point.
- Passes control to the program.
The program now runs. There is no further runtime system involved for a pure HLASM program — only the hardware and whatever z/OS services the program invokes via SVC or CALL.
Library Types on z/OS
z/OS uses Partitioned Data Sets (PDSs and PDSEs) as libraries — containers for named members.
Source Libraries
HLASM source is typically stored in a partitioned data set with RECFM=FB, LRECL=80 (fixed-block, 80-byte records — the original punched-card format). Each source file is a member of the PDS.
MY.HLASM.SOURCE(MYPROG) -- source for program MYPROG
MY.HLASM.SOURCE(SUBROUT1) -- source for subroutine SUBROUT1Macro Libraries (MACLIB)
Macro definitions are stored in libraries pointed to by the SYSLIB DD in your assembly JCL. IBM supplies two essential macro libraries:
- SYS1.MACLIB — standard z/OS macros (OPEN, GET, PUT, CLOSE, WTO, GETMAIN, FREEMAIN, etc.)
- SYS1.MODGEN — z/OS data area DSECTs (CVT, TCB, ASCB, etc.) generated by system generation
Your shop may have additional macro libraries. Always include the IBM libraries before your local ones in the SYSLIB concatenation so that overrides work as intended.
Load Libraries
Linked load modules are stored in load libraries (RECFM=U, variable block). The standard system load library is SYS1.LPALIB (Link Pack Area Library). Your programs go in a private load library referenced by STEPLIB or JOBLIB:
//STEPLIB DD DSN=MY.LOAD.LIBRARY,DISP=SHRMulti-Module Programs: Separate Assembly and Linking
For larger programs, splitting code across multiple source files keeps each module manageable and allows independent assembly. Modules communicate via external references — symbols declared with EXTRN in the referencing module and CSECT (or ENTRY) in the defining module.
* Module A — calls a routine in Module B
EXTRN SORTRTN Declare external reference
.
CALL SORTRTN The BINDER will resolve this* Module B — the routine being called
SORTRTN CSECT This CSECT name satisfies the EXTRN
STM R14,R12,12(R13) Standard entry linkage
.When both object decks are fed to the BINDER in the same SYSLIN concatenation, it resolves SORTRTN automatically and produces a single load module containing both routines.
Batch Assembly-Link JCL: The Complete Picture
Most shops have a catalogued procedure (PROC) that combines assembly and link steps. Here is what a typical inline job looks like:
//MYJOB JOB (ACCT),'MY NAME',CLASS=A,MSGCLASS=X
//ASMLINK EXEC PROC=ASMACLG
//ASM.SYSIN DD *
MYPROG CSECT
STM R14,R12,12(R13)
BALR R12,0
USING *,R12
*
WTO 'HELLO FROM HLASM'
*
L R13,4(,R13)
RETURN (14,12),RC=0
END MYPROG
/*The ASMACLG catalogued procedure performs assemble (CLG = Compile, Link, Go) — assembling, linking, and executing the program in a single job. Each shop customises their PROC, but the three stages are always present.
Common Build Errors and How to Read Them
Assembly-Time Errors (ASMA90 Messages)
ASMA90 messages appear in SYSPRINT with an ASMA prefix:
- ASMA001E — Undefined symbol. A label you referenced was never defined. Check for spelling mistakes or missing EXTRN declarations.
- ASMA044E — Operand error. Wrong number of operands for an instruction or macro.
- ASMA141E — Macro not found. Check your SYSLIB concatenation — the macro library containing the definition is missing.
- ASMA435W — No USING active for register. You are referencing a label without a valid USING statement to establish a base register.
Link-Time Errors (BINDER Messages)
BINDER messages appear in its SYSPRINT:
- IEW2456E — Unresolved external reference. The object deck referenced a symbol that no included module defines. Either add the missing module to SYSLIN or INCLUDE it from SYSLIB.
- IEW2646W — Multiple definitions. Two included modules both define the same CSECT name.
Conclusion
The HLASM build pipeline — ASMA90, BINDER, and the program loader — is well-designed and consistent. Each stage has clear inputs, outputs, and error messages. Once you understand how object decks, load modules, and library concatenations fit together, building even complex multi-module programs becomes straightforward.
The key habits to develop are: always read your SYSPRINT output, keep your macro libraries correctly ordered in SYSLIB, and use meaningful CSECT names that will make BINDER MAP output readable.
Next, explore how HLASM interacts with z/OS system services directly through SVC instructions and MVS macros in HLASM and z/OS: SVCs, MVS Macros, and System Services.
