Keil编译产生的RO,RW和ZI是什么

发布者:平静宁静最新更新时间:2019-04-18 来源: eefocus关键字:Keil  编译 手机看文章 扫描二维码
随时随地手机看文章

要了解RO,RW和ZI需要首先了解以下知识:

1、ARM程序的组成:
        此处所说的“ARM程序”是指在ARM系统中正在执行的程序,而非保存在ROM中的bin映像(image)文件,这一点清注意区别。
         一个ARM程序包含3部分:RO,RW和ZI。RO是程序中的指令和常量;RW是程序中的已初始化变量;ZI是程序中的未初始化的变量.
         由以上3点说明可以理解为:RO就是readonly,RW就是read/write,ZI就是zero
 
          2、ARM映像文件的组成
         所谓ARM映像文件就是指烧录到ROM中的bin文件,也称为image文件。以下用Image文件来称呼它。

         Image文件包含了RO和RW数据。之所以Image文件不包含ZI数据,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。


            Q:为什么Image中必须包含RO和RW?
            A:因为RO中的指令和常量以及RW中初始化过的变量是不能像ZI那样“无中生有”的。
 
         3、ARM程序的执行过程
         从以上两点可以知道,烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。因此就有必要了解ARM程序是如何从ROM中的image到达实际运行状态的。
            实际上,RO中的指令至少应该有这样的功能:
            1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
            2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中
            在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。


            说了上面的可能还是有些迷糊,RO,RW和ZI到底是什么,下面我将给出几个例子,最直观的来说明RO,RW,ZI在C中是什么意思。
1、RO
            看下面两段程序,他们之间差了一条语句,这条语句就是声明一个字符常量。因此按照我们之前说的,他们之间应该只会在RO数据中相差一个字节(字符常量为1字节)。
            Prog1:
            #include
            void main(void)
            {
            ;

            }


            Prog2:
            #include
            const char a = 5;
            void main(void)
            {
            ;
            }
            Prog1编译出来后的信息如下:
            =================================================

            Code RO Data RW Data ZI Data Debug
            948    60           0             96 0 Grand Totals

            =================================================
            Total RO Size(Code + RO Data) 1008 ( 0.98kB)
            Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
            =================================================
            Prog2编译出来后的信息如下:
            =================================================
            Code RO Data RW Data ZI Data Debug
            948   61            0             96           0 Grand Totals
            =================================================
            Total RO Size(Code + RO Data) 1009 ( 0.99kB)
            Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
            =================================================
            以上两个程序编译出来后的信息可以看出:
            Prog1和Prog2的RO包含了Code和RO Data两类数据。他们的唯一区别就是Prog2的RO Data比Prog1多了1个字节。这正和之前的推测一致。
            如果增加的是一条指令而不是一个常量,则结果应该是Code数据大小有差别。


2、RW
            同样再看两个程序,他们之间只相差一个“已初始化的变量”,按照之前所讲的,已初始化的变量应该是算在RW中的,所以两个程序之间应该是RW大小有区别。
            Prog3:
            #include
            void main(void)
            {
            ;
            }
            Prog4:
            #include
            char a = 5;
            void main(void)
            {
            ;
            }
            Prog3编译出来后的信息如下:
            ==================================================
            Code RO Data RW Data ZI Data Debug
            948    60           0             96 0 Grand Totals
            ==================================================
            Total RO Size(Code + RO Data) 1008 ( 0.98kB)
            Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
            ==================================================
            Prog4编译出来后的信息如下: 
   ==================================================
            Code RO Data RW Data ZI Data Debug
            948    60          1              96 0 Grand Totals
            ==================================================
            Total RO Size(Code + RO Data) 1008 ( 0.98kB)
            Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)
            ==================================================
            可以看出Prog3和Prog4之间确实只有RW Data之间相差了1个字节,这个字节正是被初始化过的一个字符型变量“a”所引起的。
 
