Coding in System/390 assembler language (Message queue interface)

Note the information in the following sections when coding IBM MQ for z/OS® programs in assembler language.


Names

The names of parameters in the descriptions of calls, and the names of fields in the descriptions of structures are shown in mixed case. In the assembler-language macros supplied with IBM MQ, all names are in uppercase.


Use the MQI calls

The MQI is a call interface, so assembler-language programs must observe the OS linkage convention.

In particular, before they issue an MQI call, assembler-language programs must point register R13 at a save area of at least 18 full words. This save area provides storage for the called program. It stores the registers of the caller before their contents are destroyed, and restores the contents of the caller's registers on return.

Note: This is important for CICS® assembler-language programs that use the DFHEIENT macro to set up their dynamic storage, but that choose to override the default DATAREG from R13 to other registers. When the CICS Resource Manager Interface receives control from the stub, it saves the current contents of the registers at the address to which R13 is pointing. Failing to reserve a save area for this purpose gives unpredictable results, and will probably cause an abend in CICS.


Declaring constants

Most constants are declared as equates in macro CMQA.

However, the following constants cannot be defined as equates, and these are not included when you call the macro using default options:

  • MQACT_NONE
  • MQCI_NONE
  • MQFMT_NONE
  • MQFMT_ADMIN
  • MQFMT_COMMAND_1
  • MQFMT_COMMAND_2
  • MQFMT_DEAD_LETTER_HEADER
  • MQFMT_EVENT
  • MQFMT_IMS
  • MQFMT_IMS_VAR_STRING
  • MQFMT_PCF
  • MQFMT_STRING
  • MQFMT_TRIGGER
  • MQFMT_XMIT_Q_HEADER
  • MQMI_NONE
To include them, add the keyword EQUONLY=NO when you call the macro.

CMQA is protected against multiple declaration, so we can include it many times. However, the keyword EQUONLY takes effect only the first time that the macro is included.


Specifying the name of a structure

To allow more than one instance of a structure to be declared, the macro that generates the structure prefixes the name of each field with a user-specifiable string and an underscore character (_).

Specify the string when you invoke the macro. If we do not specify a string, the macro uses the name of the structure to construct the prefix:

* Declare two object descriptors
CMQODA         Prefix used="MQOD_" (the default)
MY_MQOD CMQODA         Prefix used="MY_MQOD_"

The structure declarations in Call descriptions show the default prefix.


Specifying the form of a structure

The macros can generate structure declarations in one of two forms, controlled by the DSECT parameter:

    DSECT=YES
    An assembler-language DSECT instruction is used to start a new data section; the structure definition immediately follows the DSECT statement. No storage is allocated, so no initialization is possible. The label on the macro invocation is used as the name of the data section; if no label is specified, the name of the structure is used.

    DSECT=NO
    Assembler-language DC instructions are used to define the structure at the current position in the routine. The fields are initialized with values, which we can specify by coding the relevant parameters on the macro invocation. Fields for which no values are specified on the macro invocation are initialized with default values.

    DSECT=NO is assumed if the DSECT parameter is not specified.


Controlling the listing

We can control the appearance of the structure declaration in the assembler-language listing with the LIST parameter:

    LIST=YES
    The structure declaration appears in the assembler-language listing.

    LIST=NO
    The structure declaration does not appear in the assembler-language listing. This is assumed if the LIST parameter is not specified.


Specifying initial values for fields

We can specify the value to be used to initialize a field in a structure by coding the name of that field (without the prefix) as a parameter on the macro invocation, accompanied by the value required.

For example, to declare a message descriptor structure with the MsgType field initialized with MQMT_REQUEST, and the ReplyToQ field initialized with the string MY_REPLY_TO_QUEUE, use the following code:

MY_MQMD    CMQMDA      MSGTYPE=MQMT_REQUEST,       X
REPLYTOQ=MY_REPLY_TO_QUEUE

If you specify a named constant (or equate) as a value on the macro invocation, use the CMQA macro to define the named constant. You must not enclose in single quotation marks (' ') values that are character strings.


Writing reenterable programs

IBM MQ uses its structures for both input and output. If you want your program to remain reenterable:
  1. Define working storage versions of the structures as DSECTs, or define the structures inline within an already-defined DSECT. Then copy the DSECT to storage that is obtained using:

    • For batch and TSO programs, the STORAGE or GETMAIN z/OS assembler macros
    • For CICS, the working storage DSECT (DFHEISTG) or the EXEC CICS GETMAIN command
    To correctly initialize these working storage structures, copy a constant version of the corresponding structure to the working storage version. Note: The MQMD and MQXQH structures are each more than 256 bytes long. To copy these structures to storage, use the MVCL assembler instruction.
  2. Reserve space in storage by using the LIST form ( MF=L) of the CALL macro. When we use the CALL macro to make an MQI call, use the EXECUTE form ( MF=E) of the macro, using the storage reserved earlier, as shown in the example under Use CEDF. For more examples of how to do this, see the assembler language sample programs as shipped with IBM MQ.

Use the assembler language RENT option to help you to determine if your program is reenterable.

For information on writing reenterable programs, see MVS™/ESA Application Development Guide: Assembler Language Programs, GC28-1644.


Use CEDF

If you want to use the CICS-supplied transaction, CEDF ( CICS Execution Diagnostic Facility) to help you to debug your program, add the ,VL keyword to each CALL statement, for example:

CALL MQCONN,(NAME,HCONN,COMPCODE,REASON),MF=(E,PARMAREA),VL

The previous example is reenterable assembler-language code where PARMAREA is an area in the working storage that you specified.