Noel,
Thanks for that.
As a non-C consumer of printf, should I point R5 at some space for a stack
and call printf in the same manner as the C example I cited? If it's all
too hard I'll stick to writing to stdout with my own routines.
Paul
*Paul Riley*
Email: paul(a)rileyriot.com
On Mon, 28 Jun 2021 at 14:49, Noel Chiappa <jnc(a)mercury.lcs.mit.edu>
wrote:
From:
Paul Riley
I want to use printf from an assembly language
program, in V6. ...
the
substitutional arguments for printf are pushed
onto the stack in
reverse
order, then the address of the string, and then
printf is called.
After
this, 6 is added to the stack pointer.
This is all down to the standard C environment / calling sequence on the
PDP-11 (at least, in V6 C; other compilers may do it differently). Calls
to
printf() are in no way special.
Very briefly, there's a 'frame pointer' (R5) which points to the current
stack
frame; all arguments and automatics are relative to that. A pair of
special
routines, csv and cret (I couldn't find the source on TUHS, but it
happens to
be here:
http://ana-3.lcs.mit.edu/~jnc/tech/unix/lib/csv.s
if you want to see it), set up and tear down the frame on entry/exit to
that
routine. The SP (R6) points to a blank location on the top (i.e. lower
address;
PDP-11 stacks grow down) of the stack.
To call a subroutine, the arguments are pushed, the routine is called
(which
pushes the return PC), and on return (which pops the return PC), the
arguments
are discarded by the caller.
(I wrote a note, BITD, explaining how all this worked; I'll upload it to
the
CHWiki when I get a chance.)
I assume that the printf routine pops the address
of the string off
the
stack, but leaves the other values on the stack
No, all C routines (including printf()) leave the stack more or less
alone,
except for CSV/CRET hackery, allocating space for automatic variables on
routine entry (that would be at L1; try looking at the .s for a routine
with
automatic variables), and popping the return PC on exit. The exception to
this
is the stuff around calling _enother_ routine (sketched above).
Another exception is alloca() (source here:
http://ana-3.lcs.mit.edu/~jnc/tech/unix/lib/alloca.s
again, couldn't find it in TUHS), which allocated a block of memory on
the stack (automatically discarded when the routine which called alloca()
returns). Note that since all automatic variables and incoming arguments
are relative to the FP, alloca is _really_ simple; justs adjusts the
SP, and it's done.
What troubles me is that the stack pointer is not
decremented
before the
first mov, in the example below. Is this some C
convention? I would
assume that the first push in my example would overwrite the top of
the
stack.
That's right; that's because in the C runtime environment, the top
location
on the stack is a trash word (set up by csv).
I understand db only works on files like a.out or
core dumps. If I
wanted to break the assembly language program to examine values,
how can
I force a termination and core dump elegantly, so
I can examine some
register values?
Use 'cdb':
https://minnie.tuhs.org//cgi-bin/utree.pl?file=V6/usr/man/man1/cdb.1
which can do interactive debugging.
Noel