嵌入式系统 - 指令

  • 简述

    除非执行控制转移指令,否则程序流程以顺序方式进行,从一条指令到下一条指令。汇编语言中的各种控制转移指令包括条件或无条件跳转和调用指令。
  • 循环和跳转指令

    在 8051 中循环

    将一系列指令重复一定次数称为 循环. 一条指令DJNZ reg, label用于执行循环操作。在这条指令中,一个寄存器减1;如果不为零,则 8051 跳转到标签所指的目标地址。
    在循环开始之前,寄存器加载了重复次数的计数器。在这条指令中,寄存器递减和跳转的决定合并为一条指令。寄存器可以是 R0–R7 中的任何一个。计数器也可以是 RAM 位置。

    例子

    用重复加法的方法将25乘以10。
    解决方案− 乘法可以通过重复添加被乘数来实现,次数与乘数相同。例如,
    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 次迭代。如果不进行条件跳转,则执行跳转后的指令。

    在循环内循环

    当我们在另一个循环中使用一个循环时,它被称为 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
    
  • 其他条件跳转

    下表列出了 8051 中使用的条件跳转 -
    操作说明 动作
    JZ 如果 A = 0 则跳转
    JNZ 如果 A ≠ 0 则跳转
    DJNZ 如果寄存器 ≠ 0,则递减和跳转
    CJNE A,data 如果 A ≠ data 则跳转
    CJNE reg, #data 如果 字节≠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)
    注意 − 必须注意,所有条件跳转都是短跳转,即目标地址必须在程序计数器内容的–128 至+127 字节范围内。
  • 无条件跳转指令

    8051 中有两个无条件跳转 -
    • LJMP (long jump)− LJMP 为 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节表示目标位置的 16 位地址。2 字节的目标地址允许跳转到从 0000 到 FFFFH 的任何内存位置。
    • SJMP (short jump)− 它是一条 2 字节指令,其中第一个字节是操作码,第二个字节是目标位置的相对地址。相对地址范围从00H到FFH,分为正向跳转和反向跳转;也就是说,在相对于当前 PC(程序计数器)地址的 –128 到 +127 字节内存内。在前向跳转的情况下,目标地址可以在距离当前 PC 127 字节的空间内。在向后跳转的情况下,目标地址可以在距当前 PC 的 –128 字节以内。
  • 计算短跳转地址

    所有条件跳转(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
    

    向后跳转目标地址计算

    在向前跳转的情况下,位移值为 0 到 127 之间的正数(十六进制为 00 到 7F)。但是,对于向后跳转,位移是 0 到 –128 的负值。
  • 调用说明

    CALL 用于调用子程序或方法。子程序用于执行需要频繁执行的操作或任务。这使得程序更加结构化并节省内存空间。有两条指令 - LCALL 和 ACALL。

    LCALL(长调用)

    LCALL 是一条 3 字节指令,其中第一个字节表示操作码,第二个和第三个字节用于提供目标子程序的地址。LCALL 可用于调用在 8051 的 64K 字节地址空间内可用的子程序。
    为了在被调用的子程序执行后成功返回到该点,CPU 将指令的地址保存在堆栈中 LCALL 的正下方。因此,当调用子程序时,控制权转移到该子程序,处理器将 PC(程序计数器)保存在堆栈中并开始从新位置获取指令。RET(返回)指令在子程序执行完毕后将控制权移交给调用者。每个子程序都使用 RET 作为最后一条指令。

    ACALL(绝对调用)

    ACALL 是 2 字节指令,而 LCALL 是 3 字节。子程序的目标地址必须在 2K 字节以内,因为这 2 个字节中只有 11 位用于地址。ACALL 和LCALL 的区别在于LCALL 的目标地址可以在8051 64K 字节地址空间内的任何位置,而CALL 的目标地址在2K 字节范围内。