HLASM Macros: Defining, Invoking, and Parameterising Macros

TT

HLASM Macros: Defining, Invoking, and Parameterising Macros

HLASM macros are a powerful text-substitution and code-generation facility. A macro expands at assembly time into one or more HLASM statements. System macros like WTO and OPEN are provided by IBM; you can write your own for repeated code patterns.

Basic Macro Definition

hlasm
         MACRO
&LABEL   MYMAX &R1,&R2,&RESULT
* Compare R1 and R2, put larger value in RESULT register
         CR    &R1,&R2          Compare R1 and R2
         BNH   &LABEL.SKIP      Branch if R1 <= R2
         LR    &RESULT,&R1      R1 is larger
         B     &LABEL.DONE
&LABEL.SKIP LR &RESULT,&R2     R2 is larger
&LABEL.DONE DS  0H
         MEND

The macro starts with MACRO and ends with MEND. The second line is the prototype: &LABEL is the name field parameter, MYMAX is the operation name, and &R1, &R2, &RESULT are positional parameters.

Invoking a Macro

hlasm
FINDMAX  MYMAX 3,4,5           &LABEL=FINDMAX, &R1=3, &R2=4, &RESULT=5

This expands to:

hlasm
         CR    3,4
         BNH   FINDMAXSKIP
         LR    5,3
         B     FINDMAXDONE
FINDMAXSKIP LR 5,4
FINDMAXDONE DS  0H

Keyword Parameters

Keyword parameters have names and default values, making macros more readable:

hlasm
         MACRO
         ADDTOTAL &REG=3,&FIELD=TOTAL,&LEN=4
         A     &REG,&FIELD
         MEND
*
* Invoke with keyword parameters (order doesn't matter):
         ADDTOTAL REG=5,FIELD=GRANDTOT
         ADDTOTAL FIELD=SUBTOTAL,REG=4,LEN=4

Set Symbols: Variables at Assembly Time

HLASM provides three types of set symbols for conditional assembly:

hlasm
&COUNT   SETA  0               Arithmetic set symbol (integer)
&NAME    SETB  1               Boolean set symbol (0 or 1)
&TEXT    SETC  'HELLO'         Character set symbol (string)

Increment a counter:

hlasm
&COUNT   SETA  &COUNT+1

AIF, AGO, ANOP — Conditional Assembly

AIF (condition).label branches at assembly time if the condition is true:

hlasm
         MACRO
         GENMSG &TYPE=INFO
         AIF   ('&TYPE' EQ 'ERROR').DOERR
* Generate INFO message
         WTO   'INFORMATION MESSAGE'
         AGO   .DONE
.DOERR   ANOP
* Generate ERROR message
         WTO   'ERROR MESSAGE',ROUTCDE=11
.DONE    ANOP
         MEND
  • AIF (condition).label — conditional branch in macro expansion
  • AGO .label — unconditional branch in macro expansion
  • ANOP — no operation (used as a branch target)

LCLA, LCLB, LCLC — Local Variables

Local set symbols exist only within the current macro invocation:

hlasm
         MACRO
         GENTRY &COUNT
         LCLA  &I               Local counter
&I       SETA  0
.LOOP    ANOP
         AIF   (&I GE &COUNT).DONE
         DC    F'0'             Generate one fullword per count
&I       SETA  &I+1
         AGO   .LOOP
.DONE    ANOP
         MEND
*
         GENTRY 5               Generates 5 DC F'0' statements

GBLA, GBLB, GBLC — Global Variables

Global set symbols persist across macro invocations:

hlasm
         GBLA  &TOTALFIELDS
&TOTALFIELDS SETA 0            Initialize once in the main source

         MACRO
         ADDFIELD &LEN
         GBLA  &TOTALFIELDS
         DS    CL&LEN
&TOTALFIELDS SETA &TOTALFIELDS+1
         MEND

MNOTE — Assembly-Time Messages

hlasm
         AIF   ('&TYPE' NE 'A' AND '&TYPE' NE 'B').BADTYPE
         AGO   .OK
.BADTYPE MNOTE 8,'Invalid TYPE parameter: &TYPE'
.OK      ANOP

MNOTE severity,'message' prints a message during assembly. Severity 8 or higher marks the assembly as having errors.

System Macros

IBM provides hundreds of system macros in SYS1.MACLIB and SYS1.MODGEN:

hlasm
* Write to operator console
         WTO   'PROGRAM STARTED'

* Open a file
         OPEN  (INFILE,(INPUT))

* Get a record
         GET   INFILE,INREC

* Put a record
         PUT   OUTFILE,OUTREC

* Close files
         CLOSE (INFILE,,OUTFILE)

* Allocate storage
         GETMAIN R,LV=256       Allocate 256 bytes, address in reg 1

* Free storage
         FREEMAIN R,LV=256,A=(1)

Frequently Asked Questions

Q: How do I avoid duplicate label errors when a macro is invoked multiple times? Use the &LABEL name field parameter concatenated with a suffix: &LABEL.SKIP, &LABEL.DONE. Each invocation provides a unique label (e.g., STEP1, STEP2), so the generated labels are STEP1SKIP, STEP2SKIP, etc. If the macro has no name field parameter, use LCLA &SYSNDX&SYSNDX is a system variable that increments for each macro call, giving unique generated labels like L00001, L00002.

Q: What is the difference between a macro and an assembler instruction? A macro exists only at assembly time — it generates HLASM statements which are then assembled into machine instructions. A machine instruction corresponds directly to hardware operation codes. Macros provide abstraction and code generation; they have no runtime cost beyond the instructions they generate. Complex macros like OPEN and GET generate multiple machine instructions and data areas.

Q: Where does the assembler look for macro definitions? The assembler looks in the SYSLIB DD statement in the JCL. This typically points to SYS1.MACLIB (IBM system macros) and SYS1.MODGEN (DFSMS and other macros). Your own macros can be in a private macro library, which you add to the SYSLIB concatenation. Macros can also be defined inline in the source before their first use.


Part of HLASM Mastery Course — Module 14 of 22.