Move Instructions (Microcontrollers)

Behold the humble move instructions, for they labor to carry the data for the most elegant instructions. You might get excited when you find that this computer has a fairly fancy instruction like multiply, or you might be disappointed that it does not have floating-point instructions like the ones most big machines sport. Studies have shown that, depending on the kind of application program examined, between 25 and 40% of the instructions were move instructions, while only 0.1% of the instructions were multiplies. As you begin to understand computing, you will learn to highly regard these humble move instructions and to use them well.
Move instructions essentially move one or two bytes from memory to a register (or vice versa) or between registers or memory locations. The two aspects of these instructions that give most readers some problems are the setting of condition codes and the allowable addressing modes. We shall take some care with the setting of condition codes in this topic and the allowable addressing modes in the next topic.
The two simplest instructions from the move class are the load and store instructions. These have already been examined for accumulators A, B, and D; they also may be used with index registers like X. For example, in the load instruction
LDX 2062
the high byte of X is taken from location 2062 while the low byte of X is taken from location 2063. An exactly parallel situation holds for the store instruction
STX 2337
where the high byte of X is put into location 2337 while the low byte of X is put into location 2338. In addition to X, there are load and store instructions for index register Y and stack pointer S. They work exactly as described for D.
The TST and CLR instructions are two more examples in the move class of instructions of the 6812. The clear instruction CLR is used to initialize the accumulators or memory locations with the value zero. As such, CLRA can replace instructions such as LDAA #0 in the sequence in Figure 2.1. Further, the two instructions in Figure 2.1 can be replaced by the single instruction CLR 2090.
 A Program Segment to Clear a Byte
