Embedded Systems 简明教程
Embedded Systems - Instructions
程序流程按顺序进行,从一条指令到下一条指令,除非执行了控制传递指令。汇编语言中的各种类型的控制传递指令包括条件或无条件跳转和调用指令。
Loop and Jump Instructions
Looping in the 8051
重复执行一系列指令的特定次数称为 loop 。指令 DJNZ reg, label 用于执行循环操作。在此指令中,寄存器减 1;如果不为零,则 8051 跳到由标签所引用的目标地址。
在循环开始前,用重复次数的计数器加载寄存器。在此指令中,寄存器减量和跳跃决策合并为一条指令。寄存器可以是 R0-R7 中的任何一个。计数器也可以是 RAM 位置。
Example
Multiply 25 by 10 using the technique of repeated addition.
Solution − 乘法可以通过多次相加乘数来实现,次数与乘数相同。例如,
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 次迭代。如果未执行条件跳转,则执行跳转后的指令。
Looping inside a Loop
当我们在另一个循环内使用循环时,它被称为 nested loop 。当最大计数限制为 256 时,使用两个寄存器来保存计数。因此,我们使用这种方法来重复执行操作超过 256 次。
Example
编写一个程序 −
-
使用值 55H 加载累加器。
-
对 ACC 补码 700 次。
Solution − 由于 700 大于 255(任何寄存器的最大容量),因此使用两个寄存器来保存计数。以下代码展示如何对 R2 和 R3 这两个寄存器进行计数。
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 中使用的条件跳转 −
Instruction |
Action |
JZ |
如果 A = 0 则跳转 |
JNZ |
如果 A ≠ 0 则跳转 |
DJNZ |
减量并如果寄存器 ≠ 0 则跳转 |
CJNE A, data |
如果 A ≠ 数据则跳转 |
CJNE reg, #data |
如果字节 ≠ 数据则跳转 |
JC |
如果 CY = 1 则跳转 |
JNC |
如果 CY ≠ 1,则跳转 |
JB |
如果位 = 1,则跳转 |
JNB |
如果位 = 0,则跳转 |
JBC |
如果位 = 1,则跳转并清除位 |
-
JZ (jump if A = 0) − 在此指令中,检查累加器的内容。如果为零,则 8051 跳转到目标地址。JZ 指令仅可用于累加器,不适用于任何其他寄存器。
-
JNZ (jump if A is not equal to 0) − 在此指令中,检查累加器的内容是否不为零。如果不为零,则 8051 跳转到目标地址。
-
JNC (Jump if no carry, jumps if CY = 0) − 标志(或 PSW)寄存器中的进位标志位用于做出是否跳转的决定“JNC 标志”。CPU 查看进位标志以了解它是否被置位 (CY = 1)。如果未置位,则 CPU 开始从标签的地址获取和执行指令。如果 CY = 1,则它不会跳转,而是会执行 JNC 下面的下一条指令。
-
JC (Jump if carry, jumps if CY = 1) − 如果 CY = 1,则它跳转到目标地址。
-
JB (jump if bit is high)
-
JNB (jump if bit is low)
Note − 必须注意,所有条件跳转都是短跳转,即目标地址必须在程序计数器内容的 -128 到 +127 字节内。
Unconditional Jump Instructions
8051 中有两个无条件跳转 −
-
LJMP (long jump) − LJMP 是 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节表示目标位置的 16 位地址。2 字节目标地址是为了允许跳转到从 0000 到 FFFFH 的任何内存位置。
-
SJMP (short jump) − 这是一条 2 字节指令,其中第一个字节是操作码,第二个字节是目标位置的相对地址。相对地址范围从 00H 到 FFH,分为正向和反向跳转;也就是说,相对于当前 PC(程序计数器)地址的 -128 到 +127 字节内存内。对于正向跳转,目标地址可以从当前 PC 的 127 字节空间内。对于反向跳转,目标地址可以从当前 PC 的 -128 字节内。
Calculating the Short Jump Address
所有条件跳转(JNC、JZ 和 DJNZ)都是短跳转,因为它们是 2 字节指令。在这些指令中,第一个字节表示操作码,第二个字节表示相对地址。目标地址始终相对于程序计数器的值。要计算目标地址,将第二个字节添加到紧跟在跳转之下的指令的 PC。看看下面给出的程序 −
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。