89

Many processors have an instruction called "move" (sometimes spelled MOV) which copies data from one location (the "source") to another (the "destination") in registers and/or memory. It does not do anything to the "source".

This is analogous to the "copy" (or "cp") command in a filesystem. In a "move" (or "mv") in the filesystem, the "source" would no longer be there. It is also contrary to the simple English meaning of "move"... after you move an object, it exists in its new location but no longer in its previous location.

So why call the instruction "move"?

19
  • 7
    Unless any CPU designers (or assembler authors) are here, I think this is going to be a matter of opinion.
    – dave
    Commented Dec 6, 2019 at 1:20
  • 3
    @another-dave Yes and yes/no. In the majority of cases you are correct; the file stays where it was. Only the directory entry changes, wherein the old entry is marked as empty (or cleared) and a new one made for the same file but pretending to be in a different directory. So essentially, the filename is always moved, and the file isn't. ... Unless the file is moved to a different partition, which does actually copy the file to another place.
    – RichF
    Commented Dec 6, 2019 at 2:02
  • 3
    @another-dave, it moves to a different name or directory... it's not still under the old name or directory
    – JoelFan
    Commented Dec 6, 2019 at 2:49
  • 15
    We should keep in mind that processors predate filesystems by several decades.
    – vsz
    Commented Dec 6, 2019 at 9:52
  • 7
    I wonder whether the first use of "move," or "mov," etc. for an assembler mnemonic might pre-date the first disk-based file system. Commented Dec 6, 2019 at 14:29

9 Answers 9

41

Because "move" is the typical necessary function

It isn't always this way, of course, but especially with earlier CPUs, there were limited destinations for data from a particular operation - e.g., arithmetic results could only be in certain registers. Or in the other direction, certain functions could only operate on a few locations, typically registers or a "special" area of memory. So the point wasn't simply to copy in the sense that you might "copy" a file from one place to another, but more like:

I calculated a times b and now I need to move it from the register into the location in memory for c. Yes, the ALU register will still have it, and I could do something more with it there. But very often I will do a different calculation into that register now that I have moved the value elsewhere.

Assembly language programming, especially with a small CPU with a handful of key registers, is very different from high-level language programming - even though one can be translated into the other.

5
  • 9
    Interesting answer. Going from OPs Filesystem reference, that reminds me of how when you delete a file it often doesn't actually delete but merely forgets that the file is there on the harddrive. Why waste time setting it to 0 if you will not need a zero value anyway.
    – findusl
    Commented Dec 6, 2019 at 17:03
  • 7
    The thing is, when you're writing even moderately optimized assembly you always do keep in mind that it's a copy, not a move, because that state might be useful for something else shortly after. E.g., say after ADC #$01, STA $1234 ("move" result to $1234) and BNE otherthing not taken, you want to start with 0 in A. You wouldn't then "move" 0 into A with LDA #0 because that would be a pointless waste of time and space; you'd do nothing because A already has 0 in it since STA of course copied the value.
    – cjs
    Commented Dec 8, 2019 at 0:41
  • @findusl: somewhat similar if you only look at the data, but mov doesn't have any destructive effect on the source, not marking it as "free" or anything like that. There is no extra metadata in most normal register sets. x86's x87 FP registers are a "stack" where fstp st2 copies st0 to st2, then marks the old st0 as "free", popping the stack. (Because we used the "p" version that stores and pops). But for normal register ISAs there's no implication at all of destroying the source, just of making sure the data is present in dst. Commented Dec 8, 2019 at 20:59
  • 2
    You're saying that the name 'move' is used because the function is best described by move - but it isn't. It's clearly a copy, not a move, as the OP maintained. Manufacturers can choose terms but will be influenced by past conventions, wanting to be different to competitors or conventions to appear unique and so on. The 68000 doesn't use 'move' because Motorola went for 'standalone descriptive'.
    – TonyM
    Commented Dec 9, 2019 at 7:23
  • 3
    To paraphrase this answer... "on early processors, the programmer would think, sure, technically it's a copy, but it may as well be a move, because I'm not going to use the source any more but rather overwrite it. The fact that it's really a copy is more of a curious detail than anything useful"
    – JoelFan
    Commented May 26, 2020 at 21:04
