最经典的搬运代码分析
来源:互联网 发布:加人软件 编辑:程序博客网 时间:2024/05/16 05:43
由ADS生成的代码的标号是以设置的RO为基准的,也就是说CopyProcBeg是RAM中的一个地址 。(这解释无敌了)boot烧在0位置 整个代码绝对的起始位置(绝对地址)都是以RO开始的 即entry位置开始,所有偏移都是相对于它的,而开始boot烧在0X0处却可运行是因为,搬运代码函数之前代码与实际用不到太多有实际作用的地址,可以用普通偏移解决,而JLINK仿真开始为止和设定位置相等这个设置对代码烧入FLASH以后的分布没有关系。只是把code和data分段了一下.
3楼:>>参与讨论作者: sklar 于 2007-4-26 16:54:00 发布:呵呵,进来的都发表下看法吧
知道的说下,不清楚的也把自己的看法说说吧,大家交流啊,楼上的用什么ARM板?我用的是立YU泰的44B0
4楼:>>参与讨论作者: luhuaren 于 2007-4-26 17:15:00 发布:
re
RO Base设置为0xc000000 RW Base设置为0xc5f0000,可是BIOS不是要放0X0000000的吗
注意:如果是用44B0,那么44B0上电复位后PC的值是0,
AREA Init,CODE,READONLY
ENTRY
ResetEntry
b ResetHandler ;for debug
b HandlerUndef ;handlerUndef
b HandlerSWI ;SWI interrupt handler
b HandlerPabort ;handlerPAbort
b HandlerDabort ;handlerDAbort
b . ;handlerReserved
b HandlerIRQ
b HandlerFIQ
系统上电后第一条指令执行的是b ResetHandler (在0地址处)这是一条相对跳转指令,也就是说,这条指令和RO的设置无关
跳转到ResetHandler处,进行一些初始化动作后,就要进行代码拷贝,就是把FLASH里的代码拷贝到RO指定的地址处,代码拷贝是这样实现的:
;****************************************************
;拷贝并粘贴 RW data/zero initialized data *
;****************************************************
adr r0, ResetEntry
ldr r1,BaseOfROM
cmp r0,r1
ldreq r0, TopOfROM
beq InitRamData
;****************************************************
;计算拷贝程序在FLASH中的实际位置 *
;****************************************************
ldr r2,=CopyProcBeg
sub r1, r2, r1;r2-r1->r1
add r0, r0, r1
ldr r3,=CopyProcEnd
;****************************************************
;将拷贝程序复制到ram中 *
;****************************************************
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r2, r3
bcc %B0
;********************************************************
;开始用ram中的拷贝程序复本将所有剩下的代码复制到ram中 *
;********************************************************
ldr r3, TopOfROM
;ldr pc, =CopyProcBeg ;装入绝对地址(指到RAM中去的)
b CopyProcBeg
;********************************************************
;本段将代码由实际烧入的地址拷贝到ro-base所指定的位置 *
;只拷贝CopyProcEnd以后的代码 ;********************************************************
CopyProcBeg
0
ldmia r0!, {r4-r11}
stmia r2!, {r4-r11}
cmp r2, r3
bcc %B0
CopyProcEnd
sub r1, r2, r3
sub r0, r0, r1
InitRamData
ldr r2, BaseOfBSS
ldr r3, BaseOfZero
0
cmp r2, r3
ldrcc r1, [r0], #4
strcc r1, [r2], #4
bcc %B0
mov r0, #0
ldr r3, EndOfBSS
1
cmp r2, r3
strcc r0, [r2], #4
bcc %B1
;===================================================================
adr r0, ResetEntry
ldr r1,BaseOfROM
cmp r0,r1
请注意这几条语句,尤其是adr r0, ResetEntry,这条语句当你反汇编后发现是一条这样的指令
;[0xe24f0f5d] sub r0,pc,#0x174 ; #0xc008000
也是一条与位置无关的指令,ResetEntry的值同PC的值相关联,
当然,PC一上电的值为0,所以这里ResetEntry的值也为0,所以
ldr r1,BaseOfROM
cmp r0,r1
比较的结果就是R0 != R1于是进行代码拷贝,将复制程序拷贝完后,就可以跳转到RAM中去,执5楼:>>参与讨论作者: luhuaren 于 2007-4-26 17:20:00 发布:
RE
可以下在U-BOOT的源码看一下,感觉很多开发板上流行的BOOT代码都是从U-BOOT上改过来的
6楼:>>参与讨论作者: pigjiang 于 2007-4-27 8:46:00 发布:
有个疑问
IMPORT |Image$$RO$$Base| ; ROM code start
IMPORT |Image$$RO$$Limit| ; RAM data starts after ROM program
IMPORT |Image$$RW$$Base| ; Pre-initialised variables
IMPORT |Image$$ZI$$Base| ; uninitialised variables
IMPORT |Image$$ZI$$Limit| ; End of variable RAM space
===============================================
这几行的||里面的标号是从哪里获得的?
他们是不是就是设置linker的OUTPUT选项里面填入的RO和RW的值?
7楼:>>参与讨论作者: wowow 于 2007-4-27 9:58:00 发布:
RO/RW
RO/RW地址在debug/release设置不同的值,一个用于仿真器加载到ram运行,一个用于FLASH中运行。如果你用了中断,并且ARM不支持REMAP,调ram程序时FLASH里必须也烧进中断向量表。
|Image$$RO$$Base| 之类是linker生成的,但有些情况下不生成。最好自己读一读关于linker的pdf
8楼:>>参与讨论作者: sklar 于 2007-4-27 12:28:00 发布:
to luhuaren
你的这些代码我在44Binit.S文件里没有,不过有点懂你说的意思了,ADS里设置的这些地址就是把代码考到SDRAM里的地址?
adr r0, ResetEntry
ldr r1,BaseOfROM
cmp r0,r1 //??这里没怎么没说跳到哪里?
9楼:>>参与讨论作者: luhuaren 于 2007-4-27 15:02:00 发布:
re
当然,PC一上电的值为0,所以这里ResetEntry的值也为0;
不好意思,这句话写的不对..........ResetEntry的值得应该是|Image$$RO$$Base|
如果RO的值和你程序烧录起始地址的值不同,(如:你设置的RO=0xc000000,注意这个地址是在指向RAM,而你烧录的代码是在0地址处),这样就需要你烧录在0地址开始处的一小部分启动代码把程序从烧录地址搬运到RO设置的地址中去,但要注意,连接器为你连接的地址是以RO为基准的,这样你可能会有个疑问,为什么程序的运行域是以RO(0xc000000)为基准,但处于FLASH(0地址开始)里的一小部分启动代码还能运行呢,这就是因为程序中用了与地址无关的指令,使得一上电,能够顺利的执行0地址处的启动代码
注意
ENTRY
ResetEntry
b ResetHandler ;for debug
这条指令并不是跳转到RO处,它还是跳到了FLASH里,
再注意以下几句
adr r0, ResetEntry 这里并不是把真正的ResetEntry的值装入了R0,其实装入R0的值是0,可以看看反汇编,你自然明白
ldr r1,BaseOfROM
cmp r0,r1
想必应该可以理解了,如果再不理解,那建议多看看书.
10楼:>>参与讨论作者: sklar 于 2007-4-27 16:09:00 发布:
收了
恩,还得多看了!
11楼:>>参与讨论作者: 时宗 于 2007-4-27 19:21:00 发布:
参考一下CPU datasheet
以2410/2440为例:SDRAM 一般用的是CPU的BANK6和BANK7(各64M),从BANK0到BANK6正好是0X30000000也就是所谓的0地址ResetEntry。
12楼:>>参与讨论作者: luhuaren 于 2007-4-27 19:56:00 发布:
RE
没搞懂楼上的说的意思。
13楼:>>参与讨论作者: sklar 于 2007-4-27 21:22:00 发布:
11楼可以详细点吗
呵呵,11楼说的我也不明白!
期待详细点!
14楼:>>参与讨论作者: pigjiang 于 2007-4-27 22:20:00 发布:
to luhuaren还有个疑问
;****************************************************
;计算拷贝程序在FLASH中的实际位置 *
;****************************************************
-->ldr r2,=CopyProcBeg
sub r1, r2, r1;r2-r1->r1
add r0, r0, r1
ldr r3,=CopyProcEnd
如你所说,前面比较r0和r1结果自然是不等,所以直接运行到这里来了。
请问:CopyProcBeg 是44binit.s里面的一个标号,它所代表的地址到底应该是在FLASH里还是在ram里?如果在FLASH里,那么r2应该小于r1,因为r1=BaseOfROM,那么sub r1, r2, r1这个减法是不是有问题?
主要是觉得这个时候标号CopyProcBeg 应该是在FLASH里的某一个地址。
今天看了一天这段代码也没明白,谢谢指点!
15楼:>>参与讨论作者: luhuaren 于 2007-4-27 22:51:00 发布:
RE
ldr r2,=CopyProcBeg
注意用的是LDR指令
由ADS生成的代码的标号是以设置的RO为基准的,也就是说CopyProcBeg是RAM中的一个地址 。(这解释无敌了)
但是如果你用ADR r2,=CopyProcBeg
这条指令就不一样了,具体怎么不一样,看看指令的解释,但很多地方只是一笔带过,没有很详细的解释,我是看了汇编后代码才明白的
它会生成一条类似下面的指令
sub r0,pc,#0x174 ; #0xc008000
以上我理解的应该没有错误,因为我已经在板子上验证过。
在我不理解这些的时候,到网上搜索过很多资料,但是没有谁确切的解释过这些东东,后来等我弄明白了以后,在LINUX论坛上发现有讨论U-BOOT的帖子对这些做了很明确的解释。
为什么程序的运行域和加载域不同,但启动代码还能在加载域运行,并将加载域的代码拷贝到运行域中去,然后将PC指到运行域中去,在运行域中执行代码,可能是每一个初学者看启动代码时最难理解的地方。理解了这些,其他的,都相对好弄一些/
16楼:>>参与讨论作者: pigjiang 于 2007-4-28 11:09:00 发布:
谢谢luhuaren的解释。
还需进一步参透:)
17楼:>>参与讨论作者: 瑶瑶 于 2007-9-3 10:08:11 发布:
可是为什么我把RObase的地址设置为0x0000时,运行程序时总是发生重启的现象的,都没有运行到我的应用程序,就连开发板中提供的ucos276版本的软件都会有这个问题, 不知道上面的大侠有没有遇到过这个问题,该如何解决?(改成0x0c008000就没有问题了)
18楼:>>参与讨论作者: saga 于 2008-4-16 18:54:06 发布:
to yaoyao
前面要留出0x8000的空间用来建立堆栈的(我觉得他说的不对,目前觉得不对,要是跑裸机RObase=0x0是没问题的(但是要注意把数据段搬到RAM中),要是操作系统定义在RObase=0x0c000000恐怕是不行)
- 最经典的搬运代码分析
- 最经典的数值分析
- 一段经典的javascript代码分析
- jstack分析最耗CPU的代码
- 时下最经典的倒计时的JS代码
- android 最经典的获得网络类型状态的代码
- 代码面试最常用的10大算法(经典)
- 用java求水仙花数最经典的代码
- 15本最经典的技术分析书
- 【经典面试必备】最全的HTTP头部信息分析
- 最经典的一句话
- 最经典的笑话
- 最经典的智力题
- 最经典的算法
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享-不要积分
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享!
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享
- 史上最全!最经典!最无私的Android资料(书籍+代码)分享
- hta类型文件显示异常的解决办法
- QQ界面编程,绝佳的学习材料!
- Visual Studio编译QT出现的unresolved external symbol等问题解决
- 用VB编写ActiveX DLL实现ASP编程
- 搬运啊搬运
- 最经典的搬运代码分析
- 能力的问题
- ActiveX控件用于DHTML开发
- hibernate从头学,hibernate的配置
- 5月24天氣晴
- Hardening guide for Apache 2.2.15 on RedHat 5.4 (64bit edition)
- 问大家一个问题
- dnscat
- 贝尔面试