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

TT
Emily Ross
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:

text
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 → Execution

Each 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

  1. Reads your HLASM source statements sequentially.
  2. Expands macro calls by fetching macro definitions from the SYSLIB concatenation.
  3. Assigns addresses to labels (relative to the start of each CSECT).
  4. Encodes each instruction into its binary machine code representation.
  5. Produces a relocatable object deck — machine code with unresolved external references noted.
  6. Writes an assembly listing (SYSPRINT) showing source, generated code, and diagnostics.

A Minimal Assembly JCL Step

jcl
//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=SHR

Key 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:

OptionMeaning
OBJECTProduce an object deck in SYSLIN
NODECKDo not produce a card-image object deck
LISTInclude generated object code in the SYSPRINT listing
XREF(FULL)Cross-reference all symbols in the listing
RENTCheck for reentrance violations
AMODE(31)Set default addressing mode
RMODE(ANY)Allow residence above or below the 16 MB line
DBCSEnable 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

  1. Reads object decks from SYSLIN.
  2. Resolves external references — if program A calls program B, the BINDER locates B's object deck and links them together.
  3. Assigns final virtual addresses to each CSECT (Control Section).
  4. Applies relocation — updates address constants that were left relative in the object deck.
  5. Writes the load module to the output PDS/PDSE specified by SYSLMOD.
  6. Optionally includes members from existing load libraries (SYSLIB for the BINDER).

A Minimal BINDER JCL Step

jcl
//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:

text
  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 attributes

Stage 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:

  1. Locates the load module in the specified STEPLIB, JOBLIB, or LINKLIST library concatenation.
  2. Brings the module into virtual storage.
  3. Applies any remaining relocation fixups.
  4. Sets the PSW instruction address to the module's entry point.
  5. 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.

text
MY.HLASM.SOURCE(MYPROG)    -- source for program MYPROG
MY.HLASM.SOURCE(SUBROUT1)  -- source for subroutine SUBROUT1

Macro 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:

jcl
//STEPLIB  DD  DSN=MY.LOAD.LIBRARY,DISP=SHR

Multi-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.

hlasm
* Module A — calls a routine in Module B
         EXTRN SORTRTN          Declare external reference
         .
         CALL  SORTRTN          The BINDER will resolve this
hlasm
* 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:

jcl
//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.