<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Computer, Electron and Technology &#187; zi</title>
	<atom:link href="http://www.donevii.com/post/tag/zi/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>关注技术、移动互联网以及一切 GEEK &#38; NERD 的事情</description>
	<lastBuildDate>Wed, 21 Dec 2011 10:49:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>RO段、RW段和ZI段</title>
		<link>http://www.donevii.com/post/638.html</link>
		<comments>http://www.donevii.com/post/638.html#comments</comments>
		<pubDate>Fri, 28 Nov 2008 02:14:38 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[ro]]></category>
		<category><![CDATA[rw]]></category>
		<category><![CDATA[zi]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=638</guid>
		<description><![CDATA[一直以来对于ARM体系中所描述的RO，RW和ZI数据存在似是而非的理解，这段时间对其仔细了解了一番，发现了一些规律，理解了一些以前书本上有的但是不理解的东西，我想应该有不少人也有和... ]]></description>
			<content:encoded><![CDATA[<p>一直以来对于ARM体系中所描述的RO，RW和ZI数据存在似是而非的理解，这段时间对其仔细了解了一番，发现了一些规律，理解了一些以前书本上有的但是不理解的东西，我想应该有不少人也有和我同样的困惑，因此将我的一些关于RO，RW和ZI的理解写出来，希望能对大家有所帮助。<br />
要了解RO，RW和ZI需要首先了解以下知识：<br />
ARM程序的组成<br />
此处所说的“ARM程序”是指在ARM系统中正在执行的程序，而非保存在ROM中的bin映像（image）文件，这一点清注意区别。<br />
一个ARM程序包含3部分：<a href="http://www.donevii.com/post/tag/ro" class="st_tag internal_tag" rel="tag" title="Posts tagged with ro">RO</a>，RW和ZI<br />
RO是程序中的指令和常量<br />
RW是程序中的已初始化变量<br />
ZI是程序中的未初始化的变量<br />
由以上3点说明可以理解为：<br />
RO就是readonly，<br />
RW就是read/write，<br />
ZI就是zero<br />
ARM映像文件的组成<br />
所谓ARM映像文件就是指烧录到ROM中的bin文件，也成为image文件。以下用Image文件来称呼它。<br />
Image文件包含了RO和RW数据。<br />
之所以Image文件不包含ZI数据，是因为ZI数据都是0，没必要包含，只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。<br />
Q：为什么Image中必须包含RO和RW？<br />
A：因为RO中的指令和常量以及RW中初始化过的变量是不能像ZI那样“无中生有”的。<br />
ARM程序的执行过程<br />
从以上两点可以知道，烧录到ROM中的image文件与实际运行时的ARM程序之间并不是完全一样的。因此就有必要了解ARM程序是如何从ROM中的image到达实际运行状态的。<br />
实际上，RO中的指令至少应该有这样的功能：<br />
1. 将RW从ROM中搬到RAM中，因为RW是变量，变量不能存在ROM中。<br />
2. 将ZI所在的RAM区域全部清零，因为ZI区域并不在Image中，所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量，同理：变量不能存在ROM中<br />
在程序运行的最初阶段，RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。<br />
说了上面的可能还是有些迷糊，RO，RW和ZI到底是什么，下面我将给出几个例子，最直观的来说明RO，<a href="http://www.donevii.com/post/tag/rw" class="st_tag internal_tag" rel="tag" title="Posts tagged with rw">RW</a>，ZI在C中是什么意思。<br />
1; RO<br />
看下面两段程序，他们之间差了一条语句，这条语句就是声明一个字符常量。因此按照我们之前说的，他们之间应该只会在RO数据中相差一个字节（字符常量为1字节）。<br />
Prog1：<br />
#include &lt;stdio.h&gt;<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog2：<br />
#include &lt;stdio.h&gt;<br />
const char a = 5；<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog1编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data <a href="http://www.donevii.com/post/tag/zi" class="st_tag internal_tag" rel="tag" title="Posts tagged with zi">ZI</a> Data Debug<br />
948 60 0 96 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1008 ( 0.98kB)<br />
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)<br />
================================================================================<br />
Prog2编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data ZI Data Debug<br />
948 61 0 96 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1009 ( 0.99kB)<br />
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)<br />
================================================================================<br />
以上两个程序编译出来后的信息可以看出：<br />
Prog1和Prog2的RO包含了Code和RO Data两类数据。他们的唯一区别就是Prog2的RO Data比Prog1多了1个字节。这正和之前的推测一致。<br />
如果增加的是一条指令而不是一个常量，则结果应该是Code数据大小有差别。<br />
2; RW<br />
同样再看两个程序，他们之间只相差一个“已初始化的变量”，按照之前所讲的，已初始化的变量应该是算在RW中的，所以两个程序之间应该是RW大小有区别。<br />
Prog3：<br />
#include &lt;stdio.h&gt;<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog4：<br />
#include &lt;stdio.h&gt;<br />
char a = 5；<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog3编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data ZI Data Debug<br />
948 60 0 96 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1008 ( 0.98kB)<br />
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)<br />
================================================================================<br />
Prog4编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data ZI Data Debug<br />
948 60 1 96 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1008 ( 0.98kB)<br />
Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1009 ( 0.99kB)<br />
================================================================================<br />
可以看出Prog3和Prog4之间确实只有RW Data之间相差了1个字节，这个字节正是被初始化过的一个字符型变量“a”所引起的。<br />
3; ZI<br />
再看两个程序，他们之间的差别是一个未初始化的变量“a”，从之前的了解中，应该可以推测，这两个程序之间应该只有ZI大小有差别。<br />
Prog3：<br />
#include &lt;stdio.h&gt;<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog4：<br />
#include &lt;stdio.h&gt;<br />
char a；<br />
void main(void)<br />
{<br />
;<br />
}<br />
Prog3编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data ZI Data Debug<br />
948 60 0 96 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1008 ( 0.98kB)<br />
Total RW Size(RW Data + ZI Data) 96 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)<br />
================================================================================<br />
Prog4编译出来后的信息如下：<br />
================================================================================<br />
Code RO Data RW Data ZI Data Debug<br />
948 60 0 97 0 Grand Totals<br />
================================================================================<br />
Total RO Size(Code + RO Data) 1008 ( 0.98kB)<br />
Total RW Size(RW Data + ZI Data) 97 ( 0.09kB)<br />
Total ROM Size(Code + RO Data + RW Data) 1008 ( 0.98kB)<br />
================================================================================<br />
编译的结果完全符合推测，只有ZI数据相差了1个字节。这个字节正是未初始化的一个字符型变量“a”所引起的。<br />
注意：如果一个变量被初始化为0，则该变量的处理方法与未初始化华变量一样放在ZI区域。<br />
即：<a href="http://www.donevii.com/post/tag/arm" class="st_tag internal_tag" rel="tag" title="Posts tagged with arm">ARM</a> C程序中，所有的未初始化变量都会被自动初始化为0。<br />
总结：<br />
1; C中的指令以及常量被编译后是RO类型数据。<br />
2; C中的未被初始化或初始化为0的变量编译后是ZI类型数据。<br />
3; C中的已被初始化成非0值的变量编译后市RW类型数据。<br />
附：<br />
程序的编译命令（假定C程序名为tst.c）：<br />
armcc -c -o tst.o tst.c<br />
armlink -noremove -elf -nodebug -info totals -info sizes -map -list aa.map -o tst.elf tst.o<br />
编译后的信息就在aa.map文件中。<br />
ROM主要指：NAND Flash，Nor Flash<br />
RAM主要指：PSRAM，SDRAM，SRAM，DDRAM</p>
]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/638.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