47

Besides the matter of semantics and personal taste, there’s a much more practical reason: some instructions sets claim to be copyrighted, as the Wikipedia Z80 article states:

Because Intel claimed a copyright on their assembly mnemonics, a new assembly syntax had to be developed for the Z80. This time a more systematic approach was used.

So, I think the mnemonic scheme of the instructions have to be unique and copyrightable.

Another important factor is the tendency to use 3-letter mnemonics in the 70’s instructions sets, probably to save source code memory and to make input quicker, while maintaining a degree of readability. In the 8080 instruction set, which uses 3 letters, the MOV mnemonic is easy understandable as "move", while the hypothetical COP mnemonic could have other meanings than "copy".

12
  • 14
    what about CPY?
    – JoelFan
    Commented Dec 6, 2019 at 3:13
  • 39
    @JoelFan On the 6502, CPY means "Compare Y register". On the same CPU, data movement is called "load" (from memory), "store" (to memory), or "transfer" (between registers). Modern RISC CPUs have adopted the same convention, except that "transfer" is now called "move".
    – Chromatix
    Commented Dec 6, 2019 at 3:35
  • 9
    Does the copyright angle really explain MOV v. LD in the Z80 instruction set? At least one other contemporaneous architecture used MOV-style instructions, the VAX... The slightly later 68k also uses MOV (or rather, MOVE). Commented Dec 6, 2019 at 10:20
  • 1
    @StephenKitt maybe this has to do with the register structure of the 6502 and similar .. as you had just 3 registers ... X, Y and A - the Accumulator as the main computing register - hence LDA / STA which all refer to this accumulator register.
    – eagle275
    Commented Dec 6, 2019 at 12:20
  • 1
    @eagle275 Z80 assembly certainly seemed familiar to me after the 6502! But the Z80 was designed based on the 8080, not the 6502... Commented Dec 6, 2019 at 12:33
29

TL;DR

It's all about getting systematic, easy to memorise mnemonics, which may reflect some underlaying structure, but most important ease practical use. Exact language is not always a handy one - except you're asking a lawyer :)


So why call the instruction "move"?

Oh, the age old copy-vs-move question. A beloved friend :)

There are many different, equally plausible explanations, but before going into any it's quite important to keep in mind, that naming is not so much about being exact as being descriptive and distinctive. Also, meanings and usage evolves over time. And last but not least, people use terms they learned first.

It as well depends on the features a computer offers, like if it is a generic two address machine or restricted to certain transfers - which may as well result in other alternative, often forgotten here: Load/Store (*1) instead of Copy or Move. In a more generic view, they are all transfers - a word not really implying anything about what happens to the source (*2).

And, as with many items in computer history, the IBM /360 is deeply entrenched in the development of Move vs. Copy as well.

(points in no specific order)

Machine Structure

The copy issue usually only comes up when a machine offers more than a single accumulator. For example the Manchester Baby didn't have any mnemonics in today's notation, but as a single accumulator design some documentation used Load and Store for data transfer between accumulator and memory. A quite clear syntax - then again, not hard for a 7 instruction CPU :)

Then again, it's easy to complicate even a simple machine like that. The ERA/Atlas (Univac 1101) design(s) tried hard to confuse everyone by using a plethora of terms for transfers:

  • Insert for memory (or Q) to accumulator (or Q),
  • Replace for accumulator to memory,
  • Transmit for accumulator to Q and,
  • Store for Q (or lower half of A) to memory.

The Siemens 2002, a single accumulator machine, like the Baby and the ERA/Atlas, simplified it to an all covering Transfer for register/memory transfers ... well, plus Load to for bringing immediate values into registers (*3).

Machine operation

It can depend on the view designers had on the machine. Is it some 'fast' parts, like registers, handling temporary items that get loaded and stored, or how memory works. In fact, with core memory, data really got moved, as the original content was destroyed due the read operation and had to be restored.

Easy Recognition

