WHAT DOES NARGS() DO?

Dan Franklin dan at BBN-PROPHET.ARPA
Sat Apr 26 02:24:06 AEST 1986


The short answer is, nargs() does nothing, now, and you are unlikely to
find it on any modern "UNIX brand operating system." Don't use it.  To
quote the 6th edition manual page, "altogether it is best to avoid using
this routine and depend on, for example, passing an explicit argument count."

In 6th edition UNIX, nargs() returned the number of arguments on the
stack.  Well, not quite: it returned the number of *words* of arguments on
the stack; you needed to know already whether the arguments were ints (1
word) or doubles (4 words) or the new-fangled, partially-implemented
"long" datatype (also 2 words).

Even in 6th edition nargs() was falling out of favor, as the manual page
implies.  Its main problem then was that it didn't work in separate I & D
space, which was becoming quite popular as programs grew too large to fit
in 64kbytes (48kbytes for text and data).  It was also a bit sluggish, and
those of us who looked inside it never really felt comfortable with it
either.  As the old "dragon book" said in a footnote, "... argument counts
are obtained by a method we shall not discuss." The method was to peek at
the instruction stream immediately following the JSR and decode the
instructions to see how many words were popped off the stack immediately
following the call.  There was a potential off-by-one problem because the
top of the stack was normally kept "empty"; you could call a routine with
one argument without doing a push of the argument.  So the compiler chose
one of two equivalent forms of addressing for the destination to indicate
to nargs() whether or not it should add 1 to the number of popped words.

Nargs() understood that the compiler might pop the stack using either
explicit stack pointer arithmetic or instructions that popped the stack as
a side effect ("cmp (sp)+, (sp)+" was good for two words).  To handle some
kinds of optimization, nargs() was capable of following jump instructions.
I think it stopped at the first instruction that wasn't a kind of pop or a
jump.

In separate I&D space this didn't work because in user mode on a PDP-11, a
program couldn't read its own instruction space: instructions and data
occupied the same "addresses".  In theory you could use the MFPI (move
from previous instruction space) instruction to get around this, but in
practice you would find that DEC had specially prohibited this, even when
both the current and previous instruction spaces were user mode.  I think
this was intended as a kind of "security".  Some organizations solved the
problem by cutting a trace on one of the processor boards, which was all
it took to make nargs() work using MFPI.

It is amusing to note that the wait() system call in the V6 library
used nargs() to determine whether it was being called with 0 or 1
arguments.  The first time we tried running a program that used wait()
in separate I&D space, we got quite a surprise!

	Dan



More information about the Comp.lang.c mailing list