3、ZI
            再看两个程序,他们之间的差别是一个未初始化的变量“a”,从之前的了解中,应该可以推测,这两个程序之间应该只有ZI大小有差别。
            Prog3:
            #include
            void main(void)
            {
            ;
            }
            Prog4:
            #include
            char a;
            void main(void)
            {
            ;
            }
            Prog3编译出来后的信息如下:
            ====================================================
            Code RO Data RW Data ZI Data Debug
            948    60           0             96        0 Grand Totals
            ====================================================
            Total RO Size(Code + RO Data) 1008 ( 0.98kB)
            Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
            ====================================================
            Prog4编译出来后的信息如下:
            ====================================================
            Code RO Data RW Data ZI Data Debug
            948    60           0             97 0 Grand Totals
            ====================================================
            Total RO Size(Code + RO Data) 1008 ( 0.98kB)
            Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)
            Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)
            ====================================================
            编译的结果完全符合推测,只有ZI数据相差了1个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。
            注意:如果一个变量被初始化为0,则该变量的处理方法与未初始化华变量一样放在ZI区域。
            即:ARM C程序中,所有的未初始化变量都会被自动初始化为0。
总结:
            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 Flash,Nor Flash
            RAM主要指:PSRAMSDRAM,SRAM,DDRAM

[1] [2]
关键字:Keil  编译 引用地址:Keil编译产生的RO,RW和ZI是什么

上一篇:MDK出现红叉,程序编译正常没有错误
下一篇:MDK编译后生成bin文件占用FLASH大小说明

推荐阅读最新更新时间:2024-11-21 04:42

