> From: Grant Taylor
> However, I've had to teach enough people to know that they need a way to
> boot strap themselves into an environment to start learning.
Right, but wouldn't they learn more from a clear and concise hand-holding
which explains what they are doing and why - 'do this which does that to get
There is no more a royal road to knowing a system, than there is to
> I do consider what (I believe) Warren put together for the UUCP project
> to be a very good start. Simple how to style directions that are easy
> to follow that yield a functional system.
On 2017-03-28 09:37, jnc(a)mercury.lcs.mit.edu (Noel Chiappa) wrote:
> > 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
> 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.
Ah. Thanks for that. I hadn't dug into those parts, but that's the kind
of place where I might have suspected it might have been, if anywhere.
> 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
Hah! Thinking about it, I actually knew that calling style, but didn't
reflect on it, as you're not passing any arguments in the instruction
stream in that situation.
But it's indeed not using the PC as the register in the call, so I guess
it should count in some way. :-)
In some sense the "command subcommand" syntax dates from ar in v1,
though option flags were catenated with the mandatory subcommand.
The revolutionary notion that flags/subcommands might be denoted
by more than one letter originated at PWB (in "find", IIRC).
> 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
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
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?
(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
First the calling:
TAD (42 / Setup AC with the value 42.
. / 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
DCA CHR / Save the negative of the word to search for.
TAD I COUNT
DCA PTR / Setup pointer to the address before the buffer.
ISZ COUNT / Point to next argument.
TAD I COUNT
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.
JMP I COUNT / Done.
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.
> 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!
> 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).
> 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).