Copy quite easy collides with compare when using the usual way of 'compacting' words by leaving out vowels. CP vs. CMP is rather close creating potential confusion. For machines not using the Load/Store metaphor, Move gives an easy way out, which brings...

Unique 'Encoding'

While the IBM 1401 forced the user to use single character symbols for instructions, it became already in the 1950s standard to name instructions in a way that the first letter of a mnemonic signals the general meaning or grouping, while the follow up letter(s) are used to specify variations (like L -> Load and LH -> Load Halfword) or to add readability.

Siemens 2002 and IBM /360 are great examples here as they both used that scheme throughout. On the /370 Load/Store as well as Move was used, depending on source/target. It works like this:

A*  -> Add
B*  -> Branch
C*  -> Compare
...
L*  -> Load to register from register/memory
M*  -> Memory to memory move
ST* -> Store register to Memory

The collision between add and and was solved by using N* for and-instructions.

Conclusion:

It was always more about having a nice decodable set of mnemonics than be super clear on the semantic side - after all, new usage creates new semantics, independent of prior application.


And then there is x86 History.

Where it All Started: Datapoint 2200

The Datapoint 2200 was developed by CTC as a tool to replace card based terminals (*4). Thus the language used for their assembler was somewhat /360 orientated, with transfer instructions called Load as they happened only between registers. In this context memory addressed by the memory pointer was just a special case. In fact, except for Jumps and Calls, the 2200 did not feature any memory addressing at all. For any random access H and L had to be loaded with separate 8 bit transfers. Further all mnemonics were created to directly represent an opcode, so each transfer had its own depending on source and destination (*5):

LA  # -> Load A with immediate #
LB  # -> Load B with immediate #
...
LAB   -> Load A with B
LBA   -> Load B with A
...
LAM   -> Load A with Memory (addressed by HL)
LBM   -> Load B with Memory (addressed by HL)
...
LMA   -> Load Memory (addressed by HL) with A
LMB   -> Load Memory (addressed by HL) with B
...

While an according assembler is thus straight forward and can be quite small (*6), this led to a 'mnemonic cloud' of 59 valid mnemonics for what most would considered a single or as maximum 4 different (*7) instructions.

Making it Smaller: Intel 8008

Intel's 8008 is a (mostly) straight forward implementation of the Datapoint 2200. No change so far compared to the Version 1 of the 2200.

Extending the Design: Intel 8080

The 8080 is a greatly enhanced version of the 8008. Most important due the addition of some 16 bit features (INX, DCX, DAD, LHLD, LXI, ...) or direct use of 16 bit addresses for other than Jump/Call (LDA, STA, SHLD, LHLD). In turn Intel simplified the mnemonic landscape by unifying all of the L** instructions into just two MVI for immediate to register and MOV for register to register (*8) transfer. Which register to be used was now encoded as parameters:

8008     8080
====     ====
LA  # -> MVI A,#
LAB   -> MOV A,B
LAM   -> MOV A,M
LMB   -> MOV M,B
...

It's easy to see that this is just a more verbose but still stringent 1:1 relation between a source line and the opcode to be generated. Intel still stopped not only short of integrating the new instructions into the MOV semantics, but even stayed back to use a single mnemonic for the new memory pointer access instructions or the direct load/stores which are at least in itself symmetric. So while cutting off 57 mnemonics, 6 more were clamped on.

Sidestep in Time Line: Zilog Z80

It seems, that the Z80 designers still had an eye on the Datapoint 2200 when designing their new CPU. Not only did they add a second register set, much like the 2200 Type 2, but they also went back to use Load to name all transfer instructions (*10). Just this time all the way with sensible parameter detection. So not only all 8080 MOV became LD, but all the separate mnemonics for other transfers were brought in line:

8008     8080        Z80
====     ====        ===
LA  # -> MVI  A,# -> LD  A,#
LAB   -> MOV  A,B -> LD  A,B
LAM   -> MOV  A,M -> LD  A,(HL)
         LDAX B   -> LD  A,(BC)
         STAX D   -> LD  (DE),A
         STA  adr -> LD  (adr),A
         LHLD adr -> LD  HL,(adr)

Zilog did not only straighten up all transfers, but as well moved conditionals out of the opcode column for all Calls, Jumps and Returns. While not being any result of the improved CPU itself, but a more capable assembler, it was quite used as argument to advertise how much more advanced and comfortable the new CPU was compared to its predecessor :)) (*10)

The End of All Future: Intel 8086

The 8086 was developed as a stop gap measure until the i432 was ready, with a clear focus on existing 8080 users needing an upgrade. Its designers took the same step as Zilog did, but being used to MOV as the generic instruction for data transfer they stayed with it - but now covering every variation. After all, with the huge number of varying addressing modes and data sizes, a simple one mnemonic one opcode with a hack for RI and RR decoding couldn't do it anymore.

And the rest is history, as they say.


Postscript

What I like about the question is that it leads to a core issue of our age: Real vs. Virtual world. Our language developed over millennia to describe physical objects that can only exist once, with a certain uniqueness - copying is an extraordinary process involving much effort. In the digital age, copying isn't special, but the very base of everything. Not only every data item gets copied uncountable times until it's displayed, but already the software doing so is a copy moved into memory from some storage, to be moved into the CPU to be executed.

Our legal system(s) are badly torn when trying to judge the use of software and data (aka content) in terms of physical items, when they are in reality much more like a spoken word.

Next to everything still struggles to handle this, language usage being right at the core and this question pointing to it.


*1 - Which then again opens the question what loading does to 'the item'.

*2 - Again, but less, as a transfer paper adds copies, while a transfer ticket allows to use another transport.

*3 - Well, (next to) all assembler instructions were in German, so TAS spelled out Transferiere AR in Speicherzelle - literally: Transfer AR (accumulator register) to Storage (memory) cell.

*4 - Back then a terminal wasn't a thing on your desk, but anything remote connected to a mainframe - like a card reader in some branch office where all transactions keypunched during the day were unloaded to be read remotely.

*5 - So at the very start 80 style assembler looked much more like later Motorola/MOS sources :))

*6 - Every OP is a 1:1 encoding of the mnemonic, so it's a straight lookup in a 4 byte table. Operands are only possible for certain opcodes and come in only two flavours: 8 bit immediate and 16 bit address.

The resulting assembler was small enough to run on the machine itself, with as low as 4 KiB memory.

*7 - Immediate, Register/Register, Memory/Register, Register/Memory

*8 - Including, like before, a memory cell addressed by HL as M.

*9 - It is sometimes said this was for copyright considerations, but it's hard to justify this in any way, as it wasn't just a renaming, but a complete reorganisation of the mnemonics as well as the assembly syntax. Also, descriptive names and sensible abbreviations thereof can't be trademarked or copyrighted in any country. If at all, the architecture might qualify - or the binary representation of opcodes, something DEC tried, without much success, for the VAX instruction set.

*10 - The Game Boy uses a LR35902 is a great example how a mostly 8080 like CPU can gain from just using Z80 syntax. Likewise when restricting Z80 assemblers to 8080 features.

8
  • @Biff Iam's answer suggests that Z80's mnemonic naming might have been to avoid Intel copyrights on the text mnemonic parts of the ISA. I find "load" semantically weird when the source isn't memory. Just about as weird as x86's lahf which loads AH from FLAGS, and sahf, but those instructions get much less use. Commented Dec 8, 2019 at 21:10
  • 1
    @PeterCordes See footnote#9 - Descriptive names and sensible abrevations thereof can't be trademarked or copyrighted at all. The claim is an urban myth.
    – Raffzahn
    Commented Dec 8, 2019 at 21:52
  • 1
    So that answer deserves a downvote? It didn't make much sense to me anyway, and only explains ld not the original choice of mov. But if it's also wrong about a copyright claim holding any weight, that's just misleading. Urban myth sounds more likely for the reason you say. Commented Dec 8, 2019 at 21:57
  • @PeterCordes well, I didn't upvote. People like to believe - and many such believes are replicated in wiki pages. Who doesn't prefer a good story with conflict and so on :) Intention for MOV/MVI was most likely to clean all Lx/Lxy instructions from the mnemonic list, making it more readable and systematic - they just didn't go all the way, like Zilog did. I'm not really a Z80-fan. Sure it's a nice controller (awesome interrupt handling), but otherwise just an 8080. They stopped short of making it great. But I do love what they did to the assembler. Quite clean and easy to read.
    – Raffzahn
    Commented Dec 8, 2019 at 22:14
  • 1
    I really love this StackEchange. Not only are most questions accepted and not downvoted like in the big brother-site, but the answers… Really terrific, understandable, knowledgable, such a rich source of answers to questions I had so many years ago when I moved (!) from Z80 to 8086 :)
    – ABM K
    Commented Sep 7, 2023 at 15:38
