The PDP-11's program counter was addressable in two ways: as a general purpose register or as a memory location.

Still, the PDP-11's instruction set included separate instructions for moving a new value into the PC. Did the designers not realise that the MOV instruction would have done the trick? Is there something I'm missing?

  • 12
    Probably not applicable in this case, but in some assembly languages you'll see different mnemonics being encoded to the same basic opcode, so it would be possible for JMP to be implemented as a MOV. Commented Apr 13, 2017 at 19:39
  • 2
    I have made the discovery, that the CP1600, which was modelled on the PDP-11, does exactly as @RussellBorogove says: the same bit-pattern in the opcode for MOVR also was used for JMPR and some others depending on what the source/destination registers are. Commented Jul 6, 2018 at 9:46

3 Answers 3


Besides the flags, and differences in cycle count, the more important difference is that JMP x uses the effective address of x, while MOV x,R7 uses the value at x. In other words, there's one level less of indirection, similar to the LEA and MOV opcodes for the x86.

So JMP R1 faults, and JMP @R1 is equivalent to MOV R1,R7.

This means one can use JMP d(R7) for relative jumps with a full 16-bit displacement (BR d only has an 8-bit displacement, which is often not enough). In the same way, one can store the address of some block of code (library) in, say, R1, and use JMP d(R1) to jump to a fixed displacement inside this code block. All of this is not possible with a single MOV instruction.

It doesn't make sense to access a register via the memory mapped address instead of just using it directly, because accessing them this way would need one more word per instruction, and therefore is inefficient.

  • IIRC, bulk register save-restore routines made use of the ability to address registers as memory.
    – Leo B.
    Commented Apr 12, 2017 at 20:15
  • I wonder if this architecture actually would let you execute code in register. I've already used one that allowed it.
    – Joshua
    Commented Apr 13, 2017 at 2:36
  • @Joshua: Not to my knowledge, and it would be really difficult to assign a meaning to multi-word instructions as the register only holds one word. That's much easier on architectures where a complete instruction always fits into a register.
    – dirkt
    Commented Apr 13, 2017 at 6:21
  • @Wilson: If you remember on which versions of the PDP-11 had that feature, I'd be very interested. Registers have 16 bits, instructions have up to three words with 16 bit, so I can't imagine how it could work. I know it works e.g. on the PDP-1 (XCT instruction), which had 18-bit instructions but 36-bit registers, and no multibyte instructions.
    – dirkt
    Commented Apr 13, 2017 at 10:49
  • 2
    @Wilson: I understand this to mean it executes code fetching from 17777xx, where the contents of the registers are memory mapped? That's different than executing "code in a register" in the sense of non-faulting JMP R1 or PDP-1 XCT: it still executes via reading from "memory".
    – dirkt
    Commented Apr 13, 2017 at 11:48

MOV changes the N, Z and V flags according to the copied data. JMP doesn't do that. It means you can run e.g. arithmetic operations somewhere, then jump to another location for the compare routine.

Also JMP appears to be 1 cycle faster. The handbook says JMP takes 1 to 3 cycles while MOV take 0 to 4 - maybe because it doesn't set the flags.

  • 12
    Also worth noting that the PDP-11 was designed with a CISC philosophy, so having multiple subtly different instructions was not viewed as a design problem, but rather a Good Thing.
    – T.E.D.
    Commented Apr 12, 2017 at 14:00
  • 4
    @T.E.D.: CISC vs RISC relates more to whether a computer has a set or reduced instructions, or a set of complex instructions, than whether the set is large or small. The PDP-11 qualifies as CISC because a single instruction could IIRC fetch memory using a register with post-increment, use that resulting address to fetch another word, and then add the fetched value to another register--all in all a rather complicated sequence of steps for a single instruction. ARM has a large number of instructions, but each only requires a single ALU operation (not counting the program-counter increment).
    – supercat
    Commented Apr 12, 2017 at 15:30
  • 1
    @supercat - CISC designs during their heyday had a philosophy that you wanted to make things as easy as possible for (Assembly Language) programmers by giving them as many tools as possible in your instruction set, and by trying to make it higher-level for them (which is how you get Lisp-like queuing operations in instruction sets).
    – T.E.D.
    Commented Apr 12, 2017 at 15:47
  • 2
    @T.E.D.: Certainly designers CISC processors wanted to include a large number of instructions, but I don't think that's what "made" them CISC. Certainly many RISC processors have dedicated jump instructions even when the PC is accessible as a register, though I'm somewhat skeptical as to whether e.g. the ARM's jump and BL instructions were a good use of address space. By the time an instruction reaches the execution stage of the pipeline, the succeeding instruction will have been fetched, so I wonder if it might not have been more useful to say that if an immediate operand...
    – supercat
    Commented Apr 12, 2017 at 16:15
  • 6
    @supercat - True, but I never said any such thing. What I said was that it "was designed with a CISC philosophy". I don't believe the word (or concept of) CISC even existed back then. They just had the idea that they needed to design their instruction set to be of maximum use to Assembly-language programmers. It was only after the RISC idea came along and repudiated that philosophy that we retrospectively term such CPU's "CISC".
    – T.E.D.
    Commented Apr 12, 2017 at 16:19

One more reason is that if you have JMP 2000 and your program is moved in memory 1000 (octal) bytes forward, you automatically have JMP 3000, as it remembers the offset, and not the exact address value. You can use an exact address with JMP this way: JMP @#3000. It will not change when the program moves.

So, relative addressing allows to run the same program, loaded into different memory areas without patching.

  • For small relative jumps (127 words either way) there are the branch instructions.
    – dave
    Commented Jan 6, 2022 at 23:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .