关于|Image$$RO$$Limit||Image$$RW$$Base||Image$$ZI$$Ba|

本文详细解读了ARM启动代码中几个重要变量的含义与计算过程,包括ROBase、ROLimit、RWBase、RWLimit、ZIBase、ZILimit等,并通过实例说明了它们之间的关系与作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

对于刚学习ARM的人来说,如果分析它的启动代码,往往不明白下面几个变量的含义:

|Image$$RO$$Limit||Image$$RW$$Base||Image$$ZI$$Base|

首先申明我使用的调试软件为ADS1.2,当我们把程序编写好以后,就要进行编译和链接了,在ADS1.2中选择MAKE按钮,会出现一个Errors and Warnings 的对话框,在该栏中显示编译和链接的结果,如果没有错误,在文件的最后应该能看到Image component sizes,后面紧跟的依次是CodeRO DataRW Data ZI Data Debug 各个项目的字节数,最后会有他们的一个统计数据:

Code 163632 RO Data 20939 RW Data 53 ZI Data 17028

Tatal RO size (Code+ RO Data)             184571 (180.25kB)

Tatal RW size(RW Data+ ZI Data)           17081(16.68 kB)

Tatal ROM size(Code+ RO Data+ RW Data)   184624(180.30 kB)

后面的字节数是根据用户不同的程序而来的,下面就以上面的数据为例来介绍那几个变量的计算。

ADSDebug Settings中有一栏是Linker/ARM Linker,在output选项中有一个RO base选项,下面应该有一个地址,我这里是0x0c100000,后面的RW base 地址是0x0c200000,然后在Options选项中有Image entry point ,是一个初始程序的入口地址,我这里是0x0c100000 

有了上面这些信息我们就可以完全知道这几个变量是怎么来的了:

|Image$$RO$$Base| = Image entry point = 0x0c100000 ;表示程序代码存放的起始地址

|Image$$RO$$Limit|=程序代码起始地址+代码长度+1=0x0c100000+Tatal RO size+1

= 0x0c100000 + 184571 + 1 = 0x0c100000 +0x2D0FB + 1

= 0x0c12d0fc

|Image$$RW$$Base| = 0x0c200000 ;RW base 地址指定

|Image$$RW$$Limit| =|Image$$RW$$Base|+ RW Data 53 = 0x0c200000+0x374的倍数,055,共56个单元)

=0x0c200037

|Image$$ZI$$Base| = |Image$$RW$$Limit| + 1 =0x0c200038

|Image$$ZI$$Limit| = |Image$$ZI$$Base| + ZI Data 17028

                            =0x0c200038 + 0x4284

                            =0x0c2042bc

也可以由此计算:

|Image$$ZI$$Limit| = |Image$$RW$$Base| +TatalRWsize(RWData+ZIData) 17081

                            =0x0c200000+0x42b9+3(要满足4的倍数)

                            =0x0c2042bc

加点自己的补充:

其中RO为代码段;RW为已经初始化的全局变量;ZI是未初始化的全局变量,Bootloader要将RW段复制到RAM中并将ZI段清零;

void *mallocPt=Image$$RW$$Limit; //Image$$RW$$Limit+1 = Image$$ZI$$Base

RO code + RO Data RO data应该是const声明的常量

下载到固件中的代码包括RORWZI主要被malloc 函数用到,还有这些概念和堆栈的联系,malloc声明的变量在heap(堆)中,stack(栈)是用来存放临时变量的。

这些概念比较混杂,要理解清楚。

 

总结:

1; C中的指令以及常量被编译后是RO类型数据。

2; C中的未被初始化或初始化为0的变量编译后是ZI类型数据。

3; C中的已被初始化成非0值的变量编译后市RW类型数据。

附:

程序的编译命令(假定C程序名为tst.c):

armcc -c -o tst.o tst.c

armlink -noremove -elf -nodebug -info totals -info sizes -map -list aa.map -o tst.elf tst.o

编译后的信息就在aa.map文件中。

ROM主要指:NAND FlashNor Flash

RAM主要指:PSRAMSDRAMSRAMDDRAM

 

