`
yidongkaifa
  • 浏览: 4072566 次
文章分类
社区版块
存档分类
最新评论

MDK __main()代码执行过程分析

 
阅读更多

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。http://blog.csdn.net/wfq0624


1.1__main()代码执行分析

以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 0x00000394 Number 0anon$$obj.o(Region$$Table)

Region$$Table$$Limit 0x000003b4 Number 0anon$$obj.o(Region$$Table)


然后执行_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_enty函数

分析__rt_entry()函数

先调用__user_setup_stackheap()函数来建立堆栈


可以看出在这个函数中,会执行到BL__user_initial_stackheap()函数,这样也就明白了,为什么使用分散加载文件,需要设置__user_initial_stackheap这个函数来设置堆栈空间。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics