2. The MOVE Instruction Family

The most common instruction in the entire world, is probably the MOVE instruction. It is actually wrongly named as it really does a COPY rather than a MOVE. The format of the MOVE instruction is :

MOVE    source,destination

or :

MOVE.size    source,destination

The data in source is copied to the destination. For example,

MOVE    D0,D1

takes whatever data is in data register 0 (zero) and copies it into data register 1. How much data is moved ? In this case, because no size is specified, the default size is always WORD so a single word of data is moved from D0 to D1. As there is space for 2 words in each of these registers, which word is moved from D0 to which word in D1 ?

All instructions work from the 'lowest' end of the register towards the highest (with the exception of MOVEP - see below). So, in the above example, the lowest 16 bits of D0 are copied to the lowest 16 bits of D1. The data in D0 is not altered in any way whatsoever. The same cannot be said for D1 as the original data in D1 has been replaced - but only the lowest 16 bits. The highest word has not been altered.

If D0 contained $01020304 and D1 contained $11223344 then after the above move, D0 would be unchanged and D1 would contain $11220304. If the size of the instruction had been specified, as follows :

MOVE.B    D0,D1

Then only the lowest byte of D1 would have been altered. In this case D1 would have contained $11223304 after the move. If the size specifier had been 'L' for LONG than the entire 4 bytes in D1 would have been overwritten by the 4 bytes from D0. After a long sized MOVE, both D0 and D1 would contain $01020304.

Because the move takes place into a data register the condition codes are affected. To copy data into an address register use the MOVEA instruction, but always remember that it does not affect the flags in the condition code register.

The changes that will take place every time a data register or memory location is used as the destination for a MOVE are :

The MOVE instruction has many variations, most of them simple and easy to understand. These are :

MOVE as described above.

MOVE CCR - the size is always word although the upper 8 bits are ignored - effectively a byte sized move. The format of the instruction is :

MOVE    source,CCR

Executing this instruction results in the condition codes being set as follows :

All the other bits are simply ignored.

MOVE SR - the size is always word and may not be specified in the instruction. This instruction copied the 16 bits of the condition code register to the destination. The instruction format is :

MOVE    SR,destination

When the instruction has been carried out, the lower 16 bits of the destination contain a copy of the Status Register of the processor. The actual data in the status register is unaffected by the move.

There is a complimentary instruction to move data into the status register which is :

MOVE    source,SR

Which takes the lower 16 bits of the source data and copies it into the status register. The lower 8 bits are used to change the flags in the CCR or Condition Codes Register (See MOVE CCR above). The SR is affected according to the lower 16 bits of the source data as follows :

The other bits are simply ignored. There is a slight problem, the instruction MOVE source,SR must be executed in Privileged mode or it will cause a 'Privilege Violation Exception' which on a normal QL will simply lock it up. (Exceptions are covered later on in the series.)

Warning

Note : on the 68010 and up, the MOVE SR,destination becomes a privileged instruction. There is a new instruction MOVE CCR,destination which allows access to the CCR part of the SR. Programs written for the 68000 and 68008 may require to be re-written with this in mind.

MOVE USP - A long sized instruction which copies data into the User Stack Pointer (USP) also knows as A7. This instruction is also privileged and requires that the system is running in supervisor mode. The format of the instruction is :

MOVE    source,USP MOVE USP,destination

Both source and destination must be an address register. None of the condition codes are affected by this instruction.

Why does this have to be run in supervisor mode ? Well, if not, a privilege violation exception will be generated and these instructions allow the operating system to set the value of a job's stack pointer.

If you remember, there are two A7 registers, one used for supervisor mode and the other for user mode. Only one can be in use at any one time. This instruction allows the supervisor to set the USP without affecting its own version of the A7 register. Not used much, if at all on the QL.

MOVEA - the contents (remember that word !) of the source is moved into an address register. This instruction is either word or long sized and does not affect the condition codes. The format is :

MOVEA.size    source,An

Beware because if you move a word sized source, it will be sign extended to long (bit 15 will be copied into bits 16 to 31) before the data is copied into the address register.

For example :

MOVEA.W    #$0001,A0

This will set A0 to $00000001 after the move. Bit 15 of the data is a zero so this is copied into all the upper 16 bits of A0. The lower 16 bits are simply a direct copy of the data.

MOVEA.W    #$8000,A0

This will set A0 to $FFFF8000 after the move. Bit 15 is a one and this is copied into all the upper 16 bits of A0. The lower 16 are again a copy of the data.

Don't forget about sign extension !

MOVEM - a word or long sized instruction which allows you to copy data to or from a number of registers in a single instruction. The format of the instruction is :

MOVEM    register_list,destination
MOVEM    source,register_list

None of the condition codes are affected by this instruction.

The instruction is most often used to store a number of registers on the stack on entry to a subroutine, and to reinstate the original values on exit from the subroutine. The instruction stores the registers starting with D0, then D1 and so on up to D7, then the address registers are stored in order from A0 to A7 - assuming all registers are specified.

