一、压栈和出栈

通常会在 A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。因此必须在跳到 B 函数之前将当前处理器状态保存起来(保存 R0~R15 寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复 R0~R15 即可。

lua怎么实现堆栈 lr堆栈怎么用_寄存器

PUSH {R4,LR}           // 将通用寄存器 R4、LR 入栈
POP {R4,PC}            // 先入后出,将栈中的数据弹出到通用寄存器 R4 及 PC 中

对于不同处理器来说,栈的增长方式有向上增长和向下增长,我们这里重点关注向下增长的堆栈方式:

lua怎么实现堆栈 lr堆栈怎么用_lua怎么实现堆栈_02


二、跳转指令

lua怎么实现堆栈 lr堆栈怎么用_嵌入式_03


三、连接寄存器 LR(R14)

连接寄存器 LR 常用于函数调用和产生中断时,它们的区别是:

1、函数调用

bl 跳转时,会在寄存器 LR(R14)中保存 pc-4 值,即 bl 跳转指令的下一条指令地址,所以返回时只要 MOV pc,lr。

MOV PC, LR      // 此时 LR 中保存的值是 pc-4,寄存器 LR 中的值赋值给 PC,实现跳转

2、中断

(1)中断发生时,将 lr 入栈,lr 保存的是 pc 的值,即 pc = 当前执行指令 + 8

(2)在中断返回前 ,对 lr 进行处理,pc = lr-4,即 pc 指向之前被清空的已译码但没被执行的指令的地址

(3)然后清空流水线,返回中断发生处开始向下接着执行。

(4)重新对丢弃的前一次已译码指令取指并译码执行。

PUSH {LR}            // 在 IRQ 中断入口将 LR 寄存器压栈
POP {LR}             // 中断返回前,出栈
subs pc, lr, #4      // 将上面压栈的 LR-4 寄存器数据出栈给 pc 寄存器,因为是 3 级流水线

四、程序计数器 pc(R15)

pc = 当前执行指令地址 + 8,中断发生时保存在 lr 中的是 pc 值,即 pc 指向正在取指的地址。

lua怎么实现堆栈 lr堆栈怎么用_linux_04


为什么 pc = 当前执行指令+8 ?

【答】:第一条指令取指完成后,pc 就指向了第二条指令,此时 pc=pc+4;当第一条指令执行时,此时 pc =pc+8,每次该指令执行时,其实这时的 pc 值是 pc= pc+8。

五、程序状态寄存器 CPSR

CPSR:包含了条件标志位、中断使能位、当前处理器模式标志等一些状态位以及一些控制位。
SPSR:CPSR 的备份,因此 SPSR 和 CPSR 的寄存器结构相同。

CPSR 常用于切换处理器模式,CPSR 寄存器的 bit[4:0] 位是处理器模式控制位:

lua怎么实现堆栈 lr堆栈怎么用_嵌入式_05