arm 的pc和lr寄存器

本文深入探讨了ARM处理器如何利用流水线技术提高指令执行速度,包括取指、译码和执行阶段的工作原理。同时,阐述了在遭遇中断时,处理器如何通过保存PC地址并进行中断返回操作,确保程序的正确恢复执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 ARM处理器使用流水线来增加处理器指令流的速度,这样可使几个操作同时进行,并使处理与存储器系统之间的操作更加流畅,连续,能提供0.9MIPS/MHZ的指令执行速度。

    PC代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:1.取指(从存储器装载一条指令);2.译码(识别将要被执行的指令);3.执行(处理指令并将结果写回寄存器)。而R15(PC)总是指向“正在取指”的指令,而不是指向“正在执行”的指令或正在“译码”的指令。一般来说,人们习惯性约定将“正在执行的指令作为参考点”,称之为当前第一条指令,因此PC总是指向第三条指令。当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址加8字节的地址,即:PC值=当前程序执行位置+8;

    ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4(假设在ARM状态下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。
    当突然发生中断的时候,保存的是PC的地址
    这样你就知道了,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq #4。

 

    但是在ADS中PC确实是指向即将执行的指令处,这个是软件处理后的结果,主要是为了用户调试程序方便.

   需要注意的是,当前使用指令STM/STR保存R15时候,保存的可能是当前指令地址值+8字节,也可能保存的是当前的指令地址+12字节.到底是哪种,取决于芯片的具体的设计方式。无论如何,在同一芯片中,要么采用当前的指令地址+8,要么采用当前的指令地址+12。因此对于用户来讲,尽量避免使用STM/STR指令来保存R15的值。但是可以在开始的时候用一段程序对芯片的offset进行测试!

 代码如下:
SUB R1, PC, #4  ;获得下面的存放下面存放STR指令的地址
STR PC,[R0]
LDR R0,[RO]
SUB R0, R0, R1

ARM7中断与PC、LR的问题:

1,假设当前是PC,PC-4,PC-8(三级流水
2,发生IRQ异常,执行保护操作,LR中保存由于FIQ或IRQ占先而没有被执行的指令的地址(即有些资料上把这个地址写成PC或者当前地址,很费解甚至误解)的下一条地址
3,清空流水线
4,进入中断服务程序
5,待流水线填满,执行操作才被重新挂起(解释了ARM7为什么是0.9MIPS)
6,中断返回前,对LR处理,LR=LR-4,指向之前被清空的已译码但没被执行的指令的地址
7,清空流水线,返回
8,重新对丢弃的前一次已译码指令取指
9,待流水线满,开始继续执行

### PC寄存器LR寄存器的作用与使用方法 #### 程序计数器(PC) 程序计数器(Program Counter, PC)在ARM架构中是一个关键的寄存器,用于存储即将执行的指令地址。每当处理器执行一条指令时,PC会自动更新为下一条指令的地址[^1]。这意味着PC始终指向当前指令序列中的下一条指令。 在ARM架构中,PC并不是直接指向当前执行的指令,而是通常指向当前指令后面两条指令的地址(即PC = 当前地址 + 8字节)。这种设计是为了适应ARM的三级流水线结构[^3]。 #### 链接寄存器LR) 链接寄存器(Link Register, LR)是ARM处理器中一个具有特殊用途的寄存器。当发生函数调用或中断时,返回地址(即调用指令后的下一条指令地址)会被保存到LR中[^1]。通过这种方式,LR充当了PC的一个备份,在函数调用完成后可以恢复程序的执行流。 具体来说,当执行`BL`(Branch with Link)指令时,当前PC会被存储LR中,随后PC被设置为分支目标地址。这使得在函数执行完成后,可以通过将LR重新加载到PC来返回到调用点[^2]。 #### 使用方法 - **PC的使用** PC由硬件自动管理,程序员通常不需要直接操作它。然而,在某些情况下,可以通过跳转指令(如`B`, `BL`)或修改PC来实现程序控制流的改变。例如: ```assembly MOV PC, R14 ; 将R14的赋给PC,通常用于函数返回 ``` - **LR的使用** LR主要用于函数调用中断处理。在进入子程序或中断服务程序之前,需要保存LR以防止覆盖。通常,LR会被压入堆栈中,以便在函数返回时恢复其。例如: ```assembly PUSH {LR} ; 将LR压入堆栈 ... POP {PC} ; 从堆栈弹出LR并赋给PC,实现返回 ``` 此外,在多层嵌套调用中,每次调用都需要保存LR,以确保正确的返回路径[^4]。 ### 示例代码 以下是一个简单的汇编代码示例,展示如何使用PCLR进行函数调用返回: ```assembly .global main main: BL function ; 调用function,返回地址保存到LR B end ; 结束程序 function: PUSH {LR} ; 保存LR到堆栈 ; 函数体 POP {PC} ; 恢复LRPC,返回到调用点 end: BX LR ; 程序结束 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值