I have a basic question about assembler. Can you provide me a detailed explanation about differences between the ways to call a sub program (XCTL,LINK,LOAD,BALR and CALL). I just wanted know which is dynamic and which is static. Please explain how they will manage storage and how they will return control to calling program. what are scenarios we will use each of the these instruction?
How do we call a subroutine from a main program in Assembler. Let's say the task is to call pgm b from pgm A . I assume the command that achieves this is BALR R1,R2 in pgm A . What I don't understand is what should be the content of R1 & R2. Also, where do I give the pgm name of the one to be called (in my case B). How does the control pass from A to B. Shouldn't I be using a CALL command anywhere ? I am lost between CALL and BALR. Kindly help.
First, in accordance with the terms of IBM, it's allways BALR R14,R15 or
BASM R14,R15. Where content of R15 is the entrypoint of the loaded subprogramm. R1 is allways used for the adress of the parameters that are passed to the subprogramm. R14 will automatically filled with the needed adress to return back to the calling programm.
Example, Pgm-A (MDL00900) calls other Pgm-B (MDL00910):
In MDL00900:
LOAD EP=MDL00910 ...load EntryPointLocation MDL00910
ST R0,MDL00910_ENTPOINT ...store that Adress
L R01,MDL00910_CALLPARM ...Adress of PARM-LIST
L R15,MDL00910_ENTPOINT ...EPL MDL00910
BASSM R14,R15 ...pass control to other PGM
...next instruction , check Return-Code-Field
SPACE
MDL00910_CALLPARM DC 01F'0' ...PARM-ADR PGM MDL00910
MDL00910_ENTPOINT DC 01A(0) ...ADRESSE PGM MDL00910
MDL00900_PARAMETER DSECT
SPACE
MDL00900§PANF DS 0F
SPACE
MDL00900_PGMFUC DC CL04' ' ...PGM-FUNKTION PIC X(04)
MDL00900_PGMMOD DC CL04' ' ...PGM-CALLMODE PIC X(04)
MDL00900_PGMCMD DC CL04' ' ...PGM-PGCOMAND PIC X(04)
MDL00900_PGMRTC DC CL04' ' ...PGM-RETUCODE PIC X(04)
SPACE
MDL00900§PEND DS 0F
In MDL00910:
MDL00910 CSECT
ENTRY MDL00910
MDL00910_BEGIN DS 0H
STM R14,R12,12(R13) ...STORE REGS IN CALLERS SAVE
LR R9,R15 ...LOAD R9 ADRESS CALLERS R15
USING MDL00910_BEGIN,R9 ...AND USE IT AS BASE-REGISTER
SPACE
LA R15,MDL00910_SAVEAREA ...LOAD OWN PGM-SAVEAREA
ST R15,8(R13) ...STORE IN CALLERS SAVE-AREA
ST R13,4(R15) ...STORE IN OWN SAV-EAREA
LR R13,R15 ...POINT R13 TO OWN SAVE-AREA
SPACE
B MDL00910_START
MDL00910_START DS 0H
SR R2,R2 ...DELETE REGISTER-2
L R2,0(R1) ...LOAD PARM-ADRESS
USING MDL00900_PARAMETER,R2 ...APPROPRIATE DSECT PARM-AREA
.....
.....
MDL00910_STOPP DS 0H
SPACE
B MDL00910_ENDE
MDL00910_ENDE DS 0H PROGRAMM-ENDE
L R13,MDL00910_SAVEAREA+4 ...LOAD CALLERS SAVE-AREA
LM R14,R12,12(R13) ...RELOAD ALL THE REGISTERS
SR R15,R15 ...CLEAR REGISTER-15
BR R14 ...GET OUT OF HERE
SPACE
MDL00900_PARAMETER DSECT
SPACE
MDL00900§PANF DS 0F
SPACE
MDL00900_PGMFUC DC CL04' ' ...PGM-FUNKTION PIC X(04)
MDL00900_PGMMOD DC CL04' ' ...PGM-CALLMODE PIC X(04)
MDL00900_PGMCMD DC CL04' ' ...PGM-PGCOMAND PIC X(04)
MDL00900_PGMRTC DC CL04' ' ...PGM-RETUCODE PIC X(04)
SPACE
MDL00910§PEND DS 0F
SPACE
Thanks very much, UmeySan for this detailed explanation. But isn't BASSM used for connecting assembler programs with different address modes ? My program uses BALR, (Code below) but it keeps hitting the compilation error 'No active USING for operand =A(PARMS)'. PARMS in our code is a DSECT containing the declaration of the variables which are passed to the called pgm.
STM R14,R12,12(R13) SAVE REGISTERS
BALR R12,0
USING *,R12
ST R13,SAVEAREA+4
LA R13,SAVEAREA POINT TO MY SAVEAREA
LA R1,=A(PARMS)
USING PARMS,R13
L R15,ASUB
BALR R14,R15
Joined: 08 May 2006 Posts: 1205 Location: Dublin, Ireland
The reason you are getting " NO ACTIVE USING" message is that your USING statement must precede the statement. Coding it after, as you have, means that the Assembler can't resolve the address.
However,
Quote:
LA R1,=A(PARMS)
This looks incorrect. You are trying to load the address of an address. This should read either of:
Code:
LA R1,PARMS
or
Code:
L R1,=A(PARMS)
The effect of your code is to pass your SAVEAREA as a parameter to the called program. Is this what you want?? It looks unusual to me.
Sorry, i forgot one important fact about calling other programms:
Please do the Load EntryPoint only once in your routine. You could check the fullword before Load to achieve this. So you don't have multiple copies in the storage.
For example:
IF (MDL00900§EPLA,Z,MDL00900§EPLA,OC)
THEN C='MODUL IS NOT YET LOADED'
Joined: 08 May 2006 Posts: 1205 Location: Dublin, Ireland
Quote:
Coding it after or before does not matter.
This statement is incorrect. A Using statement must precede any instruction referencing a DSECT as otherwise the Assembler can't resolve the address.
What you should do is to load R1 with the address of the parameters you wish to pass, which probably isn't the address of your savearea.
Quote:
LA R11,=A(DesectName)
Using R11,DesectName
is also incorrect since the Assembler doesn't know what DsectName means until after seeing the USING statement.
The location of your parameters is either a constant within your program or an address you acquired (e.g via Storage Obtain). R1 should be loaded with this address.
Code:
L R1=A(PARMAREA)
USING PARMS,R1
.
.
.
.
PARMAREA DC D
.
.
PARMS DSECT
PARM1 DS F
PARM2 DS F