Cortex-M3/M4内核STM32的LR寄存器和PC寄存器

怎么控制STM32跳转到指定程序:

  • 首先,使用标号加goto语句可以使程序强制跳转,而goto的原理实际上是汇编语言里面的强制跳转。
    我们看STM32的启动文件,发现里面有这两句程序:
    其中LDR R0 ,=一个函数名
    意思是把这个函数的地址放到寄存器R0里面
    BLX R0BX R0意思都是跳转到以R0寄存器所存的地址
    在这里插入图片描述

STM32的LR寄存器和PC寄存器:

  • PC寄存器是程序计数器,内部存的是程序当前执行到了哪个地址。LR寄存器是连接寄存器,在执行子函数前,LR会保存执行完子函数后,应该回到哪个地方。验证如下:
    我们在主函数执行里面打一个断点,当程序执行到断点处时,我们发现断点处的PC指针是0X080002A2。
    由于Cortex-M3架构采用16位和32位指令集,因此其PC指针地址是4字节对齐的,换言之其最低2位一定全是0,我们发现0X080002A2符合这个特点。
    在这里插入图片描述

  • 我们看在我们打的断点处,断点处的上一句执行的是函数raw_os_init()。
    因此按照我们的推论,在跳转到函数raw_os_init()前,LR寄存器会记住执行完raw_os_init()函数后,PC指针应该回到哪个地址。
    因此我们在raw_os_init()函数里面打断点,看执行子函数raw_os_init()时LR是不是存的是执行完子函数后应该返回的地址。如下图:
    在这里插入图片描述
    在执行子函数raw_os_init()时,我们发现LR里面存的是0X080002A3,而执行完改函数后应当回到的地址是0X080002A2,我们发现比我们在temppp += 1;断点处看到的PC指针大了1。这是为什么呢?
    首先我们观察LR寄存器内存放的值:0X080002A3,其最低位为1,显然不可能是直接存放的程序地址,因为程序地址需要4字节对齐,最低2位全为0。
    LR寄存器的最低位是标识指令长度状态,因此在以LR存放的地址进行跳转时,会将最低2位与0,则与0后0X080002A3就变为了0X080002A2,也就刚好是0X080002A2,即要回到的地址。

对指令感兴趣的可以继续往下看:

在《权威指南》一书中,有以下说明:

  • 首先是Cortex-M3架构的创新性指令集:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

Cortex-M3架构的优点之一就是采用了Thumb-2指令集,其同时支持16位指令和32位指令共存,而不会混淆。
而只所以不会混淆,并不可能是存在什么魔法能够让CPU自动分辨指令长度,必定存在一个标志位,来标识每一条指令的类别是16位还是32位。

  • 我们对比LR和PC特点,发现PC最低2位一定全是0,那么LR存放的数据中,最低2位就相当于多余的,因此我们可以拿LR最低2位来做标志位,来标识一些信息。恰好,我们上边16位指令还是32位指令缺少个标志位,因此,LR寄存器的最低位是Thumb状态标志位,如下:
    在这里插入图片描述

2023年3月31日删除下面错误:
这是因为我们在temppp += 1;打断点时,是还没执行temppp += 1;语句的PC指针地址,则执行temppp += 1;时PC指针值应该是0X080002A2 + 1=0X080002A3,刚好和LR寄存器中存的值一样。

结语:

LR寄存器存的是:执行子函数后,PC指针应该跳转回去的地方。

猜你喜欢

转载自blog.csdn.net/wcc243588569/article/details/117818521