📜  AVR微控制器中的CALL指令和堆栈

📅  最后修改于: 2021-08-27 05:03:42             🧑  作者: Mango

CALL是用于调用特定子例程的控制传递指令。子例程是需要经常执行的指令块。

在AVR中,呼叫子例程有4条指令,如下所示。

  1. CALL(调用子例程)
  2. RCALL(相对调用子例程)
  3. ICALL(对Z的间接调用)
  4. EICALL(扩展到Z的间接调用)

称呼 :
在此4字节指令中,与JMP指令一样,10位用于操作码,其他22位用于目标子例程的地址。在这种情况下,用于AVR的4M地址空间为000000- $ 3FFFFF,它可用于调用给定地址范围内的子例程。

为了确保AVR知道在执行子例程后返回的位置,微控制器会自动将指令的地址保存在堆栈中CALL指令的下方。完成子例程的执行后,RET指令将控制权转移回调用者。因此,每个子例程的末尾都有一个RET指令。

堆 :
堆栈是CPU RAM中临时存储信息的部分。 CPU仅需要有限数量的寄存器,因此需要此存储。用于访问堆栈的寄存器称为堆栈指针(SP)寄存器。
在I / O存储器空间中,有两个寄存器,分别称为SPL(SP的低字节)和SPH(SPB的高字节)。
SP)。 SP由这两个寄存器实现。

在具有超过256字节内存的AVR中,有两个8位寄存器。另一方面,如果内存小于256字节,则SP仅由SPL组成,因为8位寄存器只能寻址256字节的内存。

将CPU信息存储在堆栈上的操作称为PUSH操作,将堆栈内容加载回CPU的操作称为POP操作。

推入堆栈:
堆栈指针(SP)指向堆栈的顶部。当我们将数据压入堆栈时,数据将保存到SP指向的位置,并且SP减1。

要将寄存器压入堆栈,我们使用PUSH指令。

PUSH  Rr; 
Rr can be any general-purpose register (R0 - R31)

从堆栈中弹出:
将堆栈的内容弹出回寄存器是推入的相反函数。当执行POP指令时,SP递增1,并且堆栈的顶部位置被复制回寄存器。这意味着堆栈是LIFO(后进先出)。

要从堆栈中检索数据,我们使用POP指令。

POP  Rr; 
Rr can be any general-purpose register (R0 - R31)

初始化堆栈指针:
不同的AVR具有不同数量的RAM。在AVR汇编程序中,RAMEND指定最后一个RAM单元的地址。因此,如果我们要初始化SP以使其指向最后的内存位置,则可以简单地将RAMEND加载到SP中。注意,SP由2个寄存器SPH和SPL组成。因此,我们将RAMEND的高字节加载到SPH中,并将RAMEND的低字节加载到SPL中。

CALL指令,RET指令和堆栈的作用:
当执行CALL指令时,CALL指令下方的指令地址被压入堆栈。当该子例程的执行完成并且执行了RET时,CALL指令下面的指令的地址被加载到程序计数器中并被执行。