(snip)
It is a little more complicated if you allow for varargs.
As I understand it, ANSI C allows for a different convention for
varargs and non-varargs, but the systems I know (not all that
many) use the same convention. Pushing an unknown number of
arguments right to left means that the caller can find the left
most argument(s) without knowing how many there are.
The early 808x compilers (for Pascal and Fortran) used a convention
where the arguments are pushed left to right, and the called routine
pops them off the stack with a special form of RET. As that is not
compatible with varargs, different conventions were used when C
compilers appeared, where the calling routine pops the arguments.
Many systems that pass in registers still save stack space for them.
No, the return address is always in R14!
BALR R14,R15
Which loaded the address of the next sequential instruction into R14, and
then branched to the address held in R15. Alternatively, with a named
entrypoint, you would code
BAL 14,ENTRYPOINT
(where ENTRYPOINT was the symbolic name or external name of the instruction
that started the subroutine).
To get back to the (previous) next sequential instruction, you would execute
a
BR 14
which would effectively branch to the address held in R14
Of course, for proper linkage, the subroutine would save the "callers"
registers on entry (that is, as the first part of the logic pointed to by
R15), and establish it's own base register and SAVEAREA. On exit, the
subroutine would restore all the saved registers immediately prior to the
BR 14. The address of the save/restore area (aka the SAVEAREA) was always
pointed to by R13
So, the caller would do something like...
LA 13,SA1
...
BAL 14,DOIT CALL DOIT SUBROUTINE
...
SA1 DS 18F
and the callee would do something like
DOIT STM 14,12,12(13) SAVE CALLER REGS EXCEPT R13 IN HIS SA
BALR 12,0 LOAD NSI ADDRESS INTO R12
USING *,12 R12 NOW OUR BASE REG
ST 13,SA2+4 SAVE CALLERS R13 IN OUR SAVEAREA
LA 13,SA2 R13 IS NOW OUR SAVEAREA
...
L 13,SA2+4 R13 POINTS TO CALLER SAVEAREA
LM 14,12,12(13) RESTORE CALLERS REGISTERS
BR 14 RETURN TO CALLER
SA2 DS 18F
FWIW, many s360/370/390/etc apps stored the caller's arguments in space
following the BAL or BALR that invoked the callee. Thus, the caller might
look like
LA 13,SA1
...
BAL 14,DOIT CALL DOIT SUBROUTINE
ARG1 DS F
ARG2 DS F
ARG3 DS H
DS H
ARG3 DS CL3
...
SA1 DS 18F
and the callee would access these parameters as offsets from the caller's
R14. Of course, this meant that the callee had to adjust the caller's R14
to account for the arguments /prior/ to performing the BR 14.