Embedded Systems 简明教程
Embedded Systems - Instructions
程序流程按顺序进行,从一条指令到下一条指令,除非执行了控制传递指令。汇编语言中的各种类型的控制传递指令包括条件或无条件跳转和调用指令。
The flow of program proceeds in a sequential manner, from one instruction to the next instruction, unless a control transfer instruction is executed. The various types of control transfer instruction in assembly language include conditional or unconditional jumps and call instructions.
Loop and Jump Instructions
Looping in the 8051
重复执行一系列指令的特定次数称为 loop 。指令 DJNZ reg, label 用于执行循环操作。在此指令中,寄存器减 1;如果不为零,则 8051 跳到由标签所引用的目标地址。
Repeating a sequence of instructions a certain number of times is called a loop. An instruction DJNZ reg, label is used to perform a Loop operation. In this instruction, a register is decremented by 1; if it is not zero, then 8051 jumps to the target address referred to by the label.
在循环开始前,用重复次数的计数器加载寄存器。在此指令中,寄存器减量和跳跃决策合并为一条指令。寄存器可以是 R0-R7 中的任何一个。计数器也可以是 RAM 位置。
The register is loaded with the counter for the number of repetitions prior to the start of the loop. In this instruction, both the registers decrement and the decision to jump are combined into a single instruction. The registers can be any of R0–R7. The counter can also be a RAM location.
Example
Multiply 25 by 10 using the technique of repeated addition.
Multiply 25 by 10 using the technique of repeated addition.
Solution − 乘法可以通过多次相加乘数来实现,次数与乘数相同。例如,
Solution − Multiplication can be achieved by adding the multiplicand repeatedly, as many times as the multiplier. For example,
25 * 10 = 250(FAH)
25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 = 250
MOV A,#0 ;A = 0,clean ACC
MOV R2,#10 ; the multiplier is replaced in R2
Add A,#25 ;add the multiplicand to the ACC
AGAIN:DJNZ R2,
AGAIN:repeat until R2 = 0 (10 times)
MOV R5 , A ;save A in R5 ;R5 (FAH)
Drawback in 8051 − 使用指令 DJNZ Reg label 的循环操作仅限于 256 次迭代。如果未执行条件跳转,则执行跳转后的指令。
Drawback in 8051 − Looping action with the instruction DJNZ Reg label is limited to 256 iterations only. If a conditional jump is not taken, then the instruction following the jump is executed.
Looping inside a Loop
当我们在另一个循环内使用循环时,它被称为 nested loop 。当最大计数限制为 256 时,使用两个寄存器来保存计数。因此,我们使用这种方法来重复执行操作超过 256 次。
When we use a loop inside another loop, it is called a nested loop. Two registers are used to hold the count when the maximum count is limited to 256. So we use this method to repeat the action more times than 256.
Example
编写一个程序 −
Write a program to −
-
Load the accumulator with the value 55H.
-
Complement the ACC 700 times.
Solution − 由于 700 大于 255(任何寄存器的最大容量),因此使用两个寄存器来保存计数。以下代码展示如何对 R2 和 R3 这两个寄存器进行计数。
Solution − Since 700 is greater than 255 (the maximum capacity of any register), two registers are used to hold the count. The following code shows how to use two registers, R2 and R3, for the count.
MOV A,#55H ;A = 55H
NEXT: MOV R3,#10 ;R3 the outer loop counter
AGAIN:MOV R2,#70 ;R2 the inner loop counter
CPL A ;complement
Other Conditional Jumps
下表列出了 8051 中使用的条件跳转 −
The following table lists the conditional jumps used in 8051 −
Instruction |
Action |
JZ |
Jump if A = 0 |
JNZ |
Jump if A ≠ 0 |
DJNZ |
Decrement and Jump if register ≠ 0 |
CJNE A, data |
Jump if A ≠ data |
CJNE reg, #data |
Jump if byte ≠ data |
JC |
Jump if CY = 1 |
JNC |
Jump if CY ≠ 1 |
JB |
Jump if bit = 1 |
JNB |
Jump if bit = 0 |
JBC |
Jump if bit = 1 and clear bit |
-
JZ (jump if A = 0) − In this instruction, the content of the accumulator is checked. If it is zero, then the 8051 jumps to the target address. JZ instruction can be used only for the accumulator, it does not apply to any other register.
-
JNZ (jump if A is not equal to 0) − In this instruction, the content of the accumulator is checked to be non-zero. If it is not zero, then the 8051 jumps to the target address.
-
JNC (Jump if no carry, jumps if CY = 0) − The Carry flag bit in the flag (or PSW) register is used to make the decision whether to jump or not "JNC label". The CPU looks at the carry flag to see if it is raised (CY = 1). If it is not raised, then the CPU starts to fetch and execute instructions from the address of the label. If CY = 1, it will not jump but will execute the next instruction below JNC.
-
JC (Jump if carry, jumps if CY = 1) − If CY = 1, it jumps to the target address.
-
JB (jump if bit is high)
-
JNB (jump if bit is low)
Note − 必须注意,所有条件跳转都是短跳转,即目标地址必须在程序计数器内容的 -128 到 +127 字节内。
Note − It must be noted that all conditional jumps are short jumps, i.e., the address of the target must be within –128 to +127 bytes of the contents of the program counter.
Unconditional Jump Instructions
8051 中有两个无条件跳转 −
There are two unconditional jumps in 8051 −
-
LJMP (long jump) − LJMP is 3-byte instruction in which the first byte represents opcode, and the second and third bytes represent the 16-bit address of the target location. The 2-byte target address is to allow a jump to any memory location from 0000 to FFFFH.
-
SJMP (short jump) − It is a 2-byte instruction where the first byte is the opcode and the second byte is the relative address of the target location. The relative address ranges from 00H to FFH which is divided into forward and backward jumps; that is, within –128 to +127 bytes of memory relative to the address of the current PC (program counter). In case of forward jump, the target address can be within a space of 127 bytes from the current PC. In case of backward jump, the target address can be within –128 bytes from the current PC.
Calculating the Short Jump Address
所有条件跳转(JNC、JZ 和 DJNZ)都是短跳转,因为它们是 2 字节指令。在这些指令中,第一个字节表示操作码,第二个字节表示相对地址。目标地址始终相对于程序计数器的值。要计算目标地址,将第二个字节添加到紧跟在跳转之下的指令的 PC。看看下面给出的程序 −
All conditional jumps (JNC, JZ, and DJNZ) are short jumps because they are 2-byte instructions. In these instructions, the first byte represents opcode and the second byte represents the relative address. The target address is always relative to the value of the program counter. To calculate the target address, the second byte is added to the PC of the instruction immediately below the jump. Take a look at the program given below −
Line PC Op-code Mnemonic Operand
1 0000 ORG 0000
2 0000 7800 MOV R0,#003
3 0002 7455 MOV A,#55H0
4 0004 6003 JZ NEXT
5 0006 08 INC R0
6 0007 04 AGAIN: INC A
7 0008 04 INC A
8 0009 2477 NEXT: ADD A, #77h
9 000B 5005 JNC OVER
10 000D E4 CLR A
11 000E F8 MOV R0, A
12 000F F9 MOV R1, A
13 0010 FA MOV R2, A
14 0011 FB MOV R3, A
15 0012 2B OVER: ADD A, R3
16 0013 50F2 JNC AGAIN
17 0015 80FE HERE: SJMP HERE
18 0017 END
CALL Instructions
CALL 用于调用子例程或方法。子例程用于执行需要频繁执行的操作或任务。这使程序更具结构性并节省了内存空间。有两个指令 − LCALL 和 ACALL。
CALL is used to call a subroutine or method. Subroutines are used to perform operations or tasks that need to be performed frequently. This makes a program more structured and saves memory space. There are two instructions − LCALL and ACALL.
LCALL (Long Call)
LCALL 是 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节用于提供目标子例程的地址。LCALL 可用于调用在 8051 的 64K 字节地址空间内可用的子例程。
LCALL is a 3-byte instruction where the first byte represents the opcode and the second and third bytes are used to provide the address of the target subroutine. LCALL can be used to call subroutines which are available within the 64K-byte address space of the 8051.
为了在调用子例程执行之后成功返回到该点,CPU 将紧跟在 LCALL 下面的指令地址保存在堆栈上。因此,当调用子例程时,控制权将被转移到该子例程,并且处理器将 PC(程序计数器)保存在堆栈上并开始从新位置获取指令。子例程执行完后,RET(返回)指令将控制权转移回调用者。每个子例程都将 RET 用作最后一条指令。
To make a successful return to the point after execution of the called subroutine, the CPU saves the address of the instruction immediately below the LCALL on the stack. Thus, when a subroutine is called, the control is transferred to that subroutine, and the processor saves the PC (program counter) on the stack and begins to fetch instructions from the new location. The instruction RET (return) transfers the control back to the caller after finishing execution of the subroutine. Every subroutine uses RET as the last instruction.
ACALL (Absolute Call)
ACALL 是一条 2 字节指令,而 LCALL 为 3 字节。子例程的目标地址必须在 2K 字节以内,因为 2 字节中只有 11 位用于地址。ACALL 和 LCALL 间存在差异,因为 LCALL 的目标地址可在 8051 的 64K 字节地址空间中的任何位置,而 CALL 的目标地址则在 2K 字节范围中。
ACALL is a 2-byte instruction, in contrast to LCALL which is 3 bytes. The target address of the subroutine must be within 2K bytes because only 11 bits of the 2 bytes are used for address. The difference between the ACALL and LCALL is that the target address for LCALL can be anywhere within the 64K-bytes address space of the 8051, while the target address of CALL is within a 2K-byte range.