What is the PDP-11 instruction set?
ftp.dbit.com
ftp.dbit.com
At least that is what my compilers writing class taught me 25 years ago ;-)
As far as I can tell the C operands are fairly simple and basic (add, subtract, complement, and, or, xor etc...). They would almost always map to a single instruction in MIPS, ARM32, ARM64, Z80 etc... So I'm not convinced that there's a direct correlation here, one way or the other.
Conversely if C was really deeply influenced by the PDP-11 ISA then why isn't there a single "bit set", "bit clear" or "rotate right" operator in C? Those require multiple operators in C but a single opcode here. Rotation in particular is a bit of a pain to code in C since you need to know the size of the integer you're rotating. I always thought that it was an oversight not to have built-in support for rotations in C.
The only thing that really stands out as being fairly C-ish is the auto-incrementing and -decrementing addressing modes which map well to p++ and friends (although ++p needs two opcodes as far as I can tell) but it's a feature that's available on other ISAs.
* --i = * j++ is directly a «mov @(r0)+, -(r1)» (provided * j is in r0 and * i is in r1) whereas * i++ = * j-- is a «mov @-(r0),@(r1)+»; i[4] = 1 is «mov #1, @4(r1)» and * (int * )040 |= 01 is «bis 01, @#040». A function call via a function pointer (that is, say, stored in r2) is a «jsr pc, @(r2)» etc etc.
Most of the C pointer operations map onto single PDP-11 instructions and can be used even with the program counter register (which is r7).
UCSD Pascal, TECO/KED, learning Dibol.... I learned on an 11/23 running RT-11, VT100, dual RL02s (oh, yeah). I never did learn anything serious about the O/S.
Our high school had an ancient PDP-8 we used DEC Basic on.
So for example your code could have an always-resident portion say from 0 to 100000 octal (the lowest half of memory) and an overlay area from 100000 to 140000. We had a program that has an input, calculation and runtime phase so it suited the overlay model; programs that needed all their code in memory at the same time by comparison would not be suited to overlays (especially on 8" floppies, where loading an overlay was accompanied by plenty of mechanical noise).
And you could also use tricks like TSR for simulating multiprocessing.
* Though later PDP-11s like the LSI-11 did have microcode -- AKA, in the argot of the time, a "writable control store"
mov -(pc),-(pc)
In other words, the net effect is the instruction has been copied down 1 word in memory. Finally, because it's the PC that's in use and it's been decremented to point to the new copy of the instruction, the copy of the instruction is fetched and the operation repeats. So the instruction copies itself down in memory, until all memory below the starting point is filled with 014747; what happens next depends on the particular system, but generally not useful (the instruction was often used to check memory; key it in at the highest address, run it and then inspect memory to see if it has the same value everywhere).
As an aside, in octal this translates to 014747; 01 is the MOV, 4 is the pre-decrement mode and 7 indicates R7. Thus an assembler is barely needed on a PDP-11, because knowing the opcodes for the common instructions and the addressing modes makes it trivial to convert an assembly instruction like MOV #123,@#1000 into the octal 012737 000123 001000.
The bootstrap routines are often only a few lines of assembler, thus it was easy to remember, translate to octal on the fly and key them into the front panel switches with a few well-practiced sweeps across the toggle keys.
Then find either an assembler or use the debugger.
The most important of which was probably MOV (0001, or 01 octal). Thus, something like the C 's++=t++' translates direction to a single 16-bit instruction:-
0001 011 001 011 002 = 012122
The cleverness though was that by using the addressing modes on the PC (R7) things like loading a constant into memory or moving memory contents was all single-instruction as well:-
e.g. MOV #7, @#1000 # Put '123' int address 1000 ==> MOV (PC)+,@(PC)+ ==> 012737 7 1000
The same trickery made relative addressing easy, made PUSH and POP nothing more than MOV instructions (though it did take me some time to understand the use of R5 for passing arguments in Fortran).
At PDP, the PDP-5, PDO-8 and PDP-12 were 12-bits and the PDP-6 and PDP-10 were 36 bit, all of which are multiples of both 3 and 4
Memory was expensive at the time, so I would guess most of them had 6-bit character sets. That must have made octal a popular choice.
I think https://en.wikipedia.org/wiki/Hexadecimal#History_of_written... shows the notation for hex wasn’t settled upon. I think that’s an indication of its rarity (go read it to learn which version was deemed “ridiculous” :-) )
I think that standardising on 8-bit bytes and power of 2 words is what pushed us to hex as a standard notation
But it was because there were 8 registers and 8 addressing modes, so a two operand instruction used 6 bits for each, leaving 4 bits for the instruction.