MDK __main过程分析

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


MDK __main过程分析_第1张图片

在进入__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函数中去。
MDK __main过程分析_第2张图片

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

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

MDK __main过程分析_第4张图片

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)

MDK __main过程分析_第5张图片

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

MDK __main过程分析_第6张图片
MDK __main过程分析_第7张图片

第二次循环:清栈空间
第二次循环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

MDK __main过程分析_第8张图片

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

MDK __main过程分析_第10张图片

MDK __main过程分析_第11张图片

第三次循环:给未赋初值的全局变量清零。
MDK __main过程分析_第12张图片
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)
MDK __main过程分析_第13张图片

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

MDK __main过程分析_第14张图片



在__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的分析过程。



你可能感兴趣的:(STM32,MDK,linux中C和汇编语言学习)