Update legacy mainframe assembler programs to make them LE compliant

Modernizing that old mainframe assembler program you depend on can be problematic. Here’s the best way to make them Language Environment compliant.

They’re out there, lurking deep inside your systems. They were originally written in the 1980s or ‘90s to perform some tricky programming that couldn't be done in COBOL. I’m talking about old, non-reentrant mainframe assembler programs.

For a long time it didn't matter how these old assemblers worked because they ran single-threaded in batch, IMS Transaction Manager (IMS/TM) message processing regions (MPRs) and traditional CICS applications. However, with the advent of the multithreading open Task Control Blocks (TCBs) in CICS, these programs' flaws can suddenly — and spectacularly — reveal themselves.

If the program can't be replaced, then someone has to make it re-entrant. The standard method for parallelizing a program – after a frantic search for the source code – consists of moving working storage elements into dynamically obtained memory, usually through operating system (OS) macros such as GETMAIN.

However, the OS macros may present significant performance hits in the most frequently used programs. CICS has additional challenges because the OS macros may get memory in a storage key incompatible with storage protection and areas will be outside of CICS storage management's control. The solution may be Language Environment (LE) compatible assembler.

Converting to a Language Environment compliant code
IBM developed LE with several goals in mind, but we'll focus on its relatively low-overhead memory management. In addition, in an online environment, LE performs memory management through CICS storage services.

Conversion to LE compliance requires the use of several specialized macros and storage areas.

Dynamic Storage Area (DSA):
The DSA contains the program's automatic variables as well as fields LE uses to keep track of the stack. It is as mapped by the CEEDSA macro. LE allocates stack storage from bottom to top in Last-In/First-Out (LIFO) fashion out of a larger stack segment.

To manage the stack, LE uses the next available byte (NAB) pointer. The NAB points to free storage out of which the next program's stack will be built. LE's entry code uses the length of the called program's DSA and the NAB pointer to see if there are enough bytes in the stack segment for the new stack entry. If there is, the entry code moves the NAB to the end of the new stack entry and continues. If not, it code branches into LE memory management routines to get a new stack segment.

In assembler programs, register 13 (R13) must always point to the DSA.

Program Prolog Area (PPA): The PPA, defined through the CEEPPA macro, contains fields and flags that identify an entry point and tell LE how to manage the module. There must be one PPA for each entry point to the program.

Common Anchor Area (CAA): The CAA, described by the CEECAA macro, is the mother block of the LE enclave. It maintains the enclave's state and the type of modules it has in it. In addition it has the entry points for some LE runtime routines.

In LE compliant programs, register 12 (R12) must always point to the CAA.

CEEENTRY: The CEENTRY macro generates the prolog code for every entry point into the program. The entry code sets up the proper linkage and allocates the module's DSA.  The CEEENTRY macro may need the most tweaking depending on programming requirements. The more amusing parameters and their operands are:

Parameter Values and meaning

NO should be specified if the program is used as a subroutine or the programmer is sure an LE enclave exists when the program is invoked.

YES means the program is the first module in the enclave or an enclave hasn't been built.

AUTO Use the AUTO parameter to specify the program's automatic storage requirements. It should include the bytes LE needs for memory management as mapped by CEEDSA.
NAB This parameter indicates the presence or absence of an NAB. Specify YES when you know an NAB exists in the DSA chain. NO makes LE generate code to look for one.
PARMREG Names the register to receive the parameter list address
BASE The program's base register after exiting the prolog.


CEETERM: The CEETERM macro generates the program exit code. The epilog frees the programs automatic storage and returns to the caller with the linkage conventions used in the prolog code.

CEEPPA: CEEPPA creates the PPA as described above. The programmer must create one PPA for each program entry point. The most important CEEPPA parameter is EPNAME which is the label of the entry point the PPA describes.

Putting it all together
A high-level blueprint for converting a program to LE compatible assembler follows these steps:

  • Define a DSA with the CEEDSA macro. Move working storage fields out of the program's addressing space after the macro. Any updated storage left in the program will violate reentrancy.
  • Use the CEEPPA macro to create a PPA. The EPNAME parameter should point to the name of the program entry point.
  •  Use the CEEENTRY macro to build the prolog code for each entry point. Remember to set the parameters as described above.
  • Use macro CEETERM at the program's exit point.
  • Remember that the macros will build references to LE modules required at link time to successfully build the final load module.

About the expert: Robert Crawford has been a systems programmer for 29 years. While specializing in CICS technical support he has also worked with VSAM, DB2, IMS and other mainframe products. He has programmed in Assembler, Rexx, C, C++, PL/1 and COBOL. The latest phase in his career finds him an operations architect responsible for establishing mainframe strategy and direction for a large insurance company. He lives with his family and works in south Texas.

Dig Deeper on IBM system z and mainframe systems