Introduction to Unix Callable Services
I start a small series of articles regarding Unix System Services (USS) and how to access Unix properties from an assembler program, either started from JCL or in the Unix shell. I start by showing how to access services and later the File System (zFS).
If you have no idea what I am talking about, please read the article linked to below. Even if you know something about USS you might benefit from reading it:
Crossing the border
Programming between native z/OS and zOS UNIX Systems Services
|
I have borrowed some of the examples in the article.
Calling the services
In the Unix society the programming language C is what assembler is for z/OS. So it can be no surprise that z/OS offers all services in Unix C to assembler. These services are the same modules that is used by C. There are (at least) three ways to find these Callable Services:
- by static linking each module into your load module and CALL it
- by loading the module into storage and CALL it
- by finding the address of the preloaded module in a control block and CALL it
I will definitely recommend the latter and that is what my examples will do.
L R15,16 R15 -> Common Vector Table
L R15,CVTCSRT-CVT(15) R15 -> CSRTABLE
L R15,24(R15) R15 -> CSR slot
L R15,276(R15) R15 = Address of service svc
BALR 14,15
|
There is a table of addresses of each module. At offset 276 is the address of “getpid” (get process id).
Parameters
You pass parameters in a list of addresses to the module exactly as you would to any other module.
PARM DS F
PROCESSID DS F
...
...
LA R15,PROCESSID
ST R15,PARM
OI PARM,X'80'
LA 1,PARM
|
This example passes only one parameter, PROCESSID but we will later handle several parameters
MACRO to USS Callable Service
I am a macro guy so I have of course made a macro to facilitate the call of a Unix Callable Service. It is supposed to be extended with offsets to more Unix Callable Services.
MACRO
.***************************************************
.**
.** Macro USSSERV - Call USS Callable Services **
.**
.***************************************************
&LABEL USSSERV &SERVICE,&PARMS
GBLC &PARM_LABEL
.***************************************************
.** Storage definitions **
.***************************************************
AIF ('&SERVICE' EQ 'PARM').PARM
AIF ('&SERVICE' EQ 'DSECT').DSECT
.***************************************************
.** Callable Services **
.***************************************************
AIF ('&SERVICE' EQ 'GETPID').GETPID
AIF ('&SERVICE' EQ 'OPEN').OPEN
AIF ('&SERVICE' EQ 'CLOSE').CLOSE
AIF ('&SERVICE' EQ 'READ').READ
MNOTE 8,'Wrong SERVICE'
AGO .END
.***************************************************
.** Define parm list **
.***************************************************
.PARM ANOP
&LABEL DS &PARMS.F
&PARM_LABEL SETC '&LABEL'
&PARM_LABEL._LENGTH EQU *-&LABEL
AGO .END
.***************************************************
.** Define DSECT for the BPX-services **
.***************************************************
.DSECT ANOP
PUSH PRINT
PRINT NOGEN
CVT DSECT=YES
BPXYMODE LIST=NO
BPXYOPNF LIST=NO
POP PRINT
AGO .END
.***************************************************
.** Get Process id **
.***************************************************
.GETPID ANOP
&OFFSET SETC '276'
AGO .MAKECODE
.***************************************************
.** Open file **
.***************************************************
.OPEN ANOP
&OFFSET SETC '156' BPX1OPN
AGO .MAKECODE
.***************************************************
.** Read a file **
.***************************************************
.READ ANOP
&OFFSET SETC '176' BPX1RED
AGO .MAKECODE
.***************************************************
.** Close a file **
.***************************************************
.CLOSE ANOP
&OFFSET SETC '72' BPX1CLO
AGO .MAKECODE
.***************************************************
.** Make the code to set the parm and the address **
.** of the Service **
.***************************************************
.MAKECODE ANOP
&N SETA N'&PARMS
&I SETA 0
.LOOP_PARMS ANOP
LA R15,&PARMS(&I+1)
ST R15,&PARM_LABEL+(4*&I)
&I SETA &I+1
AIF (&I LT &N).LOOP_PARMS
OI &PARM_LABEL+(4*(&N-1)),X'80'
.**************************************
.** Find the Callable Service **
.**************************************
L 15,16 R15 -> Common Vector Table
L 15,CVTCSRT-CVT(15) R15 -> CSRTABLE
L 15,24(R15) R15 -> CSR slot
L 15,&OFFSET.(15) R15 = Address of service svc
LA 1,&PARM_LABEL
BALR 14,15 .***************************************************
.** End-Of-Macro **
.***************************************************
.END ANOP
MEND
|
The macro has a “Service” called “CVTDSECT”. That must be placed outside any DSECT or CSECT. It is used to calculate an offset.
I will change this macro as I need more services and parameters.
Exampel program
PROGRAM EQU
*************************
WS PROGRAM STORAGE
WSEC DS CL16
PARM DS f
PROCESSID DS F
PID_PACKED DS PL8
PID_CHAR DS CL16
WTO DS 0f
WTOLGD DS H
WTOTEXT DS CL70
PROGRAM STORAGE
USSSERV CSVDSECT
*************************
PGM12 PROGRAM START
MVC WSEC,=CL(L'WSEC)'PGM12-WS'
USSSERV GETPID,PROCESSID
l R1,processid
CVD R1,PID_PACKED
MVC PID_CHAR,EDIT_FIELD
ED PID_CHAR,PID_PACKED
MVC WTOTEXT(10),=C'Processid:'
MVC WTOTEXT+10(l'PID_CHAR),PID_CHAR
MVC WTOLGD,=Y(l'WTOTEXT)
WTO TEXT=WTO,ROUTCDE=11
B RETURN
EDIT_FIELD DC C' ',(L'PID_CHAR-1)X'20'
NO_STORAGE_OBTAINED DS 0H
WTO 'PGM12 - Return med fejl',ROUTCDE=11
L R13,SAVEAREA+4
LM R14,R12,12(R13)
RETURN RC=8
*************************
* End of program
*************************
RETURN PROGRAM END
LTORG
END
|
Manual
z/OS V1R13.0 UNIX System Services Programming:Assembler Callable Services Reference - SA22-7803-14
List of offsets on page 1011 (Table 24. System control offsets to callable services)
Hi Jens. Have you considered linking the linkage stub into your program as described:
SvarSletWhen you link-edit a program, you can link to the linkage stub. The program can issue a call.
The linkage stubs are contained in SYS1.CSSLIB. You can specify SYS1.CSSLIB in the //SYSLIB statement of the JCL that is used to invoke the linkage editor. This causes the addresses of all required linkage-assist routines to be automatically resolved, and saves you the trouble of having to specify individual linkage-assist routines in INCLUDE statements.
I assume you are referring to page 2 in the manual "Service_name".
SvarSletWell, I have actually. I really do not like to link the services into the program, as the load module will be bigger, any PTF will not affect the load module unless relinked and if dynamically loaded into storage with a LOAD is just some extra code.
Getting the modules from system storage (same manual, Appendix A. System control offsets to callable services) is preferrable because you always know you are running the latest PTF-level, it does not increase the module size, and you also know that everybody runs the same version of the callable service.