arm 内核编译
1、决定在什么地方编译你的内核 首先,你需要决定在什么地方编译你的ARM Linux内核。你的HOME目录是一个编译内核的好地方。如果你希望使用其它的目录,可以适当地取代$HOME目录。但是不推荐在/usr/src/linux目录下编译内核。 2、决定内核的版本 对于任何的内核版本 x.y.z, ◎x-主要版本号 ◎y-次要版本号,其中偶数表示稳定版本,奇数表示开发或测试版本 ◎z-补丁的级别 在ARM的内核树中,你会发现内核版本号后面有一个后缀:-rmkN, or -vrsN,其中'N'是补丁版本号。例如,2.4.26-vrs1表明这个ARM内核的补丁应该应用于2.4.26的内核。 注意:从2.6.0-tes
[单片机]
嵌入式问题(codewarrior编译、下载程序)
开始学习arm裸机程序,之前就在准备着,可是一直进展的不是很顺;原因是自己效率不是很高,怕失败;不过突然顿悟了,与其慢慢的做自己会的东西不如突破下自己往前走因为怕失败的人终究是要失败的;但是有个前提--得有目标不能今天学linux,明天又学arm裸机;所以从今天开始学arm裸机程序。于是决定,早睡早起,遇到问题勇于尝试而不是死命的想,做技术的可以先会做了再明白为什么这么做。 前面开题,下面说说学习过程中遇到的问题,无论是硬件问题还是软件问题,无论是板子的问题还是自身的问题都将记录在日志中便于今后学习。 今天遇到问题:1.ads编译不出arm可执行的二进制文件2.bin程序下不近开发板。 解决方案: 问题1:
[单片机]
s3c2440 gcc交叉编译工具链制作
前言: 因为准备学习lwip,之前在stm32上移植跟着教程走得差不多了,但是用的keil。所以想在一个新平台移植一下巩固巩固,正好有2440的板子,也学一下gcc-make这样的开发流程,配套的编译器很老,编译配套的linux2.6.22.6内核还是没问题的,但是当我用裸机模板创建一个包含lwip的代码的工程时,编译就会出现以下错误: collect2: ld terminated with signal 11 , core dumped /home/streleizia/gcc-3.4.5-glibc-2.3.6/bin/../lib/gcc/arm-linux/3.4.5/../../../../arm-linux/bin/
[单片机]
Keil STM32调试,使用ST-Link下载程序时提示“flash timeout.reset the target and try it again”
参考: 很郁闷,买来没多久的 STM32F4-DISCOVERY 就挂了? STM32F103RB Jlink调试的时候出现flash timeout.reset the target and try it again 看完以上网友的方案后本人使用FlyMcu读芯片,内容提示芯片被锁。遂想下载一个程序试试,不想程序可以下载,然后再读芯片时已正常。 返回Keil使用ST-Link也可正常使用。 从网友结论及本人测试,些次出现“flash timeout.reset the target and try it again”是由芯片被锁导至。 以下方法未试 问题已经解决了。是keil的环境没有设置好。导致程序进步去。应该是没有Re
[单片机]
<font color='red'>Keil</font> STM32调试,使用ST-Link下载程序时提示“flash timeout.reset the target and try it again”
Keil C51对C语言的关键词扩展之七: data
8051单片机内部256字节RAM,低128字节既可直接寻址,又可间接寻址,高128字节RAM只能间接寻址(直接寻址方式下,高128字节被映射到SFR特殊功能寄存器)。内部RAM中包含16字节可位寻址区域,该区域起始地址为20H。 内部RAM存储区被分为三种不同的存储区类型:data,idata,bdata。 1)data指低128字节,以直接寻址方式访问存在该区域的变量。 2)idata指全部256字节,该存储类型编译后的代码以间接寻址方式访问内存。 3)bdata指16字节可位寻址区,该区域地址范围为20H-2FH。使用bdata能够定义可位寻址的变量。 汇编语言内部RAM直接寻址方式,示例: MOV A,10H /* 将
[单片机]
arm-linux,arm-elf-交叉编译环境下载地址
最常用的编译版本是arm-linux-gcc-3.4.1 和 arm-linux-3.3.2 的,现在的嵌入式开发基本上用的是这些,3.4.1的用于编译2.6的内核,而3.3.2的常用于编译busybox,和bootloader(u- boot),编译的版本配合不好的话就会出错,所以要选择好编译版本,如果这个版本不行的话,可以试试其他的版本,在uclinux上用的多的就是 arm-elf-tools-20030314 http://www.handhelds.org/download/projects/toolchain/arm-linux-gcc-3.4.1.tar.bz2 http://www.handhelds.org/do
[单片机]
创意电子 16nm TCAM 编译程序成功完成设计定案
创意电子公司 (Global Unichip Corp., GUC),为了服务高速网络应用ASIC芯片客户,已成功在台积电(TSMC)的16FFC制程技术完成最新高速 TCAM 编译程序之设计定案。 公司也表示,预计在 2018年3 月在 TSMC 的 7 奈米制程完成设计定案。 最新的 TCAM 编译程序采用了成功量产的 IP,适用于交换器/路由器应用。 这款新的编译程序具备 1GHz 效能及理想功耗,能够配合多种高速网络产品的设计。 对于网络、AI 和 SCM (储存级内存) 应用而言,这款编译程序是重要的 IP 组件。 创意电子的 TCAM 编译程序支持 8 到 512 的字符深度和 16 到 160 的位宽度。 TCAM
[半导体设计/制造]
keil中GD32 MCU IAP中APP的存储地址如何设置?
前面和大家聊过什么是IAP(有不懂的小伙伴请看下前面的视频哦),那么IAP中APP的存储地址该如何设置呢 以keil为例,打开工程的option选项卡: 将IROM1中的地址改为你想要保存的位置,比如0x08008000开始的位置: 这样通过keil烧录,程序就自动下载到从0x08008000起始的flash区域哦。 如果你想要通过IAP烧录APP,也一定要烧录到0x08008000起始的flash区域哦,否则跳转到APP中执行程序就会出错的。
[单片机]
<font color='red'>keil</font>中GD32 MCU IAP中APP的存储地址如何设置?
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved