[net.unix-wizards] PDP-11 stack use

jfw (01/15/83)

A long time ago, I wanted to write a better setjump/longjump system.
This involved finding out what the C stack frame looks like.  After 3
days of poking through cc -S output, I determined the stack frame for the
PDP-11 and, not desiring to ever go through that work again, came up
with the following manual page for the stack frame:

**************** /usr/man/unix/chap5/stack.5 ****************

.nr LL 6.5
.TH STACK 5 PDP-11
.SH NAME
stack, C subroutine discipline
.SH DESCRIPTION
A C subroutine stack frame looks like the following:
.nf
.in +5
.ta 8 16 24 32 40 48 56 64

------------------
|...nth argument |		push arguments in reverse order
------------------
|second argument |
------------------
| first argument |
------------------		JSR PC,*$_FOO
| return address |
------------------		JSR R5,CSV
|  old R5 value  | <----- 
------------------	|
|	r4	 |	|
------------------	|
|	r3	 |	|
------------------	|
|	r2	 |	|
------------------	|
|   blank word	 |	|
------------------	| This is the top of the stack
|     routine	 |	| when the called routine "starts"
|    allocates	 |	|
|     storage	 |	|	SUB $n,SP
|    temporary	 |	|
------------------	|
| push arguments |	|
| of next routine|	|
------------------	|	JSR PC,*$_BAR
| return address |	|
------------------	|	JSR R5,CSV
| old R5 value---+-------
------------------	^
| r4/43/r2/...	 |	|
------------------
| and so on..... |

.fi
.in -5
Functions leave their return value in R0 (floating functions return it in FR0).
"long" functions leave return values in R1/R0; functions returning structures
leave a pointer to bss storage (one chunk of which is allocated for each such
routine) in R0, and the caller will copy from that bss storage to the
local destination.

Local variables are allocated in such a way that they are referred to
as "-N(R5)", arguments are referred to as "+N(R5)"; arguments start at 4(R5),
the first integer local declared will be at -10[8](R5).

It is important to note that routines know how many arguments they pass to a
function, and will adjust the stack accordingly after a function returns.

.SH AUTHOR
John F. Woods, MIT Concouse Computer Center

ka (01/17/83)

One corrections to John's article:  there is no blank word above the space
for local variables.  There IS a blank word below this if the routine con-
tains function calls with arguments; this is used to save the last function
argument to decrease the number of pushes and pops done on the stack pointer.
					Kenneth Almquist

jfw (01/18/83)

Could someone mail me a copy of what went out on the net for my PDP-11 stack
use manual page?  Ken Almquist's comment sounds like the older version of my
document, which I first submitted in a fit of narcolepsy.  I thought I editted
the version in /usr/spool/news, but uucp might have (for once) promptly logged
in and spirited it off before I noticed.  Sigh.
	John Woods

dmmartindale (01/18/83)

Note that the "blank word" in the PDP11 stack layout is always BELOW the
local variables, not between them and the saved registers.  One word of
space is reserved by csv, but if the routine has any local variables
one of these will use this word, and the stack address below all of the
locals becomes the "blank word".  Thus, unless an arithmetic temporary has
been stored on the stack, (sp) is always a free word, and so when calling
another routine, the last argument can be stuffed directly rather than using
auto-decrement addressing.  This saves a tiny bit of time, but the real
saving comes when adjusting the stack after that routine's return.  If you
passed only one word of arguments, no adjustment is necessary, if there
were two arguments you can use a tst (sp)+ instead of a cmp (sp)+,(sp)+, and
for three arguments you can use cmp instead of add.  Since an awful lot
of subroutine calls will have 1, 2, or 3 arguments this saving is worthwhile.

gwyn@brl-vld.arpa (03/05/83)

From:      Doug Gwyn (VLD/VMB) <gwyn@brl-vld.arpa>

Fine, except there is not a "blank word" in the stack frame after the
saved R2; it is part of allocated auto storage.  The cell "(sp)" is
available for scratch use by the C code generator and percolates to
the top of the stack as it grows.

The same stack frame is used on modern Bell PDP-11 UNIX, but the
procedure linkage was changed from "jsr r5,csv" to "jsr r0,csav"
to solve a problem discussed in this mailing list not very long ago.

Bell UNIX documents the stack frame, although not as thoroughly as
you have done, in the sources for csav and cret.

cak@Purdue (04/01/83)

From:  Christopher A Kent <cak@Purdue>

Aw come on! Such a man page would give it all away! I mean, a programmer
could just sit down and have it all right there, and not have to go
digging! What fun would that be? It would be too easy to become a wizard.

(I'm actually half serious...I think that some of the best learning I
did was prowling through the UPM looking for something totally different
than what I found. I STILL tell new users to go home and read the WHOLE
UPM; I also say that they probably won't care/understand at least 50% of
it, but someday, they'll need something, and it will be tucked away in
the back of their hindbrains that they saw it SOMEWHERE once...)

Cheers,
chris