Those frames are organized in a stack-like manner. That would (by the
way) explain why C came relatively late to those machines: the
difficulty of having to keep track of a software stack is large.
Not large. Instead of Push R0 you'd have to do Add R13,4: Mov [R13],R0
or some such thing, maybe even a single instruction, assuming a linear
upwardly growing stack.
But, that screws up R13, which /always/ must point at the start of the
SAVEAREA (i.e. the "stack frame").
[snip]
Perhaps IBM weren't capable of doing anything simple.
No. IBM had to fit the requirements of the C language into an
already-established operational environment, on a CPU architecture
that /did not/ include a dedicated stack-pointer register. So, they chose
to expand the already-existing linked-list of SAVEAREAs to include a
scratchpad area for automatic variables.
Recursion is handled by chaining saveareas together, with each instance
having it's own savearea. The total size of a single instance's automatic
variable allocation is known (excluding VLAs, which can be handled
differently) at compile-time, and thus the size of each scratchpad area
within the chained SAVEAREAs is known.
The CPU /does not/ have a dedicated stack pointer.
The OS environment /already/ requires R13 to point at the equivalent of an
activation record.
It takes little effort on the part of the language implementors to expand
that activation record to include the "automatic" variables allocated to
one instance of the function, and to use the existing mechanism of linking
and unlinking these activation records to facilitate recursion.
FWIW, the first 72 octets (18 "fullwords") of the SAVEAREA are reserved for
storage of general registers and other linkage information.
SAVEAREA+4 holds the previous contents of of the previous caller's R13
SAVEAREA+12 holds the previous contents of R14
SAVEAREA+16 holds the previous contents of R15
SAVEAREA+20 holds the previous contents of R0, etc
It is the responsibility of the called function to save the caller's
registers and state, and then point R13 to the empty savearea that any
called functions will save the current function's state in. Thus, you see
at the beginning of an Assembly program
STM 14,12,12(13) SAVE CALLERS REGISTERS IN HIS SAVEAREA
ST 13,MYSAVEAREA+4 SAVE CALLERS SAVEAREA POINTER IN MY SAVEAREA
LA 13,MYSAVEAREA SET MY SAVEAREA POINTER TO POINT TO MY SAVEAREA
and at the end
L 13,MYSAVEAREA+4 RESTORE CALLERS SAVEAREA POINTER
LM 14,12,12(13) RESTORE CALLERS OTHER REGISTERS
BR 14 RETURN TO CALLER
I was employed to write programs in IBM Assembler for about 30 years. This
comes naturally to me. As does refuting Jacob's dilettante assertions about
IBM's operating environment.
--
Lew Pitcher
Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------