In a C program on z/OS you can code assembler macros. See Putting assembler code inside a C program
I wanted to use a WTO/WTOR macro to put a message onto the operator console. This took a few hours to get working, firstly I needed to understand using Re-entrant macros, and secondly see Using Re-entrant assembler macros in C ASM().
Background to using re-entrant macros in assembler
Programming in assembler
You can write a macro like
WTO 'Colins message'
This generates code
WTO 'Colin'
BRAS 1,LABEL1 Set register 1 to the following DC and jump to the label
LENDATA DC AL2(9)
DC B'0000000000000000'
DC C'Colin'
LABEL1 DS 0H
SVC 35
This works.
I can pass a string to the macro – a half word length followed by the data – like LENDATA above. This makes the WTO macro more complex.
You can pass a variable content message to WTO. The code following
- creates data in the correct format (length followed by the data).
- The WTO creates the data structure
- The WTO updates the data structure from the data passed to the macro
* define the variable data, and point register 2 to it
BRAS 2,OVERTEXT
DATA DC AL2(5) Length of string
DC C'Colin' the data to display
* invoke WTO. (2) says the address of the data is in register 2
OVERTEXT DS 0H
WTO TEXT=(2)
* This generates...
CNOP 0,4
BRAS 1,TWOLABA branch around definition
* The WTO data structure
DC AL2(8) TEXT LENGTH
DC B'0000000000010000' MCSFLAGS
TEXTADDR DC AL4(0) MESSAGE TEXT ADDRESS
..
* The instructions to update the data structure from the passed data
WTOLABA DS 0H
LR 14,1 FIRST BYTE OF PARM LIST
SR 15,15 CLEAR REGISTER 15
AH 15,0(1,0) ADD LENGTH OF TEXT + 4
AR 14,15 FIRST BYTE AFTER TEXT
ST 2,4(0,1) STORE TEXT ADDR INTO PLIST
SVC 35 ISSUE SVC 35
Where
- BRAS 2,OVERTEXT saves in register 2 the address of data, then branches to the label OVERTEXT
- BRAS 1,WTOLABA saves in register 1 the address of the structure following the instruction, then branches to label WTOLABA
- ST 2,4(0,1) this saves what register 2 points to – my data; and stores it at the front of the control block data in field TEXTADDR
This fails to execute because the whole program is Re-entrant (RENT) and so the whole program is read only. The program is trying to store register 2 into read only storage.
Solving the RENT problem.
The problem of trying to write into read only storage is solved splitting the above code into two parts and using thread read write storage.
- define the structure for the constants in read only storage
- copy the read only structure to thread read write storage
- use the thread read write storage for the request.
Define the structure for the constants in read only storage
You use an extra parameter on the macro call
WTOS WTO TEXT=(),MF=L
ETWOS DS 0H
This generates code
WTOS WTO TEXT=(),MF=L
WTOS DS 0F
DC AL2(8) TEXT LENGTH
DC B'0000000000010000' MCSFLAGS
DC AL4(0) MESSAGE TEXT ADDRESS
...
DC AL4(0) WSPARM ADDRESS
ETWOS DS 0H
This has created the data structure. The data is of length EWTOS-WTOS
Copy the read only structure to thread read write storage
In assembler you can use MVC or MVCL to copy from the read only data to thread read/write storage.
Use the thread read write storage for the request.
If the static part of the structure was copied to the block of storage userdata, the code below will issue the WTO request
WTOL WTO TEXT=((2)),MF=(E,userdata)
This generates the code to update the structure in read only storage
WTOR TEXT=((2)),MF=(E,userdata)
LA 1,userdata LOAD PARAMETER REG
LR 14,1 FIRST BYTE OF PARM LIST
SR 15,15 CLEAR REG 15
AH 15,0(1,0) ADD LENGTH OF TEXT + 4
AR 14,15 ADDR OF BYTE AFTER TEXT
ST 2,4(1,0) MOVE TEXT INTO PARM LIST
OI 4(14),B'00000000' SET EXTENDED MCS FLAGS
OI 5(14),B'10000000' SET EXTENDED MCS FLAGS2
SVC 35 ISSUE SVC 35
Note:
Some z/OS components use MF=(S,name) to generate the Static structure with the specified name, others use MF=(L).
They all use MF=(E,name).
Was just going over this in my z/OS class.
LikeLike