16

This is actually a fun little question to answer, because I get to go into how a CPU actually works, including the major difference between typical CISC and RISC architectures. In computing it is generally accepted that "moving" data is actually a copy operation, with the original remaining until overwritten; even in the bad old days of literal core memory, where the core was erased by reading it, the memory hardware automatically rewrote it to preserve that idea.

I'll talk about RISC first, or to put it more precisely, the three-operand load-store architecture. Here, the ALU is connected to the register bank (which is typically relatively large, 16 words or so) and does not have a direct path to or from external RAM. The destination register for ALU ops is specified explicitly, so a typical instruction has three operands, two inputs and one output.

There is a separate subsystem, which can usually operate in parallel with the ALU, for getting data in and out of RAM. The instructions which activate this subsystem tend to carry mnemonics of "load" and "store", indicating the direction of data movement explicitly. But there usually is not a dedicated instruction for getting data from one register to another. Instead, an ALU instruction is chosen which doesn't modify the source data, and usually the assembler provides a "pseudo mnemonic" so the programmer doesn't have to remember how to do that. Often the CPU itself will then recognise this special case and avoid having to physically pass the data through an execution pipeline.

So in PowerPC he can write mr rD,rS and the assembler converts that to ori rD,rS,0. The mnemonics here are "move register" and "OR immediate". ARM has MOV for this purpose, but still uses "load" and "store" mnemonics for memory operations.

Typically CISC is instead a two-operand accumulator architecture. Here, the ALU notionally has two physical operand buses, one connected directly to the register bank and the other to complex addressing mode logic that can take data directly from a register or from RAM. The result bus leads directly from the ALU output to the write port of the register bank, and also to the writeback buffer on its way to RAM.

Consequently, the only way to get data into a register or back into RAM is to pass it through the ALU. So one of the ALU's functions is to ignore one of the operands and pass the other through unchanged. This function is selected by the MOV or MOVE opcode. A very similar ALU mode is responsible for the NOT and NEG instructions, except that the data is then not unchanged, but the data path is the same. One advantage of this approach is that the same complex addressing modes are available for any ALU operation, of which MOV is just one.

The 6502 is a one-operand accumulator architecture; because there is only one register (normally) accessible to the ALU, it doesn't need to be specified explicitly as the destination for ALU results. Hence all 6502 instructions have at most one operand following the opcode, though that operand may be either one or two bytes.

Its mnemonics therefore adopt the "load" and "store" convention also used in RISC, and to get data from one register to another the instructions have mnemonics beginning with T for "transfer" (rather than M for "move") followed by two letters indicating the source and destination (eg. TAX transfers from Accumulator to X Index). Indeed there are no 6502 mnemonics beginning with M at all.

However there are several that begin with C, and these are instructive as to why "copy" was not used in this CPU. CMP performs a comparison involving the accumulator, but CPX and crucially CPY perform similar comparisons involving the index registers. With all 6502 mnemonics being 3 letters, CPY would have been the obvious contraction of "copy".

