MDK __main过程分析

今天分析了一下__main的流程,和大家分享一下

在进入__main之间打下断点, 当前命令“LDR r0 , [pc, #24]“  将PC+24=0x080001E0地址处的数据加载到 r0 中,因为 CM4 内部
使用了指令流水线,读 PC 时返回的值是当前指令的地址+4。所以当前命令后,R0等于0x080001E0地址处的数据,如下图所示:R0=0x080001AD。

然后运行0x080001C6处的指令 “BX R0”,CM3 中的指令至少是半字对齐的,所以 PC 的 LSB 总是读回 0。然而, 在分支时,无论是直接写 PC 的值还是使用分支指令,都必须保证加载到 PC 的数值是奇数(即 LSB=1),用以表明这是在Thumb 状态下执行。倘若写了 0,则视为企图转入 ARM 模式,CM3 将产生一个 fault 异常。所以当前指令后,PC会跳转到0x080001AC处的地址。如下图所示

然后运行”BL.W __scatterload“ 跳转到0x080001e4地址的__scatterload函数中去。

接着向下运行,由于刚开始R4 = 0X08000CD4 R5=0X08000D04。每次循环R4+0X10,所以__scatterload中需要循环3次。
LDM R4,{R0-R2}  从R4指向的地址取3个4字节的数据,保存到R0,R1,R2中

第一次循环:给给定初值的全局变量赋初值。
然后跳转到R3=0X08000B5D 指向的地址中,通过查看工程生成的.map文件可以得知R3指向的地址是__scatterload_copy 函数,形参是R0,R1,R2  
__scatterload_copy                       0x08000b5d   Thumb Code    14  handlers.o(i.__scatterload_copy)

LDM R0!,{R3} 从R0指向的地址中的数据加载R3中,然后将R0+4 。如下图所示R0的值比上图加4了
STM R1!,{R3} 将R3中的数据保存到R1指向的地址中,然后将R1+4。如下图所示R1的值比上图加4了
这样循环9次=0x24/4。将内存中0XD0000000地址开始的,长度为0x24=36字节的区域的有初值的全局变量给赋值了。
map文件中
SDRAM_Register                           0xd0000004   Data           4  sdram.o(.data)
uwWriteReadStatus                        0xd0000008   Data           4  sdram.o(.data)
uwIndex                                             0xd000000c   Data           4  sdram.o(.data)
g_u8flag                                            0xd0000010   Data           1  sdram.o(.data)

最后通过"BX LR"跳出__scatterload_copy函数,如下面2张图所示。

第二次循环:清栈空间
第二次循环R0=0X08000D04,R1=0X20000000,R2=0X00000400这是栈空间的地址,然后跳转到R3=0x08000B6D地址运行。就是__scatterload_zeroinit函数
map文件可以看到栈空间
Base Addr    Size         Type   Attr      Idx    E Section Name        Object

0x20000000   0x00000400   Zero   RW          339    STACK               startup_stm32f427x.o

通过函数名称可以看出当前函数是清零初始化函数
MOVS R0, #00将R0=0
然后STM R1!,{R0} 将0赋值给R1所指向的内存空间,就是0x20000000,然后R1+4移向下一个地址,R2 - 4循环此处减4
如此循环下去,直到R2减为0。就是将起始地址0x20000000,长度为0x0400的内存空间清零。
最后通过BX LR返回到__scatterload中

第三次循环:给未赋初值的全局变量清零。

R0=0X08000D28,R1=0XD0000024,R2=0X00000210。然后跳转到R3=0x08000B6D地址运行。就是__scatterload_zeroinit函数。
通过查看map文件,可知起始地址为0XD0000024,长度为0x210的内存针对那些变量
 RCC_Clocks                               0xd0000024   Data          16  main.o(.bss)
    aTxBuffer                                0xd0000034   Data         256  sdram.o(.bss)
    aRxBuffer                                0xd0000134   Data         256  sdram.o(.bss)

上面已经分析了,真理就不再重复了。
退出后返回到__scatterload中,由于达到了退出条件,则退出__scatterload函数到__main_after_scatterload中

在__main_after_scatterload中跳转到main中
LDR R0,[PC,#0] 则R0=0X080001B8地址处的数据,即R0=0X0800087D
BX R0  则跳转到0X0800087D指定的指令。
通过查看map文件得知,这个指定对应的就是main函数
main                                     0x08000b7d   Thumb Code    96  main.o(i.main)

以上就是__main的分析过程。

(0)

相关推荐

  • ARM Cortex-M 启动代码的使用

    Cortex-M 启动代码的使用     上一篇扯了一些关于启动代码的原理,了解了额原理不去使用意义就没有那么大了,了解了启动代码不是终极目的,我们的目的是深入理解Cortex-M系列MCU的底层原理 ...

  • STM32系列开发-揭开MDK下__main的面纱--非常详解

    之前,是大体了解了MDK下的__main函数所做的事情,一直没有深究,最近突然很想知道,MDK下在程序运行到我们用户定义的main()函数前,到底做了些什么,想看看ARMCC编译器默默地为我们做了哪些 ...

  • 「高中生物」实验过程分析和答题模板!未来只因你的努力而美丽

    一些同学做题,得出答案就结束了,没有反思,没有总结,没有举一反三,过分追求结果,不重视解题的思维过程.其实,把思维过程整理和展示出来是学习的好方法.要学会用慢镜头展示思维的关键处,学会用放大镜放大思维 ...

  • MDK(keil)4.7中文注释乱码解决

    更新:2017-04-23 17:49 转载不过很有用的 工具/原料 MDK(KEIL) 方法/步骤 1 由于编码使用不统一导致别的开发环境下的文件在MDK(keil)下打开中文显示乱码,解决这一问题 ...

  • 【<em>二轮</em>专题】2021高三<em>二轮</em>专题复习:地理过程分析

    仅供学习交流使用! END 获取方法: 扫描下面二维码加入知识星球或小红圈即可 海宁中学地理组(知识星球)

  • SAP Spartacus 里的 cxOutletRef 指令执行过程分析

    先看 cxOutletRef 指令的效果:ng-template 里定义了如下图标 1 区域所示的自定义 UI,通过 cxOutletRef, 将其插入到图标 2 所示的 ProductDetails ...

  • 【二轮专题】2021高三二轮专题复习:地理过程分析

    仅供学习交流使用! END 获取方法: 扫描下面二维码加入知识星球或小红圈即可 海宁中学地理组(知识星球)

  • 地理过程分析技巧与常见地理过程归纳

    地理过程本身就是一个动态的过程,尤其在不同时间尺度下地理事物表现出空间上的特征演变, 使地理事物变得更加复杂.这需要学生具备良好的地理思维, 小编在此整理了相关资料,希望能帮助到大家. 一.地理过程解 ...

  • 乌龟图,过程分析利器!

    为了保证过程有效运行和控制,组织应确定所需的准则及方法,这些准则和方法形成文件就是公司或企业的管理体系文件. 在体系建设初期,公司必须建立管理文件体系,来保证公司达到所要求的(产品)质量和预期管理目标 ...

  • 地理过程分析技巧与常见地理过程归纳(珍藏)

    地理过程本身就是一个动态的过程,尤其在不同时间尺度下地理事物表现出空间上的特征演变, 使地理事物变得更加复杂.这需要学生具备良好的地理思维, 小编在此整理了相关资料,希望能帮助到大家. 一.地理过程解 ...