> From: Johnny Billquist
> the PDP-11 have the means of doing this as well.... If anyone ever
> wondered about the strangeness of the JSR instruction of the PDP-11, it
> is precisely because of this.
> ...
> I doubt Unix ever used this, but maybe someone know of some obscure
> inner kernel code that do. :-)
Actually Unix does use JSR with a non-PC register to hold the return address
very extensively; but it also uses the 'saved PC points to the argument'
technique; although only in a limited way. (Well, there may have been some
user-mode commands that were not in C that used it, I don't know about that.)
First, the 'PC points to arguments': the device interrrupts use that. All
device interrupt vectors point to code that looks like:
jsr r0, _call
_iservice
where iservice() is the interrupt service routine. call: is a common
assembler-language routine that calls iservice(); the return from there goes
to later down in call:, which does the return from interrupt.
Use of a non-PC return address register is used in every C routine; to save
space, there is only one copy of the linkage code that sets up the stack
frame; PDP-11 C, by convention, uses R5 for the frame pointer. So that common
code (csv) is called with a:
jsr r5, csv
which saves the old FP on the stack; CSV does the rest of the work, and jumps
back to the calling routine, at the address in R5 when csv: is entered. (There's
a similar routine, cret:, to discard the frame, but it's 'called' with a plain
jmp.)
Noel
Lots of tools now seem to use this strategy: there's some kind of wrapper which has its own set of commands (which in turn might have further subcommands). So for instance
git remote add ...
is a two layer thing.
Without getting into an argument about whether that's a reasonable or ideologically-correct approach, I was wondering what the early examples of this kind of wrapper-command approach were. I think the first time I noticed it was CVS, which made you say `cvs co ...` where RCS & SCCS had a bunch of individual commands (actually: did SCCS?). But I think it's possible to argue that ifconfig was an earlier example of the same thing. I was thinking about dd as well, but I don't think that's the same: they're really options not commands I think.
Relatedly, does this style originate on some other OS?
--tim
(I realise that in the case of many of these things, particularly git, the wrapper is just dispatching to other tools that do the werk: it's the command style I'm interested in not how it's implemented.)
On 2017-03-27 04:00, Greg 'groggy' Lehey <grog(a)lemis.com> wrote:
> On Monday, 27 March 2017 at 6:49:30 +1100, Dave Horsfall wrote:
>> And as for subroutine calls on the -8, let's not go there... As I dimly
>> recall, it planted the return address into the first word of the called
>> routine and jumped to the second instruction; to return, you did an
>> indirect jump to the first word. Recursion? What was that?
> This was fairly typical of the day. I've used other machines (UNIVAC,
> Control Data) that did the same. Later models added a second call
> method that stored the return address in a register instead, only
> marginally easier for recursion.
>
> At Uni I was given a relatively simple task to do in PDP-8 assembler:
> a triple precision routine (36 bits!) to clip a value to ensure it
> stayed between two limits. Simple, eh? Not on the PDP-8. Three
> parameters, each three words long. only one register, no index
> registers. I didn't finish it. Revisiting now, I still don't know
> how to do it elegantly. How *did* the PDP-8 pass parameters?
This is probably extremely off-topic, so I'll keep it short.
This is actually very simple and straight forward on a PDP-8, but it
might seem strange to people used to todays computers.
Essentially, you pass parameters in memory, as a part of the code
stream. Also, the PDP-8 certainly do have index registers.
The first thing one must do is stop thinking of the AC as a register.
The accumulator is the accumulator. Memory is registers.
Some memory locations autoincrement when used indirectly, they are
called index registers.
That said, then. A simple example of a routine passing two parameters
(well, three):
First the calling:
CLA
TAD (42 / Setup AC with the value 42.
JMS COUNT
BUFPTR
BUFSIZ
. / Next instruction executed, with AC holding
number of matching words in buffer.
.
Now, this routine is expected to count the number of occurances of a
specific word in a memory buffer with a specific size.
At calling, AC will contain the word to search for, while the address
following the JMS holds the address, and the following address holds the
size.
The routine:
COUNT, 0
CIA
DCA CHR / Save the negative of the word to search for.
CMA
TAD I COUNT
DCA PTR / Setup pointer to the address before the buffer.
ISZ COUNT / Point to next argument.
TAD I COUNT
CIA
DCA CNT / Save negative value of size.
DCA RESULT / Clear out result counter.
LOOP, TAD I PTR / Get next word in buffer.
TAD CHR / Compare to searched for word.
SNA / Skip if they are not equal.
ISZ RESULT / Equal. Increment result counter.
ISZ CNT / Increment loop counter.
JMP LOOP / Repeat unless end of buffer.
CLA / All done. Get result.
TAD RESULT
JMP I COUNT / Done.
PTR=10
CNT=20
CHR=21
RESULT=22
Addresses 10-17 are the index registers, so the TAD I PTR instruction
will autoincrement the pointer everytime, and the increment happens
before the defer, which is why the initial value should be one less than
the buffer pointer.
Hopefully this gives enough of an idea, but unless you know the PDP-8
well, you might be a little confused by the mnemonics.
As you can see, the return address at the start is used for more than
just doing a return. It's also your argument pointer.
Johnny
> From: Doug McIlroy
> As Erdos would say of a particularly elegant proof, "It comes from the
> Book," i.e. had divine inspiration.
Just to clarify, Erdos felt that a deity (whom he referred to as the 'Supreme
Facist') was unlikly to exist; his use of such concepts was just a figure of
speech. 'The Book' was sort of a Platonic Ideal. Nice concept, though!
Noel
> From: Dave Horsfall
> And as for subroutine calls on the -8, let's not go there... As I dimly
> recall, it planted the return address into the first word of the called
> routine and jumped to the second instruction; to return, you did an
> indirect jump to the first word.
That do be correct.
That style of subroutine call goes back a _long_ way. IIRC, Whirlwind used
that kind of linkage (alas, I've misplaced my copy of the Whirlwind
instruction manual, sigh - a real tresure).
ISTVR there was something about the way Whirlwind did it that made it clear
how it came to be the way it was - IIRC, the last instruction in the
subroutine was normally a 'jump to literal' (i.e. a constant, in the
instruction), and the Whirlwind 'jump to subroutine' stored the return address
in a register; there was a special instruction (normally the first one in any
subroutine) that stored the low-order N bits of that register in the literal
field of the last instruction: i.e. self-modifying code.
The PDP-6 (of which the PDP-10 was a clone) was on the border of that period;
it had both types of subroutine linkage (store the return in the destination,
and jump to dest+1; and also push the return on the stack).
Noel
> From: Arthur Krewat
>> The PDP-6 (of which the PDP-10 was a clone)
> Um. More like a natural progression.
> Like 8086->80186->80286->80386->80486->...
No, the PDP-6 and PDP-10 have identical instruction sets, and in general, a
program that will run on one, will run on the other. See "decsystem10 System
Reference Manual" (DEC-10-XSRMA-A=D", pg. 2-72., which provides a 7-instruction
code fragment which allows a program to work out if it's running on a PDP-6, a
KA10, or a KI10.
The KA10 is a re-implementation (using mostly B-series Flip Chips) of the
PDP-6 (which was built out of System Modules - the predecessor to Flip Chips).
Noel
Nudging the thread back twoard Unix history:
> I really
> like how blindingly obvious a lot of the original Unix code was. Not saying
> it was all that way, but a ton of it was sort of what you would imagine it
> to be before you saw it. Which means I understood it and could bugfix it.
That's an important aspect of Thompson's genius--code so clean and right
that, having seen it, one cannot imagine it otherwise. But the odds are
that the same program from another hand would not have the same ring of
inevitability. As Erdos was wont to say of an elegant proof, "It comes
> like how blindingly obvious a lot of the original Unix code was
> ... sort of what you would imagine it to be before you saw it.
That's a facet of Thompson's genius--code so clean and right that,
having seen it, one cannot imagine it otherwise. Odds are, though,
that the same program from another hand would not have the same
aura of inevitability. As Erdos would say of a particularly elegant
proof, "It comes from the Book," i.e. had divine inspiration.
Doug