9
  • 2
    fun fact: ARM needs a hardware mov opcode (not just pseudoinstruction) because it doesn't have a hardwired zero register and it wants that opcode to use the real source operand as the 2nd operand which can be a "flexible" operand: immediate or shifted register. It doesn't need shift opcodes because every instruction can have a shifted input, so lsl r0, r1, #2 is just a pseudo-instruction for mov with a shifted source. Implementing mov as orr r0, r1, #0 would have removed that possibility. Commented Dec 8, 2019 at 21:21
  • The ALU in a RISC isn't typically directly connected to the register file. One operand might be an immediate, and forwarding from the previous instruction is possible for either or both operands (bypassing write-back to the register file). Commented Dec 8, 2019 at 21:26
  • CISC NOT and NEG are typically 1-operand instructions. Did you have an ISA in mind that has NOT A, B to copy-and-NOT? x86 has to mov eax, ebx / not eax. Or copy-and-NEG by zeroing the destination and using sub. Anyway yes in theory you could have this, but instruction-encoding considerations usually mean packing one-operand instructions more closely instead of making them copy-and-op. e.g. x86 uses the /r field of the ModR/M byte as extra opcode bits for op r/m, imm8 and for one-operand instructions like inc/dec/not/neg. And also shifts. 8-bit CISC won't copy-and-op Commented Dec 8, 2019 at 21:30
  • A classic RISC 5-stage pipeline puts the MEM stage after ALU. It can operate in parallel with the next instruction's ALU phase yes. But the ALU gets used for address-generation by memory instructions, in ISAs like MIPS where the only addressing mode is reg+sign_extended_imm16. Anyway, that part's not wrong and it probably doesn't really matter if its misleading. Different phrasing doesn't spring to mind but I wanted to comment anyway. :/ Commented Dec 8, 2019 at 21:34
  • In general I agree with what you're saying, but the real answering-the-question part just boils down to the fact that cpy is too visually similar to cmp, or is even compare-with-Y. I guess talking about how MOV is implemented in RISCs as a pseudo-instruction is interesting if you don't know that, so not downvoting. Also fun fact: AArch64 has a zero register (wzr/xzr) and does encode mov reg,reg as ORR with the zero register, allowing the source operand to be a shifted reg or a bit-pattern immediate. Separate-opcode for 16-bit wide immediate. Commented Dec 8, 2019 at 21:41
9

Copy implies at the end you care about having 2 independent copies. Move implies at the end you care only about having the destination.

In assembly language, and particularly in register-starved architectures such as the 6502, you are moving (not wanting to copy) stuff around a lot because data has to be in a certain register to do something.

Additional implementation circuitry is needed to perform an actual move where the source contents are destroyed. Real moves would be something like "Copy src->dest, set src to 0" whereas simple copies are just the "Copy src->dest." So even though a move is what's meant, it's cheaper to implement as a copy.

Inconsistent words have been used in various assembly language mnemonics to describe what is a copy over the history of CPUs.

  • 6502 uses "load" (LDA) and "transfer" (TXA, etc.)
  • MIPS uses "load" (lui) and "move" (mfhi, mflo)

  • Intel and many others used MOV, including the PDP-8 and VAX.

  • 68000's was MOVE.

  • Z80 had LD

  • POWER's instructions use ld for load and st for store.

  • The Intel 4004 has mnenomics that refer to "Load" (not "Store" though), Fetch, Read and Write.

So it's really up in the air.

3
  • 1
    MOV for PDP-8, really?
    – lvd
    Commented Dec 7, 2019 at 16:19
  • POWER / PowerPC uses mr for "move register". As another answer points out, it's actually a pseudo-instruction for or with an immediate zero. I guess you're only including mnemonics for true hardware machine instructions, even though the same ISA vendors typically define mnemonics for pseudo-instructions as well. Commented Dec 8, 2019 at 21:46
  • "Copy implies at the end you care about having 2 independent copies. Move implies at the end you care only about having the destination." I'm afraid that reads like you're making it up as you go along, there. Copy and move have perfectly stable and distinct meanings with no ambiguous subtext. As the OP says, copy describes what actually happens and move doesn't. Move wasn't chosen because secretly it defines it better. I thinks it's something in convention, technical office politics, companies wanting to stand apart or summat else. But it's not that move's a better description of a copy.
    – TonyM
    Commented Sep 9, 2023 at 9:19
6

Assembly language was initially just a tiny step up from machine programming and its main function was to convey a bit more meaning when drafting code and when dumping disassembly. As a result, it tended to be very matter of fact and directly and mechanically translatable with little effort to machine code.

If you take a look at the 8080 mnemonics, sort of the most widespread microcomputer mnemonics at their time due to CP/M's availability, you don't have various "overlaid" meanings of "LD" like the Z80 mnemonics had but rather every code point has its own mnemonic.

The operators working with fixed registers (add/subtract, even things like exchange-top-of-stack-with-memory-pointed-to-by-HL) don't name those fixed registers as operands but, if at all, have them hardwired into the mnemonic.

Mnemonics are generally only 3 letters (with exceptions "CALL", "PUSH", "SPHL", "XCHG", and "XTHL") for more compact printouts, with the 4 letter mnemonics having at most one argument.

To load register B with the value 7, you'd write MVI 7,B. The respective mnemonic CPI (if one wanted to use "copy" as basis for the mnemonics) is already taken by "compare accumulator to immediate value", with CPI 3 comparing the accumulator with the value 3 and setting the flags according to the result of the comparison.

As a note aside, there are CP, CPE, and CPO instructions for "call when positive, parity even, parity odd". This kind of high density in the "CP" realm may well have triggered a desire to search for a different synonym.

Zilog did considerably decompressed mnemonics for its upwards compatible Z80 processor (where most of the data transfer stuff ran through LD) even though TDL assembly mnemonics designed an Intel-style mapping of the Z80 machine code.

"Load" and "store" were actually also in use early on but more used for indicating memory->register and register->memory transfers, respectively. So instructions between registers were looking for alternative names early on.

The strong move/copy distinction made it into computer science later than assembly language, with the UNIX cp/mv instructions for entire files and with the copy/move/cut/paste idioms from early graphical user interfaces.

0
4

At first glance it just seems a matter of taste.

The question actually starts off with an incorrect presumption: "The" "processor" instruction isn't called MOV(e), it's on some instruction sets where it was called move, on others there is load, store, and transfer.

Having grown up with 6502, I totally feel that "load" for load register from memory vs. "store" to store register into memory vs. "transfer" between registers is the best way to put it. Looking at the PDP-8 instruction set, apart from the odd fact that it has no no "load" at all (you always use TAD, add), it had "store" and "transfer" (though no other general register to transfer to).

"Register transfer" is a well understood concept, and usually thought different from "load" and "store" from and to memory, as the external address / data bus is not involved in the transfers.

But now setting my quaint taste aside, I can also see the rationale for a single op-code mnemonic "MOV" (copy or transfer) because the source and destination are simply thought to be parameters, which is just an extension of the "addressing modes" (immediate, absolute/direct, indirect, indexed ...) there already are. Just include the registers into the domain of source and destinations, and hence a single "move" opcode is elegant, it's parameter polymorphic in what it does exactly.

If you continue thinking along those lines, understanding that "load" and "store" and "transfer" had already been used and have specific meanings, you'll begin to appreciate that for the abstract generalization of these opcodes, a new word had to be found.

The word "copy" (vs. move) may be known from the file system world, but copy is too specific because it implies that after the operation you will have 2 copies of the value, and that might not even always be true. For example, there are registers that clear themselves once they have been read (e.g., in memory-mapped I/O chips as were common in the 6502 world). So, the closest common English word to transfer is move.

I believe thinking that way it all makes a lot of sense.

Now you can wonder why they didn't also rename the "jump" instruction into "move" source to IP?

2
  • 2
    Don't forget that the PDP-8 had DCA (Deposit and Clear Accumulator) as a complementary instruction to the TAD. So it still required just two instructions to store the ACC in memory and load the ACC with a new value. Commented Dec 8, 2019 at 18:10
  • 2
    On ARM, you really can mov pc, r0 because PC is one of the 16 architectural registers that normal integer instructions can read/write. But there are dedicated opcodes for relative conditional branching, of course. Still, your everything-is-a-MOV idea can be taken further; no reason an asm syntax for a 3-operand RISC couldn't look like mov $t0, $t1 & $t2 instead of and $t0, $t1, $t2 (so the opcode is determined by a C-like operator between register names). Well, no reason except sanity and what everyone is used to! Commented Dec 8, 2019 at 21:54
