当前位置:网站首页 > 编程语言 > 正文

能从单片机里面读取程序吗(能不能把单片机里面程序读出来)



刚接触ARM的cortex-m系列单片机时,被告知一切都从main() 函数开始,要将程序写在main()函数中。而仿真时也貌似是从main() 函数开始的,以STM32F103为例。

在这里插入图片描述

后来了解到全局变量是在main()函数之前初始化的。MDK默认情况下勾选下面选项,跳过了启动的汇编部分代码,直接进入了main() 函数.
在这里插入图片描述

实际起始位置

在这里插入图片描述

在cortex-m系列中,中断向量表存放在 Flash 开始部分,Flash中第一个字存放栈顶指针,第二个字存放复位中断服务函数入口地址,其他中断服务函数入口地址依次存放在Flash中。

在这里插入图片描述

MCU上电后,会将Flash中的第一个字加载到R13 MSP寄存器中,第二个字加载到R15 PC寄存器中。

在这里插入图片描述

从上图可以看出ARM规定了M3,M4内核要从地址0x0000 0000读取中断向量表,而STM32设置Flash地址到0x0800 0000怎么办?

STM32将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中,这样就解决了从0x0000 0000读取中断向量表的问题。
下图可以看出STM32F105实际读出的0x0000 0000和0x0800 0000内容一样
在这里插入图片描述

R13:栈顶指针寄存器SP

SP寄存器有两个,MSP或者PSP,PSP是为了RTOS特意设置的,如果使用RTOS,则在RTOS的任务中就是使用的PSP,在中断服务函数中则使用MSP。如果不使用RTOS,则默认一直使用MSP。

在这里插入图片描述

在MCU中,RAM只是负责暂存数据,真正的运算是在寄存器中完成的,例如要对两个变量进行加法运算,就需要将两个变量的值从RAM中取出存入寄存器中,然后操作寄存器进行计算,最后将计算结果存入RAM中。因此常说的在进入子函数或者中断服务函数时需要保存现场,其实也就是保存寄存器中的值,将寄存器值PUSH在栈中。

在这里插入图片描述

SP寄存器指向栈顶地址,因此随着PUSH和POP,SP寄存器会跟着自动变化。

在这里插入图片描述

MSP寄存器存放栈顶指针,栈中存放局部变量、函数参数以及进入子函数、中断服务函数前寄存器的值,当从子函数或者中断服务函数中跳出时,会从栈中POP寄存器值,也就是恢复现场,确保程序可以正常执行。平时尽量不让使用递归就是为了防止多次调用自身,多次保存现场导致栈溢出。

在这里插入图片描述

入栈和出栈操作由编译器自动生成代码,但是入栈时默认只会将R0-R3入栈,如果中断服务函数过于复杂,则编译器也会将R4-R11入栈,这也就是为什么中断服务函数尽量简短的原因之一。

在这里插入图片描述

R15:程序计数寄存器PC

PC寄存器指向当前的程序地址。如果修改它的值,就能改变程序的执行流(很多高级技巧就在这里面)
在这里插入图片描述
上电时将中断向量表中的第二个字加载到PC寄存器中,也就是让程序跳转到复位中断服务函数中。
在这里插入图片描述
在这里插入图片描述
不过复位中断服务函数是一个汇编函数。




在这里插入图片描述

到此这篇能从单片机里面读取程序吗(能不能把单片机里面程序读出来)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • linux 目录重命名(linux改目录名字命令)2026-01-29 07:36:11
  • 华为机考题库2023(华为机考题库20234)2026-01-29 07:36:11
  • bigboss源怎么用(bigboss源可以删掉吗)2026-01-29 07:36:11
  • 域名ip地址区别(域名ip地址区别)2026-01-29 07:36:11
  • de4dot反混淆(.net反混淆)2026-01-29 07:36:11
  • van怎么读(vans怎么读)2026-01-29 07:36:11
  • ad9154中文手册(ad9954中文手册)2026-01-29 07:36:11
  • 换国内ip的加速器哪个好(改ip加速器哪个好)2026-01-29 07:36:11
  • atb战斗系统的游戏(战斗系统做得最好的游戏)2026-01-29 07:36:11
  • 线上小程序制作谷子(线上小程序制作谷子视频)2026-01-29 07:36:11
  • 全屏图片