__main()代码执行分析

标签:
it |
分类: ARM |
1.1
以keyled程序为例说明,keyled代码请参考我的博客网址:http://my.csdn.net/wfq0624/code/detail/7645 程序经过汇编启动代码,执行到__main()后,可以看出有两个大的函数: __scatterload():负责把RW/RO输出段从装载域地址复制到运行域地址,并完成了ZI运行域的初始化工作。 __rt_entry():负责初始化堆栈,完成库函数的初始化,最后自动跳转向main()函数。 分析__scatterload()函数 执行到__main(),先跳转到_scatterload下图红框框中代码所示,执行完后,R10和R11就被赋给成了下面两个值。 Map文件中的symbol Region$$Table$$Base Region$$Table$$Limit 然后执行_scatterload_null代码,将R10对应地址存放的的4个字copy到R0~R3中,可以看出 R0:0x1000表示的是keyled.o加载域起始地址 R1:0x30000100为keyled.o运行域地址 R2:0X160为copy的大小,keyled.o的大小从map文件中得知就是0x160 Byte R3:0X1E4 是_scatterload_copy 代码的起始地址,实用BXR3 就能跳转到_scatterload_copy来复制代码。 跳到_scatterload_copy,开始copy,循环0x16次,每次搬移4个字(16Byte),共搬移0x16*0x10=0x160 复制完keyled.o代码后,进一步循环到_scatterload_null准备好,ZI段需要清零的地址和范围 执行完这个循环后 R1:0x30050000 为ZI段的起始地址 R2:0x618为ZI段大小,换成十进制是1560.从map文件得知ZI大小就是1560Byte R3:0x20c 为_scatterload_zeroinit 的地址 执行下面红框框中循环体,共清零0x610Byte范围,然后再执行蓝框框中代码,清零8Byte,总共0x618 ZI段清零(0x30050000~0x30050618) 然后使用BX R14跳转到0x000001BC处,顺序执行到BL 成功跳转到__rt_enty函数 分析__rt_entry()函数 先调用__user_setup_stackheap()函数来建立堆栈 可以看出在这个函数中,会执行到BL__user_initial_stackheap()函数,这样也就明白了,为什么使用分散加载文件,需要设置__user_initial_stackheap这个函数来设置堆栈空间。 http://www.openedv.com/posts/list/19165.htm
|