📜  嵌入式系统-说明

📅  最后修改于: 2021-01-07 05:48:38             🧑  作者: Mango


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

循环和跳转指令

循环进入8051

重复执行一系列指令称为循环。指令DJNZ reg,label用于执行循环操作。在该指令中,寄存器减1;否则,寄存器减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)

8051的缺点-带有DJNZ Reg标签指令的循环动作仅限于256次迭代。如果不执行条件跳转,则执行跳转之后的指令。

循环内循环

当我们在另一个循环中使用一个循环时,它称为嵌套循环。当最大计数限制为256时,将使用两个寄存器来保存计数。因此,我们使用此方法将操作重复的次数大于256。

写一个程序到-

  • 将值55H加载到累加器中。
  • 补充ACC 700次。

解决方案-由于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中使用的条件跳转-

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(如果A = 0,则跳转) -在该指令中,检查累加器的内容。如果为零,则8051跳至目标地址。 JZ指令只能用于累加器,不适用于任何其他寄存器。

  • JNZ(如果A不等于0,则跳转) -在此指令中,累加器的内容被检查为非零。如果不为零,则8051跳至目标地址。

  • JNC(如果没有进位,则跳转,如果CY = 0,则跳转) -标志(或PSW)寄存器中的进位标志位用于决定是否跳转“ JNC标签”。 CPU查看进位标志以查看是否将其抬高(CY = 1)。如果未升高,则CPU开始从标签的地址获取并执行指令。如果CY = 1,它将不会跳转,但将执行JNC下面的下一条指令。

  • JC(如果进位,则跳转;如果CY = 1,则跳转) -如果CY = 1,则跳转至目标地址。

  • JB(如果位高则跳转)

  • JNB(如果位低则跳转)

–必须注意,所有条件跳转都是短跳转,即目标地址必须在程序计数器内容的–128至+127字节之内。

无条件跳转指令

8051有两个无条件跳转-

  • LJMP(跳远) -LJMP是3字节指令,其中第一个字节代表操作码,第二个和第三个字节代表目标位置的16位地址。 2字节的目标地址允许从0000跳转到FFFFH的任何存储位置。

  • SJMP(短跳转) -这是一个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字节范围内。