Developing AMODE(64) assembler language programs
CICS® Transaction Server supports non-Language Environment® (LE) assembler language programs that run in 64-bit addressing mode (AMODE(64)) and thereby access up to 16 exabytes (EB) of virtual storage. This support allows you to develop non-LE assembler language programs, which are able to process large amounts of data.
Because CICS also allows linkage between AMODE(64) and AMODE(31) or even AMODE(24) programs, it is possible to provide service routines that handle data in 64-bit storage without rewriting other parts of the application.
CICS AMODE(64) native assembler application programming
Writing a CICS AMODE(64) native assembler application program is very similar to writing a CICS AMODE(31) native assembler application program. The same CICS macros that are included in the AMODE(31) version of the application program are included in an AMODE(64) application program.
There are a number of differences between writing in AMODE(64) and writing in AMODE(31), as follows:
- The z/OS® SYSSTATE macro must specify AMODE64=YES. The CICS macros DFHEISTG, DFHEIEND, DFHEIENT, DFHEIRET and DFHECALL are SYSSTATE aware and generate AMODE(64) assembler when SYSSTATE AMODE64=YES has been specified. The SYSSTATE macro must be invoked before any of the SYSSTATE aware CICS macros are invoked.
- Macro DFHEIENT must use relative addressing. To specify that relative addressing is to be used, CODEREG=0 must be specified and STATREG and STATIC values must be supplied.
- The AMODE(64) version of the CICS stub must be included in the Binder (Link-edit) step in a similar way that the AMODE(31) CICS stub must be included in the Binder step for an AMODE(31) or AMODE(24) application. The AMODE(64) CICS stub is DFHEAG.
When writing AMODE(64) assembler, whether for CICS or batch, you must ensure that the registers used to reference storage have valid addresses. There are assembler instructions that ensure that a clean 31-bit address is loaded into a 64-bit register. These instructions are LLGT and LLGTR. LLGT loads a 31-bit address into a registers and clears the top 33 bits of the registers. LLGTR loads a register from another register and clears the top 33 bits. Instruction LLGF can be used to load a fullword into a 64-bit register; the fullword is loaded into the bottom 32 bits of the register and the top 32 bits of the registers are cleared.
EXEC CICS 64-bit commands
To allow AMODE(64) programs to use above-the-bar storage, CICS provides 64-bit variants of some of the CICS API commands to manipulate data in 64-bit storage (also referred to as above the bar). These commands are as follows:
- GETMAIN64
- To get storage above the bar (by default: other storage locations can be explicitly specified)
- FREEMAIN64
- To release storage that was acquired by a program running in AMODE(64), typically used to free storage above the bar
- PUT64 CONTAINER
- To put data from 64-bit storage into a named channel container
- GET64 CONTAINER
- To get data from a named channel container into 64-bit storage
EXEC CICS assembler language macros
- DFHEIENT
- For AMODE(64) programs, the DFHEIENT macro calls the AMODE(64) PROLOG program, which allocates working storage to hold any user variables and for CICS use. The PROLOG program sets up the CICS portion of this storage. When the PROLOG program returns, this code sets up the registers specified by the DFHEIENT parameters. For more information, see Coding the DFHEIENT macro for AMODE(64) assembler language programs.
- DFHEISTG
- For AMODE(64) programs, the DFHEISTG macro generates an AMODE(64) DSECT. At translation, the translator inserts the DFHEISTG macro immediately following your DFHEISTG DSECT instruction. In this way, the DSECT describes dynamic storage needed for the parameter list, for the command-level interface, and for any user variables. For more information, see Extending dynamic storage for assembler language programs.
- DFHEIRET
- For AMODE(64) programs, the DFHEIRET macro calls the AMODE(64) EPILOG program to release the working storage of the application program. For more information, see Coding the DFHEIRET macro for assembler language programs.
- DFHECALL
- For an assembler language application program, when the CICS translator detects a CICS command, each command is replaced by an invocation of the DFHECALL macro. The DFHECALL macro sets up the command parameters and calls the initial CICS command processor to handle the command. For more information, see DFHECALL macro.
Procedure
The following procedure summarizes the information that relates specifically to developing AMODE(64) assembler language programs.
- Use the z/OS Assembler SYSSTATE macro to declare that an
application is AMODE(64).
- Include a SYSLIB statement for the SYS1.MACLIB macro library (which contains the SYSSTATE macro) in your compile JCL.
- Ensure one of the following:
- The SYSSTATE macro with parameter AMODE64=YES is placed immediately after the CICS translator options statement. For example:
*ASM XOPTS(NOPROLOG NOEPILOG) SYSSTATE AMODE64=YES
- If the program does not specify CICS translator options, the SYSSTATE macro with parameter AMODE64=YES is the first statement.
The SYSSTATE statement must be on one line, because CICS does not support continuation for this statement. For more information about the SYSSTATE macro, see SYSSTATE - Identify system state in z/OS MVS Programming: Assembler Services Reference IAR-XCT.
- The SYSSTATE macro with parameter AMODE64=YES is placed immediately after the CICS translator options statement. For example:
Note: If the SYSSTATE macro is not specified, or is specified without parameter AMODE64=YES, when any of the CICS-supplied macros, DFHEIENT, DFHEISTG, DFHEIRET, and DFHECALL, first generates code, these macros generate AMODE(24) or AMODE(31) code. - Specify the DFHEIENT macro with the appropriate parameters for relative addressing. See Coding the DFHEIENT macro for AMODE(64) assembler language programs.
For information about the DFHEISTG storage, see Extending dynamic storage for assembler language programs.
- If you are not using EXEC CICS RETURN, specify the DFHEIRET macro, or use the translator-inserted version. See Coding the DFHEIRET macro for assembler language programs.
- Translate, assemble and link-edit the program. See Translating, assembling, and link-editing assembler language application programs.
For information about the DFHECALL macro, see DFHECALL macro.
For information about link-editing the stub programs, see Using the EXEC interface modules for AMODE(64) applications.
CICS AMODE(64) assembler example
Here is an example of a CICS AMODE(64) native assembler application program. The source code has been augmented with annotations. There are many styles in which assembler code can be written, and no one is better than any other, it is just a matter of the writer’s preference. This example illustrates a possible style for writing AMODE(64) assembler in CICS.
The example shows how to obtain shared storage located above the bar and save the address of the shared storage address in the CWA. The example does not show how data is loaded into the shared storage, as there are many ways in which this could be done. For example, you might want to read data from a VSAM file or from a Db2® database.
The data stored in the shared storage above the bar in this example cannot be accessed by AMODE(31) or AMODE(24) applications, but an AMODE(64) assembler program called by the AMODE(31) or AMODE(24) application would be able to access this data and then return all, or portions of, the data to its caller.
There are several ways in which the data could be returned to the AMODE(31) or AMODE(24) caller, including:
- CICS COMMAREA
- CICS container, within a channel
- A buffer supplied by the caller
The *ASM XOPTS statement is used to pass options to the translator. In this case NOPROLOG and NOEPILOG are specified to stop the translator inserting PROLOG and EPILOG instructions.
*ASM XOPTS(NOPROLOG NOEPILOG) Translator options
The SYSSTATE macro tells SYSSTATE aware macros that the AMODE is 64 and also specifies the architecture level of the machine that the program will execute on. The CICS native assembler macros are SYSSTATE aware so will generate AMODE 64 code when AMODE64=YES is set.
SYSSTATE AMODE64=YES,ARCHLVL=4 Sysstate AMODE 64, Z10
***********************************************************************
* Register equates.
***********************************************************************
r0 equ 0
r1 equ 1
r2 equ 2
r3 equ 3
r4 equ 4
r5 equ 5
r6 equ 6
r7 equ 7
r8 equ 8
r9 equ 9
r10 equ 10
r11 equ 11
r12 equ 12
r13 equ 13
r14 equ 14
r15 equ 15
***********************************************************************
* Module’s working storage.
***********************************************************************
Macros DFHEISTG and DFHEIEND are SYSSTATE aware. These macros define DSECT DFHEISTG. As the SYSSTATE macro specified AMODE64=YES the CICS portion of this DSECT is defined for an AMODE 64 application.
The CICS portion of the DSECT defines a format-four save area, the 64-bit address of the COMMAREA and EIB, and other fields used by CICS when the application program issues a CICS command.
The application’s working storage variables are defined after the DFHEISTG macro and before the DFHEIEND macro. In this case these variables are wk_shared_storage_addr, wk_cwa_address and wk_flength.
The DFHEIEND indicates the end of the DSECT.
dfheistg ,
ds 0ad
wk_shared_storage_addr ds ad Shared storage address
wk_cwa_addr ds ad CWA address
wk_flength ds f Getmain64 flength
dfheiend
The next two DSECTs (cwa_mapping and shared_data) map the CWA and the shared data storage area.
***********************************************************************
* CWA dsect.
***********************************************************************
cwa_mapping dsect
cwa_shared_storage_addr ds ad Shared storage address
***********************************************************************
* Shared data dsect.
***********************************************************************
shared_data dsect
shared_thing ds xl1000 Shared data object
shared_data_length equ *-shared_data Length of shared data
The following statements name the CSECT and its AMODE and RMODE.
AMODE64X csect
AMODE64X amode 64
AMODE64X rmode 31
Macro DFHEIENT generates the program’s entry code. This code:
- Saves the caller’s registers in the format-four save area pointed to be R13.
- Makes a call to DFHEAG0 is obtain the program’s working storage. This storage must be obtained below the bar to allow all CICS command processors to function correctly.
- Sets up the working storage, static and EIB registers. The working storage register is R13, the static register is R12 and the EIB register is R11.
DFHEIENT CODEREG=0, Relative addressing -
DATAREG=R13, Data register -
EIBREG=R11, EIB register -
STATREG=R12, Static register -
STATIC=STATIC_AREA Static label
***********************************************************************
* Obtain above the bar shared storage.
***********************************************************************
The CICS command below obtains above the bar shared storage. The address of the shared storage obtained is returned in R2 if the command is successful.
EXEC CICS GETMAIN64 -
FLENGTH(LENGTH_OF_SHARED_STORAGE) -
SET(R2) -
SHARED -
NOHANDLE
The code below checks the EIB response and if it is not normal jumps to label abend1.
clc eibresp,dfhresp(normal)
jne abend1
If the response to the command is normal the address of the shared storage is saved in the program’s working storage.
stg r2,wk_shared_storage_addr Save shared storage address
Insert code here to load data into the shared storage. Data could be read from many sources including VSAM files or databases.
***********************************************************************
* Obtain address of CWA.
***********************************************************************
The CICS command below returns the address of the CWA in R3 if the command is successful.
EXEC CICS ADDRESS CWA(R3) NOHANDLE
The code below checks the EIB response and if it is not normal jumps to label abend2.
clc eibresp,dfhresp(normal)
jne abend2
If the response to the command is normal, the address of the CWA is saved in the program’s working storage.
stg r3,wk_cwa_addr Save CWA address
***********************************************************************
* Save shared storage address in CWA.
***********************************************************************
The code below uses the CWA mapping to save the address of the shared data area in the CWA.
using cwa_mapping,r3
stg r2,cwa_shared_storage_addr Save shared storage addr
drop r3 Drop r3
***********************************************************************
* Return to CICS.
***********************************************************************
return ds 0h
The command below returns control to CICS. In fact the DFHEIRET macro could have been used instead the of the CICS return command.
EXEC CICS RETURN
***********************************************************************
* Issue abend.
***********************************************************************
The CICS command below issues abend ERR1 if the CICS GETMAIN command is not successful.
Abend1 ds 0h
EXEC CICS ABEND ABCODE('ERR1')
The CICS command below issues abend ERR2 if the CICS ADDRESS command is not successful.
Abend2 ds 0h
EXEC CICS ABEND ABCODE('ERR2')
***********************************************************************
* Static
***********************************************************************
The program’s static area
static_area ds 0fd
length_of_shared_storage dc al4(shared_data_length)
***********************************************************************
* Ltorg
***********************************************************************
ltorg
end
Using AMODE(64) native assembler programs
An AMODE(64) program such as the example shown above could be used to store large amounts of data, and return portions of this to other programs within an application. In this scenario, the AMODE(64) program could act as a service routine which is called by programs in other addressing modes to manipulate large storage areas on their behalf.
One particularly valuable way of using an AMODE(64) program could be to put data from a 64-bit storage area directly into a container within a channel (either a named channel or the default current channel). This data in this container can then be accessible to an AMODE(31), or even AMODE(24), program by using the container API. The EXEC CICS GET CONTAINER command will return the 64-bit data into a 31-bit (or 24-bit) storage area provided by the invoking program. This can be a useful way of sharing data between 64-bit ‘service’ routines and other programs in the application, without the need to convert all of the application to AMODE(64) native assembler.
To invoke an AMODE(64) program from a program in another addressing mode, use EXEC CICS LINK or XCTL.