2. Data transfer instructions between accumulator A and off-chip RAM
MOVX A,@Ri
MOVX@Ri,A
MOVX A,@DPTR
MOVX @DPTR,A
illustrate:
1) In 51, the only accumulator that can interact with the external RAM is the A accumulator. All data that needs to be sent to the external RAM must be sent through A, and all data that needs to be read from the external RAM must also be read through A. Here we can see the difference between the internal and external RAM. The internal RAM can directly transfer data, but the external RAM cannot. For example, to send a unit in the external RAM (set to the data of the 0100H unit) to another unit (set to the 0200H unit), the content of the 0100H unit must first be read into A, and then sent to the 0200H unit.
2) To read or write external RAM, of course, you must know the address of the RAM. In the last two instructions, the address is directly placed in DPTR. In the first two instructions, since Ri (i.e. R0 or R1) is only an 8-bit register, only the lower 8-bit address is provided. Because sometimes the number of extended external RAM is relatively small, less than or equal to 256, it is enough to provide only 8-bit address.
3) When using, the address to be read or written should first be sent to DPTR or Ri, and then the read or write command is used.
Example: Send the content in the 100H unit in the external RAM to the 200H unit in the external RAM.
MOV DPTR, #0100H
MOVX A, @DPTR
MOV DPTR,#0200H
MOVX @DPTR,A
3. The program memory transfers instructions to accumulator A
MOVC A, @A+DPTR
This instruction is to send the number in ROM to A. This instruction is also called table lookup instruction, which is often used to look up a table that has been prepared in ROM.
illustrate:
1) This instruction introduces a new addressing method: displacement addressing. This instruction is to find data in an address unit of ROM. Obviously, the address of this unit must be known. The address of this unit is determined as follows: there is a number in DPTR and a number in A when executing this instruction. When executing the instruction, add the numbers in A and DPTR to get the address of the unit to be found.
2) The search result is placed in A. Therefore, the value in A may not be the same before and after the execution of this instruction.
Example: There is a number in R0, and you need to use a table lookup method to determine its square value (the value range of this number is 0-5)
MOV DPTR, #TABLE
MOV A, R0
MOVC A, @A+DPTR
.
.
TABLE: DB 0,1,4,9,16,25
Assume that the value in R0 is 2, and is sent to A, and the value in DPTR is TABLE, then the address of the ROM unit finally determined is TABLE+2, that is, the number is taken from this unit, and the number is 4, which is obviously the square of 2. The same can be said for other data.
The real meaning of the label: From this point, we can also see another problem. We use labels to replace specific unit addresses. In fact, the real meaning of the label is the address value. Here it represents the starting position of the data 0, 1, 4, 9, 16, 25 stored in the ROM. In the LCALL DELAY instruction we have learned before, DELAY represents the starting address of the program with DELAY as the label stored in the ROM. In fact, the CPU finds this program through this address.
-------------------------------------------------------------------------------- You can look at the meaning of the labels through the following examples:
MOV DPTR, #100H
-------------------------------------------------- ------------------------------- MOV A, R0
If the value in R0 is 2, the final address is 100H+2, which is 102H, and the value found in unit 102H is 4. Do you understand this?
Why not write the program like this, using labels? Doesn't it just add to the confusion?
If we write a program in this way, we must determine the specific location of this table in the ROM when writing the program. If we want to insert another program before this program after writing the program, the location of this table will change again, and we have to change the sentence ORG 100H. We often need to modify the program, which is very troublesome, so we use labels instead. As long as the program is compiled, the position will change automatically, and we leave this troublesome matter to the computer (referring to the PC).
4. Stack Operations
PUSH direct
POP direct
The first instruction is called push, which is to put the content in direct into the stack, and the second instruction is called pop, which is to put the content in the stack back into direct. The execution process of the push instruction is to first add 1 to the value in SP, then use the value in SP as the address, and put the value in direct into the RAM unit with the value in SP as the address. Example:
MOV SP, #5FH
MOV A, #100
MOV B, #20
PUSH ACC
PUSH B
The execution of the first PUSH ACC instruction is as follows: add 1 to the value in SP, which becomes 60H, and then send the value in A to the 60H unit. Therefore, after executing this instruction, the value of the 60H unit in memory is 100. Similarly, when executing PUSH B, SP+1 is added, which becomes 61H, and then the value in B is sent to the 61H unit. That is, after executing this instruction, the value in the 61H unit becomes 20.
The execution of the POP instruction is as follows: first, the value in SP is used as the address, and the number in this address is sent to the direct following the POP instruction, and then SP is reduced by 1.
Continuing from the previous example:
POP B
POP ACC
The execution process is: use the value in SP (now 61H) as the address, take the value in the 61H unit (now 20), and send it to B, so after executing this instruction, the value in B is 20, then reduce SP by 1, so after this instruction is executed, the value of SP becomes 60H, then execute POP ACC, use the value in SP (60H) as the address, take the number from the address (now 100), and send it to ACC, so after executing this instruction, the value in ACC is 100.
What is the meaning of this? The value in ACC is originally 100, and the value in B is originally 20. Yes, in this example, it does not make sense, but in actual work, other instructions are often executed after PUSH B, and these instructions will change the values in A and B. So at the end of the program, if we want to restore the values in A and B to their original values, then these instructions make sense.
Another question, if I don't use the stack, for example, use MOV 60H, A at the PUSH ACC instruction, use MOV 61H, B at the PUSH B instruction, and then use MOV A, 60H, MOV B, 61H to replace the two POP instructions, isn't it the same? Yes, it is the same in terms of the result, but it is different in terms of the process, PUSH and POP instructions are single-byte, single-cycle instructions, while MOV instructions are double-byte, double-cycle instructions. What's more, the role of the stack is more than that, so there is a stack on general computers, and when we write subroutines and need to save data, we usually don't use the latter method, but use the stack method to achieve it.
Example: Write out the results of the following program:
MOV 30H, #12
MOV 31H, #23
PUSH 30H
PUSH 31H
POP 30H
POP 31H
As a result, the value in 30H becomes 23, and the value in 31H becomes 12. The data is exchanged. From this example, we can see that when using a stack, the order of writing into the stack and the order of writing out of the stack must be opposite to ensure that the data is sent back to the original position, otherwise an error will occur.