3

In many machines, there are three primary forms of operation that cause something to hold a copy of something else:

  1. Causing a register to hold a copy of something in memory, called "loading".
  2. Causing memory to hold a copy of something in a register, called "storing".
  3. Causing one register to hold a copy of another, called ... ?

All three operations involve copying something. If one recognizes that the first two operands move something to a new location but leave behind a copy that may or may not be useful, then describing the third operation as "Move a value from one register to another, leaving a copy behind" would fit that pattern.

Note that in terms of semantic usage, code may sometimes want to make a backup copy of the value in a register but remain focused on the primary copy, but there's generally no need to have instruction sets worry about whether purpose of an operation is to have two copies of a value, as opposed to having the value available in a new place, while a useless copy is left behind.

3
  • You forgot "causing memory to hold a copy of something in memory, called … ?" :-) Let's hear it for orthogonal ISAs!
    – dave
    Commented Dec 7, 2019 at 1:20
  • 2
    @another-dave: Many machines have separate actions for loading and storing data from/to memory, and don't have direct memory-to-memory transfers. On orthogonal machines, either copy or move would make sense.
    – supercat
    Commented Dec 7, 2019 at 1:55
  • The 65816 has memory-to-memory transfers, via the block move instruction, and the ISA is not remotely orthogonal. So I wouldn't say the two things were necessarily related.
    – fadden
    Commented Dec 7, 2019 at 15:39
3

It is important to notice that the MOV instruction isn't actually a single one : it actually corresponds to different opcodes according to what you're handling and which addressing mode you follow.

On the most rudimentary processors, if you can almost always read/store values from/to memory, you're very often unable to perform direct transfers from a register to another one, especially because these registers are meant to retain the read value to store it again elsewhere. And because of this same reason, you're almost never able to directly move/copy a value from an address to another one in a single operation (requires two distinct bus transactions with value retainment in between).

On 6809 processors, we had:

LDx : Load - Load register "x" with a value from memory (even immediate) ;
STx : Store - Store register "x"'s content in memory ;
TFR x,y : Transfer - Copy content of register x into register y ;
EXG x,y : Exchange - Swap content of register x and y.

This makes senses but all combinations are available, and it remains consistant as long as instructions set and addressing modes are orthogonal enough. When there's too many exceptions to this schema, all these operations are considered as moves in a global way. Thus the assembler mnemonic MOV, which then recognizes what's to be done by looking at its operands.

But this has never been a move by opposition with a copy.

4
  • 1
    How did the 6809 perform the exchange? Was there just another register involved that they just didn't make accessible to general use? Or some latch activated by CLK derivatives? Commented Dec 8, 2019 at 12:21
  • I can't really tell since I never had access to internal documentation, lower than machine language. I'm not aware of any bus transaction to perform this (but I should check again on a genuine Motorola physical 6809). What I can tell is that it requires 8 cycles to complete, which is as much as MUL (tiply). I tended first for successive XOR, but internal general-purpose registers or some latch works are distinct possibilities too.
    – Obsidian
    Commented Dec 8, 2019 at 14:21
  • 1
    @GuntherSchadow: on x86, xchg reg,reg typically uses a "private" register only accessible by microcode. Or on some modern AMD CPUs, register renaming tricks so it only needs 2 uops. See Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures?. I'd assume on an old microcoded CPU there would be 2 internal places to stash things so it could do that and then copy them back to opposite registers. Commented Dec 8, 2019 at 22:05
  • 1
    Whether 'MOV' is a single opcode or not depends on what instruction set architecture you're talking about. On PDP-11, for example, there is exactly one MOV (and one MOVB) that applies to all addressing modes. On PDP-10, for counter example, there are many 'move' instructions, but they have different mnemonics and thus any given 'move' is still exactly one opcode. What ISA are you talking about in this answer?
    – dave
    Commented Dec 12, 2019 at 3:43

You must log in to answer this question.

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