A register list takes the format of a starting register name, a hyphen then a finish register name. Another form is a start register name a slash and another register name. The two formats can be mixed to give almost endless possibilities. The following are all register list examples :

D1-D4
A0-A3
D1/D4-D7
D0-D2/D4/D7/A0-A3/A6

The hyphen means that all registers from the starting one to the finish one (inclusive) will be moved to the destination. The slash signals that there is a 'gap' in the register list. The above examples mean :

D1 and D2 and D3 and D4
A0 and A1 and A2 and A3
D1 and D4 and D5 and D6 and D7
D0 and D1 and D2 and D4 and D7 and A0 and A1 and A2 and A3 and A6.

The list can be specified in any order (unless the assembler rules differently) as each register detected is used to set a single bit in a 16 bit word. This word is used by the processor to determine which of the registers are to be copied.

This instruction will be most often used in its Post decrement and pre-increment forms :

MOVEM.L    D0-D3,-(A7) 
MOVEM.L    (A7)+,D0-D3

MOVEP - Probably the strangest instruction in the 68000 set. This instruction transfers data from a data register to alternating bytes in memory. The data is transferred from the data register starting from the highest 8 bits, then the next 8 bits and so on. This is a word or long sized instruction. The condition code flags are not affected. (I have never used or seen this instruction used on the QL.) The formats are :

MOVEP.size    Dn,displacement(An)
MOVEP.size    displacement(An),Dn

The size is long or word, Dn is any data register, An is any address register and the displacement is added to the address register to get the first address to be filled with data. An example might make things clearer. If we assume that D0 holds $11223344 and A1 holds the address $000200000 then the instruction :

MOVEP.L    D0,0(A1)

Copies the highest byte of D0 ($11) into address $20000, the next highest ($22) into address $20002, the next byte ($33) into address $20004 and finally the lowest byte of D0 ($44) into address $20006. Addresses $20001, $20003 and $20005 are not affected.

Had the displacement and A1 combined created an odd address then the odd addresses would have been filled with data and the even ones would not have been affected.

MOVEQ - This is a very useful instruction and you will see it used on many occasions in QL assembly language programs. It is the 'Move Quick' instruction and is used to quickly move any value between -128 and 127 into any data register. The value is sign extended to 32 bits or long sized and so fills the entire data register. The format is :

MOVEQ    #data,Dn

The flags are affected by this instruction as follows :

Remember, only 8 bit values are allowed and these must be between -128 and 127.

A number of 68000 instructions have this 'quick' mode, but why is it quick ? Let us compare the MOVEQ #0.D0 with its equivalent MOVE.L #0,D0. We simply see two different forms of what is effectively the same instruction, the QL's processor sees things a bit differently, as follows :

First MOVEQ #0,D0 is a 16 bit instruction in memory. MOVE.L #0.D0 is also a 16 bit instruction but it is followed in memory by a long word (32 bit) holding the data, in this case zero. This makes the MOVEQ instruction 3 times smaller than the MOVE.L one. As the processor has less data to fetch from memory, it takes less time to read the instruction and its data, therefore it is quicker. Looking at the 68008 timing chart, it takes the MOVEQ instruction 8 clock cycles to execute and the MOVE.L 24 clock cycles.

And that is about it for the 68008's MOVE instructions. This is probably the instruction with the most variants and as I said before, probably the most used instruction in any program.

2.1. Exercise

1. Write down the correct instruction which will copy 4 bytes of data from address $20000 into data register D7.

2. What is the fastest way to get the 8 bit value of 17 into all 32 bits of register D2 ?

3. What instruction would you use to copy the lowest 16 bits of register D1 into the lowest 16 bits of register D3 ? What happens to the data in D1 after the move and what happens to the data that is currently held in D3 ?

4. How would you place the lowest byte of D1 into a memory location which is 10 bytes further on from the address currently held in A0 ?

5. Why is the MOVE instruction 'wrongly' named ?

6. What does a privileged instruction require before it can be executed ?

7. What happens if a privileged instruction is executed in user mode ?

8. How many data registers does the 68008 have and how many address registers ?

9. What values are set in each of the condition codes wher the instruction MOVEQ #0,D1 is executed ?

10. What values are set if the instruction executed was MOVEA.L #0,A0 ?

2.2. Answers

1. MOVE.L $20000,D7

2. MOVEQ #17,D2 or MOVEQ #$11,D2

3. MOVE.W D1,D3. Nothing happens to the data in D1. The highest word on D3 is not affected but the lower word is overwritten by the lowest word from D1.

4. MOVE.B D1,10(A0) or MOVE.B D1,$0A(A0).

5. The MOVE instruction actually copies data from source to destination, it does not move it in the traditional sense of 'it was over there but it has been moved to over there'.

6. The processor must be in supervisor mode.

7. A privilege exception will be generated (and the QL will probably hang).

8. There are 8 data registers and 9 address registers but only one of the A7 'twins' can be used at a time.

9. The Z flag is set to one and all the rest are reset to zero except the X flag which is unaffected and keeps its previous value.

10. No flags are changed. They all keep their previous values.