源文档 <http://blog.youkuaiyun.com/fjiale/archive/2009/12/30/5108703.aspx>

源文档 <http://hi.baidu.com/zifengshen/blog/item/d632d88f6bcd0cf0513d9239.html>

<think>好的,我需要回答用户关于ARM汇编中LDR指令以及Image$$RO$$LimitImage$$RW$$BaseImage$$ZI$$Base这些符号含义的问题。首先,我得回忆一下ARM的编译和链接过程,了解这些符号通常在什么情况下出现。记得这些符号和链接脚本有关,用于定义内存区域的起始和结束地址。 用户提到的LDR指令,可能是指加载地址的伪指令,比如LDR Rn, =label这种形式,用来将标号的地址加载到寄存器。需要区分LDR作为指令和伪指令的不同用法。接着,关于Image的那些符号,RO代表只读段,RW是读写数据,ZI是零初始化数据。这些符号由链接器生成,通常在分散加载文件(scatter file)中定义,用于指定各段在内存中的位置。 需要确认这些符号的具体含义,比如RO段结束地址,RW和ZI的基地址。可能还需要解释在启动代码中如何用这些符号来初始化数据段,比如将RO数据从Flash复制到RAM中的RW区域,然后初始化ZI区域为零。 然后要考虑用户可能的疑问点,例如这些符号是如何生成的,链接脚本的作用,以及它们在代码中的具体应用场景。比如在ARM编译工具链中,如armcc或gcc,链接脚本如何定义这些区域,启动代码中如何引用这些符号来完成数据初始化。 还需要检查是否有相关的引用资料,比如用户提供的引用[1]和[2],虽然主要是关于编译器工具和镜像转换,但可能涉及链接过程中的内存分配。需要确保解释准确,必要时引用这些资料。 最后,要生成相关问题,可能涉及链接脚本的编写、启动代码的数据初始化过程、不同编译器的差异等,帮助用户进一步深入理解。</think>### ARM汇编中加载地址与链接符号解析 #### 一、LDR指令的两种形态 1. **直接加载指令**:$LDR\ Rd, [Rn, \#offset]$ 用于从内存地址$Rn+offset$加载数据到寄存器 2. **伪指令形式**:$LDR\ Rd, =imm$ 用于加载32位立即数地址,编译器会自动转换为合适的指令组合[^2] #### 二、链接符号含义 这些符号由ARM链接器生成,与内存区域划分相关: - $Image$$RO$$Limit$:只读段(代码+常量)的结束地址+1 - $Image$$RW$$Base$:读写数据段的起始地址 - $Image$$ZI$$Base$:零初始化数据段的起始地址 示例内存布局: $$ \begin{array}{|c|c|} \hline \text{RO区域} & \text{代码/只读数据} \\ \hline Image$$RO$$Limit & ↓ \\ \hline \text{RW区域} & \text{已初始化全局变量} \\ \hline Image$$ZI$$Base & ↓ \\ \hline \text{ZI区域} & \text{未初始化/零初始化变量} \\ \hline \end{array} $$ #### 三、典型应用场景 在启动代码中用于数据段初始化: ```armasm ; 将RO段中的初始化数据拷贝到RAM LDR r0, =Image$$RO$$Limit ; 源地址 LDR r1, =Image$$RW$$Base ; 目标地址 LDR r2, =Image$$ZI$$Base SUB r2, r2, r1 ; 需要复制的数据长度 copy_loop: CMP r2, #0 LDMIA r0!, {r3-r6} STMIA r1!, {r3-r6} SUB r2, r2, #16 BGT copy_loop ; 初始化ZI区域为0 MOV r3, #0 LDR r1, =Image$$ZI$$Base LDR r2, =Image$$ZI$$Limit zi_init: CMP r1, r2 STRLO r3, [r1], #4 BLO zi_init ``` #### 四、编译器支持差异 不同编译器对符号命名有细微差别: - armcc:保持$Image$$XX$$YY$格式 - gcc:通常使用$__etext$, $__data_start__$等符号 - IAR:使用$__ICFEDIT_region_ROM_end__$等自定义符号 [^1]: 引用自ARM镜像转换工具文档 : 参考ARM编译器特性对比分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值