Figure 2.1. A Program Segment to Clear a Byte
Table 2.1. Move Instructions Using an Effective Address
Move Instructions Using an Effective Address
Notice that although CLRA and LDAA #0 make the same move, CLRA clears C, whereas LDAA #0 does not affect C. Your program may need to use C later. The test instruction TST, sometimes called a “half a load ” instruction, adjusts the N and Z bits in the condition code register exactly as a load instruction does but without actually loading the byte into an accumulator. The versatile “load effective address” instructions, LEAX, LEAY, and LEAS, load one of the index registers or stack pointer with the effective address computed in an indirect index address calculation, which will be discussed in topic 3. These instructions do not affect the condition code register bits.
Table 2.1 lists the move instructions that use addressing modes. The expressions such as (E) -> A; accurately describe the instruction’s principle effect. E is the effective address, (E) is the word in memory at location E, A is accumulator A, and -> is a data transfer, so (E) -> A; means that the word in memory at the location determined by the instruction’s effective address is put into accumulator A. The CPU12RG/D manual Instruction Set Summary further gives the opcode bytes, allowable addressing modes for each instruction, and condition code modifications that result from executing these instructions. These same conventions are used with the tables that follow in this topic.
Table 2.2 lists move instructions that push on or pull from the stack. The stack pointed to by register SP is called the hardware stack. A program can have other stacks as well. A stack is an abstraction of a stack of letters on your desk. Received letters are put on top of the stack; when read, they are removed from the top of the stack.
In the computer, letters become bytes and the memory that stores the stack becomes a buffer with a stack pointer as follows. One decides to put this buffer, say, from $b80 to $bff. See Figure 2.2. The amount of storage allocated to the buffer should be the worst case number of bytes saved on the stack. Usually, we allow a little extra to prevent a stack overflow. SP points to the top byte that is on the stack. The SP register is generally initialized once to the high end of the buffer, at the beginning of the program.
A Stack
Figure 22. A Stack
and is thereafter adjusted only by push and pull instructions and, perhaps, the LEAS instruction to move it. For example, at the beginning of the program, the instruction LDS #$c00 initializes the stack so that the first push is into location $bff.
If a byte is pushed onto the stack, SP is decremented by 1, and a byte, from one of the 8-bit registers, is put into location (SP). If one byte is removed or pulled from the stack, the byte is transferred to one of the 8-bit registers, and SP is incremented by 1. If two bytes are pushed onto the stack, SP is decremented by 2, and two bytes, from one of the 16-bit registers, are put into location (SP) and (SP+1). If two bytes are pulled from the stack, two bytes from location (SP) and (SP+1) are put into one of the 16-bit registers and SP is incremented by 2. Any of the registers, except SP, may be pushed or pulled from the stack for which SP is the stack pointer. PSHB will push B onto the stack, PULD will pull two words from the stack, putting the combined word in accumulator D. The order for 16-bit words is always that the low byte is pushed before the high byte and the high byte pulled before low byte.
The stack will later be used for saving and restoring the program counter when executing a subroutine and saving and restoring all the registers when executing an interrupt. It will later also be used to store procedure arguments and local variables.
The hardware stack and the stack pointer SP must be used with some care in computers like the 6812. There may be a temptation to use it as an index register, to move il around to different data locations. This is very dangerous. Interrupts, which may occur randomly, save data on the hardware stack, and programs used to aid in the testing and debugging of your program generally use interrupts. Such a program may be very
Table 22. Stack Move Instructions
Stack Move Instructions
Table 23. Special Move Instructions
Special Move Instructions
difficult to test and debug because some data in your program may be overwritten in your attempt to test and debug it. On the other hand, this same stack is the best place to save data used by a subroutine, which is not used by other subroutines, as we explain later. Incidentally, the word “pop” is used instead of “pull” in many text topics.
The transfer and exchange instructions in Table 2.3, TFR and EXG, allow the transfer of register Rl to R2 or the exchange of Rl and R2, respectively, where RJ and R2 are any pair of 8- or 16-bit registers. You can move data from an 8-bit register to a 16-bit one or vice versa. As an example, the instruction TFR D, Y puts the contents of D into Y, and EXG D, X exchanged the contents of accumulator D and index register X.
The TFR or EXG machine code consists of an operation code byte and a post byte. The opcode byte is obtained from the CPU12RG/D manual Instruction Set Summary, and the post byte (see Table 3 therein) can be obtained as follows: The source is the left nibble and the destination is the right nibble; their values are: 0, accumulator A; I, accumulator B; 2, condition code register; 4, accumulator D; 5, index register X; 6, index register Y; 7, stack pointer SP. As an example, the instruction TFR D, Y is stored in memory as the two bytes:
The post byte’s left four bits indicate the source of the transfer, which is D, and the right four bits indicate the destination of the transfer, which is Y. When transferring from an 8-bit to a 16-bit register, the sign bit is extended so that positive numbers remain positive and negative numbers remain negative; the sign extend mnemonic SEX can be used as an alternative to the TFR mnemonic in these cases. Figure 2.3a illustrates sign extension when transferring the data from an 8-bit register, like A, shown on the top, into a 16-bit register like X, shown on the bottom. The low-order byte is moved bit-by-bit from the flip-flops in the 8-bit to the flip-flops in the 16-bit register. The high-order byte’s flip-flops are loaded with the low-order byte’s sign bit. The EXG instruction similarly permits exchanging the contents of two registers, and the post byte coding is the same, but when moving from an 8-bit to a 16-bit register, instead of
Transfers between Registers
Figure 23. Transfers between Registers
extending the sign, it merely fills the high byte with zeros (see Figure 2.3b). Exchanges are accomplished by means of a hidden register (see Figure 2.3c). The instruction EXG A, B first copies register B into the hidden register. Then it copies A into B. Then it copies the hidden register into A. Such hidden registers are not in the description of the 6812′s register set (Figure 1.2) but are additional registers within the data operator.
The MOVB and MOVW instructions implement a constant-to-memory or a memory-to-memory move. The instruction below puts the constant $04 into location $803.
MOVB #4,$803
This instruction is coded as shown below; the prefix byte $18 precedes the opcode byte SOB. See the CPU12RG/D manual. In effect, the opcode is a 16-bit opcode $180B. The prefix byte $18 is used in the 6812 to encode a number of instructions. It is as if, when the 6812 fetches the prefix $18, it thinks: Oh, this is one of the 2-byte op codes, so fetch another byte to get the complete opcode. The third byte is the immediate operand $04, and the last two bytes are the direct address $803.
This move instruction moves the immediate operand $04 into a hidden register and then moves the data from the hidden register into location $803. From the CPU12RG/D manual. we observe that its execution takes four memory cycles. The alternative to this instruction is the program segment:
which is encoded as follows:
This pair of instructions takes the same number of bytes as the MOVB instruction. Further, the LDAA instruction executes in one memory cycle, and the STAA instruction executes in three memory cycles. The MOVB instruction is neither statically nor dynamically more efficient than the pair of instructions, LDAA and STAA. However, it is clearer. We recommend using the MOVB instruction to write a constant into memory.
But if the same constant is written into two places in memory, as in
then a program sequence using the MOVB instruction is less efficient:
This program sequence takes ten bytes and executes in eight memory cycles, while the program sequence above it takes eight bytes and executes in seven memory cycles.
The MOVB instruction also moves data from any memory location to any memory location. MOVB $801, $803 moves a byte from location $801 to location $803. The MOVW instruction similarly moves 16 bits of data.
Missing move instructions can often be implemented by combinations of other move instructions. Because there is no instruction to “load” the condition code register, it can be loaded through accumulator A or B with the TFR instruction. For example, to put 3 into the condition code, execute the code shown in Figure 2.4.
Program Segment to Initialize the Condition Code Register
Figure 2.4. Program Segment to Initialize the Condition Code Register

Next post:

Previous post: