在main之前,iar都做了啥

微兔家 2024-05-26 10:29:37
最佳回答
0 bx r0;bx r0  08007e24 6c69  08007e26 0800  08007e28 7d8d  08007e2a 0800    细心的观众会发现地址是0x0800'7e1c,比我们查到的0x0800'7e1d差了1,这是arm家族的遗留问题,因为的指令至少是半字对齐的(16位thumb指令集 or 32位),所以pc指针的l**是常为0的,为了充分利用寄存器,给pc的l**了一个重要的使命,那就是在执行分支跳转时,pc的l**=1,表示使用thumb模式,l**=0,表示使用arm模式,但在最新的cortex-m3内核上,只使用了thumb-2指令集挑大梁,所以这一位要常保持1,所以我们查到的地址是0x0800'7e1d(c=1100,d=1101),放心,我们的cm3内核会忽略掉l**(除非为0,那么会引起一个fault),从而正确跳转到0x0800'7e1c。    从0x0800'7e20处的加载指令,我们可以算出__iar_program_start所处的位置,就是当前pc指针(0x0800'7e24),再加上4,即0x0800'7e28处的所指向的地址——0x0800'7d8d(0x0800'7d8c),我们跟紧着跳转,__iar_program_start果然在这里:    __iar_program_start:  08007d8c f000f88c bl __low_level_init  08007d90 2800 cmp r0, #0x0  08007d92 d001 beq __iar_init$$done  08007d94 f7ffffde bl __iar_data_init2  08007d98 2000 movs r0, #0x0  08007d9a f7fdfc49 bl main    我们看到iar提供了__low_level_init这个函数进行了“底层”的初始化,进一步跟踪,我们可以查到__low_level_init这个函数做了些什么,不是不是我们想象中的不可告人。    __low_level_init:  08007ea8 2001 movs r0, #0x1  08007eaa 4770 bx lr    __low_level_init出乎想象的简单,只是往r0寄存器写入了1,就立即执行"bx lr"回到调用处了,接下来,__iar_program_start检查了r0是否为0,为0,则执行__iar_init$$done,若不是0,就执行__iar_data_init2。__iar_init$$done这个函数很简单,只有2句话,第一句是把r0清零,第二句就直接"bl main",跳转到main()函数了。不过既然__low_level_init已经往r0写入了1,那么我们还是得走下远路——看看__iar_data_init2做了些什么,虽然距离main只有一步之遥,不过这中间隐藏了编译器的思想,我们得耐心看下去。    __iar_data_init2:  08007d54 b510 push {r4,lr}  08007d56 4804 ldr r0, [pc, #0x10]  08007d58 4c04 ldr r4, [pc, #0x10]  08007d5a e002 b 0x8007d62  08007d5c f8501b04 ldr r1, [r0], #0x4  08007d60 4788 blx r1  08007d62 42a0 cmp r0, r4  08007d64 d1fa bne 0x8007d5c  08007d66 bd10 pop {r4,pc}  08007d68 7c78  08007d6a 0800  08007d6c 7c9c  08007d6e 0800    看来iar迟迟不执行main()函数,就是为了执行__iar_data_init2,我们来分析分析iar都干了些什么坏事~    首先压r4,lr入栈,然后加载0x0800'7c78至r0,0x0800'7c9c至r4,马上跳转到0x0800'7d62执行r0,r4的比较,结果若是相等,则弹出r4,pc,然后立即进入main()。不过iar请君入瓮是自不会那么快放我们出来的——结果不相等,跳转到0x0800'7d5c执行,在这里,把r0指向的地址——0x0800'7c78中的值——0x0800'7d71加载到r1,并且r0中的值自加4,更新为0x0800'7c7c,并跳转到r1指向的地址处执行,这里是另一个iar函数:__iar_zero_init2:    __iar_zero_init2:  08007d70 2300 movs r3, #0x0  08007d72 e005 b 0x8007d80  08007d74 f8501b04 ldr r1, [r0], #0x4  08007d78 f8413b04 str r3, [r1], #0x4  08007d7c 1f12 subs r2, r2, #0x4  08007d7e d1fb bne 0x8007d78  08007d80 f8502b04 ldr r2, [r0], #0x4  08007d84 2a00 cmp r2, #0x0  08007d86 d1f5 bne 0x8007d74  08007d88 4770 bx lr  08007d8a 0000 movs r0, r0    __iar_data_init2还没执行完毕,就跳转到了这个__iar_zero_inti2,且看我们慢慢分析这个帮凶——__iar_zero_inti2做了什么。  __iar_zero_inti2将r3寄存器清零,立即跳转到0x0800'7d80执行'ldr r2, [r0], #0x4',这句指令与刚才在__iar_data_init2见到的'ldr r1, [r0], #0x4'很类似,都为“后索引”。这回,将r0指向的地址——0x0800'7c7c中的值——0x0000'02f4加载到r2寄存器,然后r0中的值自加4,更新为0x0800'7c80。接下来的指令检查了r2是否为0,显然这个函数想放我我们,r2的值为2f4,我们又被带到了0x0800'7d74处,随后4条指令做了如下的事情:  1、将r0指向的地址——0x0800'7c80中的值——0x2000'27d4加载到r1寄存器,然后r0中的值自加4,更新为0x0800'7c84。  2、将r1指向的地址——0x2000'27d4中的值——改写为r3寄存器的值——0,然后r1中的值自加4,更新为0x2000'27d8。  3、r2自减4  4、检查r2是否为0,不为0,跳转到第二条执行。不为,则执行下一条。    这简直就是一个循环!——c语言的循环for(r2=0x2f4;r2-=4;r!=0){...},我们看看循环中做了什么。    第一条指令把一个地址加载到了r1——0x2000'27d4 是一个ram地址,以这个为起点,在循环中,对长度为2f4的ram空间进行了清零的操作。那为什么iar要做这个事情呢?消除什么记录么?用jlink查看这片内存区域,可以发现这片区域是我们定义的全局变量的所在地。也就是说,iar在每次系统复位后,都会自动将我们定义的全局变量清零0。    清零完毕后,接下来的指令"ldr r2, [r0], #0x4"将r0指向的地址——0x0800'7c84中的值——0加载到r2寄存器,然后r0中的值自加4,更新为0x0800'7c88。随后检查r2是否为0,这里r2为0,执行'bx lr'返回到__iar_data_init2函数,若是不为0,我们可以发现又会跳转至“4指令”处进行一个循环清零的操作。    读到这里,我们应该可以猜到iar的意图了:__iar_data_init2一开始加载了0x0800'7c78至r0,0x0800'7c9c至r4,[r0,r4]就是一段启动代码区,在这个区域内保存了要“处理”的所有地址与信息——执行的函数地址或者参数,实际上,这片区域也有一个名字,叫做:region$$table$$。在这个区域内,程序以r0为索引,r4为上限,当r0=r4,__iar_data_init2执行完毕,跳转至main()函数。    好了,保持我们这个猜想,继续跟踪我们的pc指针——我们回到了__iar_data_init2函数中,第一件事就是比较r0,r4的值,可惜的是,仍然不相等,我们又被带到了0x0800'7d5c,至此,我们应该能看出这是一个__iar_data_init2的“主循环”,这也验证了我们对iar意图的猜想~  __iar_data_init2中的“主循环”:  08007d5c f8501b04 ldr r1, [r0], #0x4  08007d60 4788 blx r1  08007d62 42a0 cmp r0, r4    我们可以等价写为:for(r0=0x0800'7c78,r4=0x0800'7c9c;r0!=r4;r0 =4){...}  此时,我们的r0为0x0800'7c88,经过“指令1”,r0变为0x0800'7c8c,r1为0x0800'7c55。我们来看看,7c55处,iar又要执行何种操作。    __iar_copy_init2:  08007c54 b418 push {r3,r4}  08007c56 e009 b 0x8007c6c  08007c58 f8501b04 ldr r1, [r0], #0x4  08007c5c f8502b04 ldr r2, [r0], #0x4  08007c60 f8514b04 ldr r4, [r1], #0x4  08007c64 f8424b04 str r4, [r2], #0x4  08007c68 1f1b subs r3, r3, #0x4  08007c6a d1f9 bne 0x8007c60  08007c6c f8503b04 ldr r3, [r0], #0x4  08007c70 2b00 cmp r3, #0x0  08007c72 d1f1 bne 0x8007c58  08007c74 bc12 pop {r1,r4}  08007c76 4770 bx lr  这是一个名为__iar_copy_init2的函数,他执行了什么"copy"操作呢?  首先压r3,r4入栈,然后跳转到0x0800'7c6c,从r0——region$$table$$base中取出参数0x238放入r3,接下来的指令大家应该都熟悉了,0x238不为0,所以我们被带至7c58处,再次从region$$table$$base中取出参数0x0800'7f14放入r1,从region$$table$$base取出参数0x2000'2ac8放入r2处。细心的观众应该能察觉这和__iar_zero_init2中取参数的几乎一样:先取出大小,随后取出了地址——只不过这里多出了1个地址,没错这就是"copy",随后的指令  08007c60 f8514b04 ldr r4, [r1], #0x4  08007c64 f8424b04 str r4, [r2], #0x4  08007c68 1f1b subs r3, r3, #0x4  08007c6a d1f9 bne 0x8007c60  则是另一个“4指令”,指令1将r1指向地址的数据读到r4,指令2将r2指向地址的数据改写为r4的数据,指令3、4是完成一个循环。 20210311
汇率兑换计算器

类似问答
  • 你在三下乡之前做了哪些功课?
    • 2024-05-26 01:13:12
    • 提问者: 未知
    说起这个也是一把鼻涕一把眼泪的经历啊!我们队伍的实践活动属于自主选题的类型,在通过项目之前必须要完成立项书、立项答辩等等一系列环节。接下来我就讲讲我们队伍都做了哪些活动前的准备。要做一项活动,首先我们必须要有一个最初的想法作为支撑点。例如,在选题的角度方面,是选择精准扶贫还是非遗文化,活动形式方面,是选择实地调研还是乡村支教……这些都是活动组织安排的基础。其次,对于这项活动有了大致的想法之后,还必...
  • 之前都是零报税,过了一年税务局要求补报表,怎么做
    • 2024-05-26 23:03:32
    • 提问者: 未知
    可以多多少少做点收入,可以加我交流,,因为不能持续零申报
  • 我在镇江买房 在房产证拿到之前都只能做商业贷款?
    • 2024-05-26 08:33:15
    • 提问者: 未知
    亲爱的 要有房产证以后才可以的哦
  • c语言中,main() ; int main(void) ; int main() ; void main() 有什么区别?
    • 2024-05-26 00:47:04
    • 提问者: 未知
    http://www. open-std.org/jtc1/sc22/ wg14/www/docs/n1256.pdf entry point ​ 34 ​ ​ 添加评论 ​ ...腾讯视频后台码农.b站up,公众号同名,分享基金和编程小视频 ...
  • 做学前的老师都转行做什么了?
    • 2024-05-26 10:02:18
    • 提问者: 未知
    很想知道学前教育的老师都转行做什么工作了,感觉如何。3 人赞同了该回答 更新一下答案,至于为什么更新,因为这是我在知乎上,唯一的一篇回答。白嫖?说的是不是我?以下是原回答— ...
  • 剑灵没出之前玩点儿啥
    • 2024-05-26 10:02:12
    • 提问者: 未知
    真三国无双5,真三国无双6…虽然是单机的,不过还算爽,推荐无双6,画面还过得去,还有**原型、上古卷轴、鬼泣等,游民星空就可以下载。不用花钱,可以省下来投资剑灵……非要说网络的话……永恒之塔,龙之谷,冒险岛,第九**,洛奇英雄传也都不错……。
  • 做了一段时间期货之后不想做了,能不能把本金啥的都转到**里啊?
    • 2024-05-26 19:21:43
    • 提问者: 未知
    可以全部出完,要求本人给期货公司结算部打电话 确认是本人操作就可以
  • 你好我是之前公司法人和股东现在做了
    • 2024-05-26 14:13:04
    • 提问者: 未知
    股东可申请**解散公司 新公司法:公司经营发生严重困难,继续存续会使股东利益受到重大损失,通过其他途径不能解决的,持有公司全部股东表决.更多 2011-12-19 关于公司...
  • 请问:在结婚之前都要做些什么准备?
    • 2024-05-26 03:24:28
    • 提问者: 未知
    结婚前的准备有很多,我准备了有100页的word文档,上面什么都列有了的,如果你有兴趣可以看看,在这儿我就不打了,实在是太多了,你去我的共享资料里面找找,上面有关房子的布置,还有应该有的礼仪什么...
  • 之前在
    • 2024-05-26 15:33:14
    • 提问者: 未知
    另外,在追讨债务过程中需要注意收集足够的证据,比如合同、协议、债权文书(借条、欠条等)、收发货凭证、往来信函等...专业:婚姻家庭 刑事辩护 房产纠纷 企业法律顾问 合同...
汇率兑换计算器

热门推荐
热门问答
最新问答
推荐问答
新手帮助
常见问题
房贷计算器-九子财经 | 备案号: 桂ICP备19010581号-1 商务联系 企鹅:2790-680461

特别声明:本网为公益网站,人人都可发布,所有内容为会员自行上传发布",本站不承担任何法律责任,如内容有该作者著作权或违规内容,请联系我们清空删除。