<?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; brew</title>
	<atom:link href="http://www.donevii.com/tags/brew/feed" rel="self" type="application/rss+xml" />
	<link>http://www.donevii.com</link>
	<description>DoneVII CET &#38; CPPLITE</description>
	<lastBuildDate>Sun, 17 Jan 2010 05:32:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>在BREW程序中调用另一个mod的分析</title>
		<link>http://www.donevii.com/post/817.html</link>
		<comments>http://www.donevii.com/post/817.html#comments</comments>
		<pubDate>Sun, 17 May 2009 07:10:27 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[brew]]></category>
		<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[mod]]></category>
		<category><![CDATA[动态加载]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=817</guid>
		<description><![CDATA[近日读到这样一段程序。可以在程序运行时调用另一个mod文件并执行。这样可以做到应用自升级，压缩程序文件等实用的功能。
 
 要想理解这点，先看一下正常的BREW程序加载过程。
 BREW程序... ]]></description>
			<content:encoded><![CDATA[<p>近日读到这样一段程序。可以在程序运行时调用另一个mod文件并执行。这样可以做到应用自升级，压缩程序文件等实用的功能。</p>
<p> </p>
<p> 要想理解这点，先看一下正常的BREW程序加载过程。</p>
<p> BREW程序的入口，即相当于c程序的main，是位于AEEModGen.c中的AEEMod_Load函数。这可以从mak文件的连接选项中看出来。</p>
<p> </p>
<p>LINK_ORDER = -first AEEMod_Load</p>
<p> </p>
<p> 这个选项使得链接程序将该函数放在程序文件的0地址处。函数的定义如下：</p>
<p> </p>
<p>int AEEMod_Load(IShell *pIShell, void *ph, IModule **ppMod)</p>
<p>{</p>
<p>  <span> </span>// Invoke helper function to do the actual loading.</p>
<p>   return AEEStaticMod_New(sizeof(AEEMod),pIShell,ph,ppMod,NULL,NULL);</p>
<p>}</p>
<p>  </p>
<p>  BREW底层调用这个函数，需要提供三个参数。pIShell是ISHELL接口的指针，有了它就可以创建和访问其它接口。ph是helper function类函数的函数列表指针，有了它就可以调用MALLOC等函数。ppMod是用于返回给BREW底层的地址，存储生成的module的信息。</p>
<p>  AEEMod_Load函数调用了AEEStaticMod_New函数。在这个函数中初始化了module数据结构，ppMod就是指向它的。函数结束后返回BREW底层。</p>
<p>  BREW底层稍后通过存储在module数据结构中的函数指针，调用同样位于AEEModGen.c中的AEEMod_CreateInstance函数，生成该Module的某一个Applet实例。在这个函数中会调用到我们所编写的AEEClsCreateInstance函数。在我们这个函数中注册了HandleEvent函数和FreeAppDate函数。这些信息同样通过一个applet数据结构指针返回给BREW底层。这之后，BREW会通过给HandleEvent发各种Event，来驱动程序运行。</p>
<p> </p>
<p>  通过这整个过程，可以总结出BREW程序运行的必要条件。</p>
<p>  程序必须得到IShell指针，Helper Function指针，这样程序中对BREW底层各种函数的调用才能进行。BREW底层必须知道两个地址，通过它们，可以将Event传递给程序，调用FreeAppDate函数。</p>
<p>  因此，想在程序中调用另外一个mod,只需要想办法把程序里的IShell指针，Helper Function指针传递给mod，同时得到mod中的HandleEvent函数，FreeAppDate函数的地址就可以了。</p>
<p>  剩下的问题就是,程序怎样和mod文件交互呢，mod文件的格式是怎样的？</p>
<p> </p>
<p>  生成mod的mak文件最后一般有这样两句话，</p>
<p> </p>
<p>ld *.o a.elf</p>
<p>fromelf &#8211;bin a.elf a.mod</p>
<p> </p>
<p>  arm链接器ld生成ELF格式，之后用格式转换工具fromelf将ELF文件转换成mod文件。</p>
<p>  ELF文件是带格式的可执行文件，对它的执行要靠操作系统的解析来进行。而通过&#8211;bin选项生成的mod文件，格式却是plain binary,即赤裸裸的二进制机器指令，其实是无格式的。只要将mod文件载入内存，跳转到它的0地址处，就可以一条条指令的执行下来。和mod文件交互，也就是要安排好mod文件0地址处的内容，知道mod文件的调用者会传入什么东西，mod文件会返回什么东西。</p>
<p> </p>
<p>  </p>
<p>  下面来看一种实际的调用方法吧。代码如下：</p>
<p> </p>
<p>typedef int (*RunLoadMod)(IShell *pIShell, void *ph, IModule **ppMod);</p>
<p> </p>
<p>pData = MyLoadZip(pIShell);</p>
<p>if( !pData )</p>
<p>return EFAILED;</p>
<p>DBGPRINTF(&#8220;to RunLoadMod&#8221;);</p>
<p>if( SUCCESS != ((RunLoadMod)pData)(pIShell,ph,&amp;pOrgMod) )</p>
<p>{</p>
<p>DBGPRINTF(&#8220;RunLoadMod_Err&#8221;);</p>
<p>goto Crt_Err;</p>
<p>}</p>
<p>  </p>
<p>  这段程序将mod文件读入内存，放在pData缓冲区内，用((RunLoadMod)pData)(pIShell,ph,&amp;pOrgMod)一句执行之。RunLoadMod只不过是用typedef定义的一种函数指针类型。这句话的意思相当于是为待调用的mod文件准备好pIShell,ph,pOrgMod三个数据后，直接跳到内存中的mod文件的第一个字节处，将它当做普通机器指令一样执行。这种方法调用的mod文件，应是一个用完整的BREW框架编译后生成的。0地址处放下的是AEEMod_Load函数。Mod文件直接将Applet信息传递给BREW底层，注册HandleEvent函数。实际上是Mod文件取代了调用者的位置。</p>
<p>  </p>
<p>  但是这段程序很可能会运行失败。因为BREW底层除了传参外，还做了其它事情。这在AEEStdlib.h中可以看出。</p>
<p> </p>
<p>#define GET_HELPER()      (*(((AEEHelperFuncs **)AEEMod_Load) &#8211; 1))</p>
<p>#define GET_HELPER_VER()  (*((uint32 *)(((byte *)AEEMod_Load) &#8211; sizeof(AEEHelperFuncs *) &#8211; sizeof(uint32))))</p>
<p> </p>
<p>  这两个宏定义可以看成是两个全局常量。第一个是BREW Helper Function的函数指针表，第二个是函数指针表的版本号。上面提到的通过参数传递Helper Function函数指针，是只在模拟器上成立的。手机上其实是通过全局常量形式传递的。为保证mod可以正常运行，也应在缓冲区前保存这两个常量。</p>
<p> </p>
<p>  这种“冒名顶替”的方式，对于只想压缩一下mod的应用来说是完全可以的。但有时，我们希望新调用的mod只是整个应用的一小部分，调用者继续存在。这就需要调用者充当BREW底层的一部分角色，记住mod返回的各种信息，在适当的时候调用mod中的相应函数。新调用的mod如果想要取得主mod的信息，类似于上面提到的HelperFuncs全局常量指针的方法是个可行的选择。</p>
<p> </p>
<p>  其实知道了BREW程序的加载过程，就可以比较灵活的达到调用mod的目的，甚至BREW程序架构都是可以改动的。但是改动之后，如何在模拟器上进行调试就又成了一个问题。</p>
<p> </p>
<p>  程序中调用mod的技巧，在国外几年前就已得到了应用。甚至有家公司专门开发了利用这个技巧压缩mod的工具。</p>
<p> </p>
<p>http://www.s-cradle.com/english/products/sophiacompress_brew/index.html</p>
<p> </p>
<p>参考文章：</p>
<p> </p>
<p>1.How to build A mod to load B mod?<span> </span></p>
<p> </p>
<p>http://brewforums.qualcomm.com/showthread.php?t=11637</p>
<p> </p>
<p>2.How to run mod file that is loaded in the HEAP&#8230;</p>
<p> </p>
<p>http://brewforums.qualcomm.com/showthread.php?t=18413&amp;highlight=modloader</p>
<p> </p>
<p>3.深入BREW模块加载机制</p>
<p> </p>
<p>http://nicefuture.ycool.com/post.722858.html</p>
<p> </p>
<p>4.深度剖析BREW实现原理收藏</p>
<p> </p>
<p>http://blog.csdn.net/Gemsea/archive/2006/09/07/1190206.aspx</p>

	<h4>相关文章</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.donevii.com/post/820.html" title="How to run mod file that is loaded into HEAP (2009-05-17)">How to run mod file that is loaded into HEAP</a> (1)</li>
	<li><a href="http://www.donevii.com/post/744.html" title="《深入BREW》 &#8211; 硬件基础 (2009-01-18)">《深入BREW》 &#8211; 硬件基础</a> (0)</li>
	<li><a href="http://www.donevii.com/post/746.html" title="《深入BREW》 &#8211; BREW原理 (2009-01-18)">《深入BREW》 &#8211; BREW原理</a> (1)</li>
	<li><a href="http://www.donevii.com/post/479.html" title="[转] 嵌入式单地址空间中实现动态加载的过程 (2008-09-11)">[转] 嵌入式单地址空间中实现动态加载的过程</a> (0)</li>
	<li><a href="http://www.donevii.com/post/481.html" title="[转] 实现动态加载VXWORKS .O/.OUT模块 (2008-09-11)">[转] 实现动态加载VXWORKS .O/.OUT模块</a> (1)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/817.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[转] Symbian OS 9 可执行文件格式</title>
		<link>http://www.donevii.com/post/802.html</link>
		<comments>http://www.donevii.com/post/802.html#comments</comments>
		<pubDate>Fri, 24 Apr 2009 08:32:55 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[brew]]></category>
		<category><![CDATA[c/c++/c#]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mtk]]></category>
		<category><![CDATA[ELF]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[Symbian]]></category>
		<category><![CDATA[可执行文件]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=802</guid>
		<description><![CDATA[原译者：陈啸天(cxt_programmer)
请关注www.cpplite.com及bbs.cpplite.com
声明：原文出自大牛——ScreenShot作者A ntony  P ranata 。本人英语很烂，之所以瞎译出来一是为了以后参考方便一些，二是在翻译的过... ]]></description>
			<content:encoded><![CDATA[<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">原译者：<span style="font-weight: bold; font-size: 16pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">陈啸天(cxt_programmer)<br />
请关注<a href="http://www.cpplite.com">www.cpplite.com</a>及bbs.cpplite.com</span></span></span></span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;"><!--EndFragment--></span></span></p>
<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">声明：原文出自大牛——ScreenShot作者A</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ntony</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"> P</span> <span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ranata</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。本人英语很烂，之所以瞎译出来一是为了以后参考方便一些，二是在翻译的过程中自己能更仔细的看～。强烈建议大家对照英文原版来看哈。另外有些地方没有翻译，大家意会哈。</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">原文地址：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span><a href="http://www.antonypranata.com/articles/new-symbian-os-9-executable-file-format-e32image"><span class="16" style="font-size: 10pt; color: #0000ff; font-family: 'Times New Roman'; text-decoration: underline; mso-spacerun: 'yes';">http://www.antonypranata.com/articles/new-symbian-os-9-executable-file-format-e32image</span> </a></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; margin-right: 24pt;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">前言：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">Symbian OS 9<span style="font-family: 宋体;">已经发布，与之前的版本相比，OS 9增加了许多新特性并有了一些改变，其中之一就是新的可执行文件格式（E32Image）。本文主要讨论了这个新的文件格式，如果你想了解OS 9之前的可执行文件格式，可以阅读一下我之前关于此话题的文章。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">在开始之前，请注意我们仅仅讨论的是真机环境下的可执行文件格式（ARM）。为什么不讨论模拟器环境呢？因为运行在模拟器的可执行文件使用了一种不同的文件格式（Cxt注：模拟器下的可执行文件应该是windows的PE格式），如果你之前不了解任何一个平台的可执行文件格式，下面的介绍会更好的帮助你理解E32文件格式。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">这篇文章是在Symbian网站或者其他拥有Symbian OS licensees的厂商（例如Nokia）提供的公开信息（文档）之上完成的。虽然我目前在一家手机厂商工作，但这篇文章涉及内容的正确性并未经过公司的核对。尽管我已经紧握最大的努力确保这篇文章内容的正确，但我仍然无法100％保证（Cxt音：看看，大牛总是很谦虚的，我们要做一个谦虚的人哈）。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';">EABI<span style="font-family: 宋体;">介绍（</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Introduction to EABI</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">ABI<span style="font-family: 宋体;">（应用程序二进制接口，Application Binary Interface）是由ARM及其合作伙伴们制定的一个标准，它定义了如何编译、链接，以及其他工具怎样生成obj文件和可执行文件。这个标准可以让不同编译器生成的obj文件互通，例如可以把不同编译器生成的obj文件组合在一起。EABI（嵌入式应用程序二进制接口，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Embedded Application Binary Interface</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）也是这样的标准，它就是嵌入式平台的ABI。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">写这篇文章的时候，有两种编译器可以用于Symbian OS 9——RVCT（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">RealView Compilation Tools</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）和GCCE。RVCT是ARM公司开发的编译器，license费用可达数千美元；与此不同，GCCE是一个由</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">CodeSourcery</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">开发的免费编译器；顾名思义，GCCE基于GNU编译器。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    EABI<span style="font-family: 宋体;">编译器生成的格式为ELF（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Executable and Linking Format</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">），它不同于Symbian OS 9之前的PE格式。然而Symbian OS并不使用ELF格式，因为Symbian OS通常在大小受限的ROM上，而标准ELF文件的尺寸通常又很大。所以Symbian把标准的ELF转换为Symbian特有的E32Image格式。如果你有安装Symbian SDK，可以在epoc32\tools目录下找到用于把ELF转换为E32Image的工具，它叫elf2e32.exe。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">下图展示了Symbian OS 9的新工具链。如你所见，最后生成的是由elf2e32.exe转换完的Symbian特有格式——E32Image。Symbian网站和SDK中有更多关于这方面的介绍。（Cxt注：SDK help：</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span class="15" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">»</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span><a href="mk:@MSITStore:C:\Symbian\9.1\S60_3rd_MR\S60Doc\Symbian_DevLib.chm::/doc_source/index.html"><span class="16" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Symbian OS v9.1</span> </a></span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span class="15" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">»</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span><a href="mk:@MSITStore:C:\Symbian\9.1\S60_3rd_MR\S60Doc\Symbian_DevLib.chm::/doc_source/N1035A/index.html"><span class="16" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Symbian OS Tools And Utilities</span> </a></span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span class="15" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">»</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span><a href="mk:@MSITStore:C:\Symbian\9.1\S60_3rd_MR\S60Doc\Symbian_DevLib.chm::/doc_source/N1035A/BuildTools/index.html"><span class="16" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Build tools guide</span> </a></span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span class="15" style="font-size: 10pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">»</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> The native build targets</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">目录下有全面详细的文档介绍）。通常你不会看到下图所示的流程，因为Symbian OS使用一些脚本工具（例如bldmake、abld等）自动完成。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt; text-align: center;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image1.png" alt="" width="409" height="513" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">如果你不熟悉.dso文件也没关系，它其实与Symbian OS 9以及其他平台的.lib文件是一样的。（Cxt注：.dos提供导出的函数的名称和位置，DLL包含实际的函数和数据。）</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">我在前面说过，ELF文件通常都很大，不适合用于手机。减少ELF尺寸的方法之一是把函数名字替换为序号。例如可以把MyFunction()替换为1，正如你期望的，这种方法可以极大的减小ELF的尺寸，特别是当函数名称很长时（例如</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ThisIsVeryLongFunction</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">()<span style="font-family: 宋体;">）这种效果更加明显。额等等！如此一来，如何找到序号和函数名称之间的对应关系呢？别急，我们有一个.def文件，它提供了序号与函数名之间的对应关系。（Cxt：呼</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">……</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';">E32Image<span style="font-family: 宋体;">概述（</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Overview of E32Image</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">现在让我们来看看E32Image吧。与其他标准的可执行文件类似，它也包含头（Header）、代码段（Code Section）、数据段（Data Section）、导入段（Import Section）等等。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: center;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image2.png" alt="" width="234" height="316" /><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">上图展示了E32文件格式，与其他可执行文件格式一样，最开始的部分是header。下面我会着重介绍E32 header里面都有些什么东东。在Header之下还有一些其它section（Cxt：这部分大家意会哈^_^）：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Code section, contains all the object files (.o) of your source code as well as export address table that lists all the exported functions.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">BSS section, contains un-initialized data.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Data section, contains initialized data.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Import section, contains the information about all imported functions used by your program.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">·</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Relocation section, contains relocation table needed by Symbian OS loader to load your program.</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';">E32Image<span style="font-family: 宋体;">头（</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Header of E32Image</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">头信息也许是最有趣的部分，因为它包含了可执行文件的很多信息。E32ImageHeader的声明可以在SDK的\epoc32\include\f32image.h中找到。看看class </span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderV</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的声明，这可是E32Image文件格式完整的头信息。如果你仔细看了class </span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderV</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，你会发现它继承了E32HeaderComp（E32HeaderComp继承了E32ImageHeader）。下图对它们的关系做了更好的说明：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt; text-align: center;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image3.png" alt="" width="208" height="208" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">下面的代码片段展示了</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">EImageHeader</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">EImageHeaderComp</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">和</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderV</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的声明，请注意我删减了部分函数以及注释以便于更清晰的查看：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">class</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> E32ImageHeader</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">{</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">public</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">:</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iUid1;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iUid2;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iUid3;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iUidChecksum;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iSignature; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// &#8217;EPOC&#8217;</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iHeaderCrc; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// CRC-32 of entire header</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iModuleVersion; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Version number for this executable (used in link resolution)</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iCompressionType; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Type of compression used (UID or 0 for none)</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TVersion iToolsVersion; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Version of PETRAN/ELFTRAN which generated this file</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iTimeLo;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iTimeHi;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iFlags; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// 0 = exe, 1 = dll, 2 = fixed address exe</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iCodeSize; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// size of code, import address table, constant data and export dir</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iDataSize; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// size of initialised data</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iHeapSizeMin;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iHeapSizeMax;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iStackSize;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iBssSize;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iEntryPoint; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// offset into code of entry point</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iCodeBase; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// where the code is linked for </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iDataBase; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// where the data is linked for</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iDllRefTableCount; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// filling this in enables E32ROM to leave space for it</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iExportDirOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// offset into the file of the export address table</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iExportDirCount;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TInt iTextSize; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// size of just the text section, also doubles as the offset for the</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// iat w.r.t. the code section</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iCodeOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// file offset to code section, also doubles as header size</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iDataOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// file offset to data section</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iImportOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// file offset to import section</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iCodeRelocOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// relocations for code and const</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint iDataRelocOffset; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// relocations for data</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint16 iProcessPriority; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// executables priority</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint16 iCpuIdentifier; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// 0&#215;1000 = X86, 0&#215;2000 = ARM</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">};</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">class</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> E32ImageHeaderComp : </span> <span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">public</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> E32ImageHeader</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">{</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">public</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">:</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iUncompressedSize; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Uncompressed size of file</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// For J format this is file size - sizeof(E32ImageHeader)</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// and this is included as part of the compressed data :-(</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// For other formats this is file size - total header size</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">};</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">class</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> E32ImageHeaderV : </span> <span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">public</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> E32ImageHeaderComp</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">{</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; color: #0000ff; font-family: '新宋体'; mso-spacerun: 'yes';">public</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">:</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">SSecurityInfo iS;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Use iSpare1 as offset to Exception Descriptor</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iExceptionDescriptor; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// Offset in bytes from start of code section to Exception Descriptor,</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// bit 0 set if valid</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint32 iSpare2;</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint16 iExportDescSize; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// size of bitmap section</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint8 iExportDescType; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// type of description of holes in export table</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-align: left;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"> </span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">TUint8 iExportDesc[1]; </span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';">// description of holes in export table - extend</span> <span style="font-size: 9pt; color: #008000; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">};</span> <span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';">    </span> <span style="font-size: 10.5pt; font-family: '新宋体'; mso-spacerun: 'yes';">我将逐一解释上面这些字段。从下面的列表中，左端的16进制数表示这个字段在文件中的偏移量，例如iUid2的位置是从文件头部开始0&#215;04的位置。换句话说，如果你把可执行文件用二进制编辑器打开，然后找到偏移量0&#215;04的位置你就可以找到iUid2。注意E32Image使用小端格式（little-endian order）。</span> <span style="font-size: 10.5pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 9pt; font-family: '新宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeader</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;00:</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">iUid1</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的第一个UID。这个UID可被看作是一个系统级别的标识符，例如Dlls是</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 0079</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行程序是</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 007A</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。如果你想更多的了解Symbian OS UID相关信息，可以</span> </span><span><a href="http://www.symbian.com/developer/techlib/v70sdocs/doc_source/ToolsAndUtilities/BuildTools/UsingUids.guide.html"><span class="16" style="font-size: 10pt; color: #0000ff; font-family: '宋体'; text-decoration: underline; mso-spacerun: 'yes';"><span style="font-family: 宋体;">访问这里</span> </span></a></span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;04: iUid2</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的第二个UID。当两个对象拥有同一个UID1的时候，就需要用这个UID来区分它们，例如</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 39CE</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">表示多态接口Dll（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">polymorphic interface DLLs</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">），</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> 0&#215;1000 008d</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">表示静态接口（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">static interface (shared library)</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;08: iUid3</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的第三个UID。</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">每个程序的UID3都不同。下面这段不翻译了，贴个图看图识字吧^_^。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">It is unique for each application. Developers have to request this UID from Symbian Signed service. Symbian OS 9 applications usually have UIDs in the range of 0&#215;200 0000 and 0&#215;2FFF FFFF. Examples from Symbian OS SDKs, like S60 SDK or UIQ SDK, have the UIDs in the range of 0xA000 0000 and 0xAFFF FFFF. There are also some UID available for testing, which can be chosen from the range 0&#215;0100 0000 to 0&#215;0FFF FFFF.</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt; text-align: center;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image4.png" alt="" width="538" height="462" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;0C: iUidChecksum</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，校验前面提到的3个UID。Symbian SDK中提供了一个uidcrc.exe工具完成该功能；下面的例子展示了如何生成这三个UID：</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 007A</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 39CE </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">和</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0xA000 017F</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的校验码：</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">C:\&gt;uidcrc 0&#215;1000007A 0&#215;100039CE 0xA000017F</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000007a 0&#215;100039ce 0xa000017f 0&#215;1e7cca07</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;10: iSignature</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，E32文件唯一签名（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">unique signature</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）。值统一为“EPOC”。图示如下：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image5.png" alt="" width="553" height="33" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;14: iHeaderCrc</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，整个头信息的完整校验，使用</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">CCITT CRC-32</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">算法。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;18: iModuleVersion</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行版本号。该信息用于链接过程（linking process）。在S60 3</span> </span><span style="font-size: 10.5pt; vertical-align: super; font-family: '宋体'; mso-spacerun: 'yes';">rd </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">iModuleVersion </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">值为10（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;0000 000A</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）（Cxt注：大牛这里可能笔误了，iModuleVersion是T</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">u</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">int32<span style="font-family: 宋体;">，占4个字节，这个值应该是0&#215;000A 0000）。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image6.png" alt="" width="553" height="35" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1C: iCompressionType</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，一个UID，表示使用哪种压缩算法压缩了可执行文件。如果值为0就说明未压缩。就我目前所看到的，只使用了一种压缩算法：由RFC 1951定义的</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Deflate/Huffman</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">算法。它的UID是</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">KUidCompressionDeflate</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">（</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;101F 7AFC</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">）。需要注意的是，未来也许会使用其他压缩算法。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt; text-align: center;"><img src="file:///C:/DOCUME~1/GODWIN~1/LOCALS~1/Temp/ksohtml/wps_clip_image7.png" alt="" width="553" height="34" /><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;20: iToolsVersion</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，生成这个可执行文件的</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ELFTRAN</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">工具版本。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;24: iTimeLo</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，时间戳。</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">the lowest word of the timestamp when the file is created.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;28: iTimeHi</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，时间戳。</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">the lowest word of the timestamp when the file is created.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;2C: iFlags</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的一个标记，比如</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">KImageDll </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">KImageNoCallEntryPoint </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">等。这些标记定义在f32image.h中。f32image.h中有一些函数定义用来解释这些标记的意思。例如：如果flag值为</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1200 002A</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，我们可以把它看作：</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;1000 0000 + 0&#215;0200 0000 + 0&#215;0000 00020 + 0&#215;0000 0008 + 0&#215;0000 00002</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，结合f32image.h中的常量声明，我们可以发现：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 21pt; layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;10000000 = KImageImpFmt_PE</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件使用ELF-derived入口。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 21pt; layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;02000000 = KImageHdrFmt_V</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，header的版本支持。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 21pt; layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;00000020 = KImageEpt_Eka2</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，EKA2可执行文件。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 21pt; layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;00000008 = KImageABI_EABI</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件为EABI image file。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 21pt; layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">· </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;00000002 = KimageNoCallEntryPoint</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，no call to entry point。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;30: iCodeSize</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">is the size of code section, import address table, constant data and export dir.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;34: iDataSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, size of initialised data.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;38: iHeapSizeMin</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the minimum size of the heap.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;3C: iHeapSizeMax</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the maximum size of the heap.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;40: iStackSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the size of the stack.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;44: iBssSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the size of the un-initialized data section.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;48: iEntryPoint</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, offset into code of entry point.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;4C: iCodeBase</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, where the code is linked for.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;50: iDataBase</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, where the data is linked for.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;54: iDllRefTableCount</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the number of DLLs imported by this program.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;58: iExportDirOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, offset into the file of the export address table.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;5C: iExportDirCount</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the offset of the export address table.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;60: iTextSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, size of just the text section, also doubles as the offset for the iat w.r.t. the code section.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;64: iCodeOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, file offset to code section, also doubles as header size.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;68: iDataOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, file offset to data section.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;6C: iImportOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, file offset to import section.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;70: iCodeRelocOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, relocations for code and const.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;74: iDataRelocOffset</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, relocations for data.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;78: iProcessPriority</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, executables priority.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 20.58pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;7A: iCpuIdentifier</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, the identifier of CPU. Look at the following constant for all possible values:</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">enum TCpu</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">{</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuUnknown=0, </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuX86=0&#215;1000, </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuArmV4=0&#215;2000, </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuArmV5=0&#215;2001, </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuArmV6=0&#215;2002, </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECpuMCore=0&#215;4000</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 105pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">};</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">                </span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 10.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderComp</span> <span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    <span style="font-family: 宋体;">开始之前，我们需要知道2个结构：定义在e32cmn.h的</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ScapabilitySet</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">和</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">SSSecurityInfo</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">。Symbian OS 9可以看到它们，它们保存了平台安全相关信息，比如能力（capability）、安全标识符（secure identifier）和厂商标识符（vendor identifier）。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">struct SCapabilitySet</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">{</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 115.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">enum {ENCapW=2};</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 115.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">TUint32 iCaps[ENCapW];</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">};</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">struct SSecurityInfo</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">{</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 115.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">TUint32 iSecureId;</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 115.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">TUint32 iVendorId;</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 115.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">SCapabilitySet iCaps; // Capabilities re. platform security</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">};</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">好了，让我们回到</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderV</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;80: iS.iSecureId</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的安全ID（secure ID）。就是可执行文件的UID3。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;84: iS.iVendorId</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，可执行文件的厂商ID（vendor ID）。对于第三方应用程序，值为0。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;88: iS.iCaps.iCaps</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，运行可执行文件需要的能力。Symbian OS所有的能力定义可以在</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">e32capability.h</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">文件中找到。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">enum TCapability</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">{</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityTCB = 0,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityCommDD = 1,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityPowerMgmt = 2,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityMultimediaDD = 3,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityReadDeviceData = 4,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityWriteDeviceData = 5,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityDRM = 6,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityTrustedUI = 7,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityProtServ = 8,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityDiskAdmin = 9,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityNetworkControl = 10,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityAllFiles = 11,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilitySwEvent = 12,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityNetworkServices = 13,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityLocalServices = 14,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityReadUserData = 15,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityWriteUserData = 16,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityLocation = 17,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilitySurroundingsDD = 18,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityUserEnvironment = 19,</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="margin-left: 94.5pt; layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">};</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    <span style="font-family: 宋体;">能力以bit的形式表示，例如</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ECapabilityTCB</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">意味着最低有效位（LSB），如果设置了最低有效位，可执行文件就具有TCB能力。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;90: iExceptionDescriptor</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">is offset in bytes from start of code section to Exception Descriptor, bit 0 set if valid</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;94: iSpare2</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, reserved.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;98: iExportDescSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, size of bitmap section.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;9A: iExportDescType[1]</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, type of description of holes in export table.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-weight: bold; font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">0&#215;9B: iExportDesc[1]</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">, is description of holes in export table.</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';">Example<span style="font-family: 宋体;">：</span> </span><span style="font-weight: bold; font-size: 14pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    <span style="font-family: 宋体;">下面我们来看一个例子，来帮助你更好的理解上面说的那些字段。我们将使用标准的Symbian OS build command来编译3.0 SDK提供的Helloworld Basic例子。</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">C:\Symbian\9.1\S60_3rd\S60Ex\helloworldbasic&gt;bldmake bldfiles</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">C:\Symbian\9.1\S60_3rd\S60Ex\helloworldbasic&gt;abld build gcce urel</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">现在切换到</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">\epoc32</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">\r</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">elease\gcce\urel</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">目录，使用</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Elf2E32</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">工具读取E32 image头信息。做法如下：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">C:\Symbian\9.1\S60_3rd\S60Ex\helloworldbasic&gt;elf2e32 &#8211;e32input=helloworldbasic.exe</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">然后你将会看到</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">helloworldbasic.exe</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的头信息；输出的过程可能会很长，所以一个比较好的方法是将他转储到文件，便于我们进一步分析：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">C:\Symbian\9.1\S60_3rd\S60Ex\helloworldbasic&gt;elf2e32 &#8211;e32input=helloworldbasic.exe &gt; helloworldbasic.txt</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">打开</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">helloworldbasic.txt</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">，你将会看到头信息（我已经用绿色的注释标明了</span> </span><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageHeaderV</span> <span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"><span style="font-family: 宋体;">的字段）：</span> </span><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">E32ImageFile &#8217;helloworldbasic.exe&#8217;</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">V2.00(505) Time Stamp: 00e0eb0a,d2525b80 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iTimeStampHi, iTimeStampLo</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">EPOC Exe for ARMV5 CPU </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCpuIdentifier = 0&#215;20001 (ARMv5)</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Flags: 1200002a </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iFlags</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Priority Foreground</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Entry points are not called</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Image header is format 2</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Image is compressed using the DEFLATE algorithm </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCompressionType</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Uncompressed size 0000b788</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Image FPU support : Soft VFP</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Secure ID: a000017f </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iSecureId</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Vendor ID: 00000000 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iVendorId</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Capabilities: 00000000 00000000</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iSs.iCaps.iCaps</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Exception Descriptor Offset: 00002561</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iExceptionDescriptor</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Exception Index Table Base: 00012dfc</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Exception Index Table Limit: 000130bc</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">RO Segment Base: 00008001</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">RO Segment Limit: 0000a77c</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Export Description: Size=000, Type=01 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iExportDescSize = 000 iExportDescType = 01</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Export description consistent</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Module Version: 10.0 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iModuleVersion</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Imports are ELF-style</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">ARM EABI</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Built against EKA2</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Uids: 1000007a 100039ce a000017f (1e7cca07)</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iUid1 = 1000007a, iUid2 = 100039ce, iUid3 = a000017f, iUidChecksum = 1e7cca07</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Header CRC: 023aca0d </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iHeaderCrc</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">File Size: 0000b788 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iUncompressedSize</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Code Size: 0000b0bc </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCodeSize</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Data Size: 00000000</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iDataSize</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Compression: 101f7afc </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCompressionType</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Min Heap Size: 00001000 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iHeapSizeMin</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Max Heap Size: 00100000</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iHeapSieMax</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Stack Size: 00005000 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iStackSize</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Code link addr: 00008000 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCodeBase</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Data link addr: 00400000</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iDataBase</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Code reloc offset: 0000b650</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iCodeRelocOffset</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Data reloc offset: 00000000 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iDataRelocOffset</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Dll ref table count: 10 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iDllRefTableCount</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Offset Size Relocs #Relocs</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Code 00009c 00b0bc 00b650 00007d +002504 (entry pnt)</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iCodeOffset = 00009c iCodeSize = 00b0bc iCodeRelocOffset = 00b650</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Data 000000 000000</span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iDataOffset iDataSize</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Bss 000000</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> // iBssSize</span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char; text-indent: 21.75pt;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"> </span> <span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';">Import 00b158 </span> <span style="font-size: 10.5pt; color: #008000; font-family: 'Times New Roman'; mso-spacerun: 'yes';">// iImportOffset</span> <span style="font-size: 10.5pt; color: #008000; font-family: '宋体'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-spacerun: 'yes';"></span></p>
<p class="0" style="layout-grid-mode: char;"><span style="font-size: 10.5pt; font-family: '宋体'; mso-spacerun: 'yes';">    <span style="font-family: 宋体;">全都在这了！！希望你能够喜欢这篇文章！</span> </span></p>
<p><!--EndFragment--></p>

	<h4>相关文章</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.donevii.com/post/595.html" title="各有所长 四大智能手机操作平台大比拼 (2008-10-24)">各有所长 四大智能手机操作平台大比拼</a> (0)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/802.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《深入BREW》 &#8211; BREW原理</title>
		<link>http://www.donevii.com/post/746.html</link>
		<comments>http://www.donevii.com/post/746.html#comments</comments>
		<pubDate>Sat, 17 Jan 2009 18:20:15 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[brew]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=746</guid>
		<description><![CDATA[我们PC的Windows操作系统功能是如此的强大，以至于我们可以获得任何一个我们想要的程序，任何一个人都可以为Windows开发应用程序，或者给自己，或者为他人。而这一切源于操作系统的开放性... ]]></description>
			<content:encoded><![CDATA[<p>我们PC的Windows操作系统功能是如此的强大，以至于我们可以获得任何一个我们想要的程序，任何一个人都可以为Windows开发应用程序，或者给自己，或者为他人。而这一切源于操作系统的开放性和硬件平台的不断发展，尤其是存储器的发展，使得我们在编写程序的时候不必在意需要多大的存储空间了。</p>
<div><span>       </span>然而，嵌入式系统可就没那么幸运了。至今为止，在嵌入式系统里仍然没有一个能够像Windows这样应用如此广泛的操作系统，也没有可以不考虑存储空间的硬件平台。在数以亿计的嵌入式设备使用者中，都还在用着一成不变的应用程序，单调同时也令人乏味。我们能不能也像在Windows下面一样，在嵌入式系统中可以安装应用程序呢？应该怎样克服嵌入式系统的限制而实现这个功能呢？</div>
<div><span>       </span>有梦想才会不断的追求！我们知道，在Windows中程序都是以文件的形式存储在文件系统中的，然后通过操作系统控制这些程序的运行，我们可以说它的程序是“分散式”的。而在嵌入式系统中通常是将程序烧录在一个Flash芯片中，文件系统在另一个Flash芯片中（也可以二者在同一个芯片中），CPU是直接从程序Flash芯片中读取指令执行的，没有经过文件系统，我们可以叫这种程序是“一体式”的。Windows的“分散式”程序体通过文件的形式存在，可以把程序的不同部分分割成不同的文件，当我们只需要更新一个模块内容的时候，只更新这个文件就可以了。熟悉它的朋友们可能已经知道了，这个文件就是在Windows操作系统中的DLL文件。这样的方式可以很容易的实现程序分发，这给了我们一个很好的启示：嵌入式系统中也有文件系统，把程序放在文件系统里不就可以了吗？真是个好主意！</div>
<div><span>       </span>在我们庆幸找到了好方法的时候，问题不偏不倚地出现了：系统如何运行文件系统中的程序，文件中的程序又如何调用平台中的函数？要实现“分散式”的程序运行，这两个问题是必须要解决的，而其中第二个问题就更为重要了。或许您现在还不是十分的明白这些问题的意义，不要着急，这一章里我会逐一的向您讲解如何理解并解决这两个问题。当然，现在我们知道BREW已经在嵌入式系统中解决了这两个问题，从现在开始就让我们沿着开发者的足迹去追寻BREW的本质吧。</div>
<div><strong><span style="font-size: medium;">1.<span>平台的作用</span></span></strong></div>
<div><span>       </span>如果想要清楚的了解我们在嵌入式系统中所面临的问题，那么我们就首先需要了解“分散式”系统的结构。一个“分散式”系统需要有三个部分组成：平台、软件开发工具包（SDK： Software Development Kit）和应用程序。“分散式”应用程序的运行需要平台的支持，就像是DLL文件只有在Windows操作系统平台下才有作用，而到了Linux平台则不起任何作用一样；应用程序则通过SDK进行开发，开发出的源程序经过编译之后可以运行在运行平台之上。平台又分为开发平台和运行平台，开发平台是SDK运行的平台，用来开发可以在运行平台上运行的应用程序，对于一些系统还会提供模拟运行平台的模拟器，以便于在没有显而易见的运行设备的时候也可以看到开发的效果；运行平台是应用程序运行的平台，它提供应用程序运行的环境，同时肩负着控制应用程序的作用。开发平台和运行平台可以是同一个平台，也可以两个不同的平台，比如现在的Winows平台的应用就可以使用VC等工具开发基于Windows的应用程序，而BREW SDK则是运行在Windows环境下，但应用程序却在嵌入式系统中运行。它们之间的关系如下图：<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-1.bmp" alt=" " /></div>
<p> </p>
<div>图1 分散式系统结构图</div>
<div><span>       </span>从这个图中我们可以看出，SDK需要使用运行平台的接口声明来开发应用程序，运行平台负责根据用户的输入启动应用程序，而应用程序则通过运行平台的接口调用运行平台的函数库来实现功能，我们的问题主要集中在应用程序和运行平台的互动关系上。</div>
<div><span>       </span>从前面的编译器基础一章中我们可以知道，在固定链接的模式下，各个函数的地址是固定的，我们可以在同一个映像文件中调用任何函数。而存储在文件系统中的程序就不一样了，文件系统中的程序没有固定的位置并且地址也不连续，我们该怎样实现应用程序的启动呢？可选的方案就是将应用程序复制到一个连续的内存块中去，然后在内存中执行程序。在这里需要特别的说明一下，在PC的Windows操作系统中，Windows将全部的程序载入内存中运行，并且其中包含了复杂的内存管理功能，但是在嵌入式系统中通常程序是在Flash芯片中运行的，只有可读写的数据是放在RAM中的，具体的细节可以参考编译器基础一章。BREW主要是应用程序在嵌入式系统中的，因此将程序复制到内存中执行是需要特殊处理的。这个特殊的处理就是我们所面临的第一个问题了——系统如何运行文件系统中的程序。</div>
<div><span>       </span>在我一开始理解BREW的时候，我曾经认为系统如何运行存在于文件系统中的程序是我们所面临的主要问题，但当深入BREW内部的时候发现根本不是这么回事。现在我们可以假设运行平台分配了一个足够大的内存，这块内存地址是已知的，可以想象的到我们可以从这个地址开始执行程序。现在我们暂时忽略那些特殊的处理，文件系统中的这个程序现在正在运行，就像在Flash中的程序一样的在运行。从理论上来讲这个是行得通的，因此系统如何运行文件系统中的程序的问题并不是我们所面临的难题。实际上BREW也是按照这个思路做的，只是实现时还有细节的东西在，关于这些细节我们将在Shell内幕一章进行详细的介绍。</div>
<div><span>       </span>进一步的，假设现在程序运行到了需要调用平台函数的时候了，问题就来了，由于当前的应用程序是开发者使用SDK开发的，就像平台不知道应用程序的地址一样，应用程序也不知道平台的函数地址，因此，我们现在面临的问题是怎么能够知道应用程序中所调用的平台函数的地址。SDK可以提供运行平台中的每个函数的地址吗？可以提供，但是行不通。因为平台是会经常升级的，导致每个函数的链接地址不固定，如果由SDK提供所有函数的地址带来的问题是，只要运行平台一升级，那么SDK和应用程序都需要同时升级。如果这样的话我们的分散式程序就不能实现“分散式”的升级了，这种程序的运行方式也就没有任何意义了。看来我们还要寻找更为高级的方法，这种方法要能够提供一种应用程序与运行平台之间无关的机制。我们现在所需要的这个“机制”就是第二个问题了——文件系统中的程序如何调用平台的函数。</div>
<div><span>       </span>从分散式系统结构图中我们可以看到，SDK使用的是运行平台的接口声明，应用程序调用真正的运行平台接口。或者换句话说开发过程中使用运行平台的接口声明，而在运行时应用程序使用真正的二进制接口，并且在二进制层面调用接口函数。那么，现在无论是SDK还是应用程序都与接口相关，那么，可以想象的到的解决第二个问题的方式就是让接口和接口实现之间分离。接口与实现间分离的方法就是BREW的核心，也是接下来我们主要阐述的议题。</div>
<div><strong><span style="font-size: medium;">2.<span>软件分发和C</span><span>语言</span></span></strong></div>
<div><span>       </span>为了更好的理解“实现接口和实现分离”所面临的问题，让我们先来看看通常的C语言软件库是如何分发的，这对于我们的理解非常有用。为了能够更加清楚地理解问题，我们在接下来几节的论述中不会仅仅局限于嵌入式系统，因为同样的问题也存在于PC系统中，更为重要的是PC系统所面临的问题更加典型，并且这些问题在软件系统中是具有普遍性的。</div>
<div><span>       </span>想象现在有一个C语言库的开发厂商，它开发了一个算法，可以在O(1)时间效率内实现子字符串的搜索，O(1)时间效率的意思是指搜索时间为常数，与目标字符串的长度没有关系。为了实现这个功能，软件厂商生成了一个头文件FastString.h，包含如下内容：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件第一版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div><span>#ifndef FASTSTRING_H_</span></div>
<div><span>#define FASTSTRING_H_</span></div>
<div><span> </span></div>
<div><span>// 要求使用者不能直接使用此结构体中的内容</span></div>
<div><span>typedef struct _IFastString {</span></div>
<div style="text-indent: 21pt;"><span>char *m_pString;<span>   // </span>指向字符串的指针</span></div>
<div><span>} IFastString;</span></div>
<div><span> </span></div>
<div><span>// 创建目标字符串对象</span></div>
<div><span>void IFastString_CreateObject(IFastString * pIFastString, char *pStr);</span></div>
<div><span> </span></div>
<div><span>// 释放目标字符串对象</span></div>
<div><span>void IFastString_Release(IFastString *pIFastString);</span></div>
<div><span> </span></div>
<div><span>// 获取目标字符串长度</span></div>
<div><span>int IFastString_GetLength(IFastString *pIFastString); </span></div>
<div><span> </span></div>
<div><span>// 查找字符串，返回偏移量</span></div>
<div><span>int IFastString_Find(IFastString *pIFastString, char *pFindStr);</span></div>
<div><span>#endif // FASTSTRING_H_</span></div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>除了这个头文件之外软件厂商还提供了接口的实现文件FastString.c</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件第一版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#include ”FastString.h”</div>
<div>#include &lt;string.h&gt;</div>
<div> </div>
<div>// 创建目标字符串对象</div>
<div>void IFastString_ CreateObject (IFastString * pIFastString, char *pStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">IFastString *pMe = pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL || pStr == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_pString = malloc(strlen(pStr) +1);</div>
<div style="text-indent: 21.75pt;">strcpy(pMe-&gt;m_pString,pStr);</div>
<div>}</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>void IFastString_Release(IFastString *pIFastString)</div>
<div>{</div>
<div><span>    IFastString *pMe = pIFastString;</span></div>
<div><span>    </span></div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe-&gt;m_pString)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    free(pMe-&gt;m_pString);</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div>}</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>int IFastString_GetLength(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">IFastString *pMe = pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div> </div>
<div><span>    return strlen(pMe-&gt;m_pString);</span></div>
<div>}</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>int IFastString_Find(IFastString *pIFastString, char *pFindStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">IFastString *pMe = pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">// 搜索算法省略，因为这里仅仅假设存在这样的一个搜索算法</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>这个接口总共有四个接口：CreateObject、Release、GetLength和Find。CreateObject用来创建IFastString接口，从实现中我们可以看到它构建了IFastString结构体的内容。Release用来释放由CreatObject分配的内存。GetLength获得字符串的长度。Find用来在目标字符串中查找指定的字符串。在这个接口的实现中，使用了一个初始化的技巧（CreateObject和Release），目的是为了再使用前构建IFastString结构体，使用后可以通过Release释放构建时分配的内存。</div>
<div><span>       </span>一般来讲这个库的使用者会将.lib库链接到自己的工程中，通过接口声明的头文件使用库中的函数，这是一个非常可行的做法。这样做带来的结果是库的可执行代码将成为客户应应用程序中不可分割的一部分。</div>
<div><span>       </span>现在假设对于FastString库文件占用了大约16M的代码空间（这里假设为了完成O(1)算法可能需要十分复杂的程序，并且采取了一些空间换时间的策略等，这可能占用大量的存储空间）。如图2所示，如果现在有三个应用程序都在使用FastString库，那么每一个应用程序都将使用16M的空间来存储这些代码，总共花费了48M的空间。如果一个用户安装了这三个程序，也就是说有32M的空间浪费了，去存储了同样的FastString.lib中的代码。</div>
<div> <img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-2.bmp" alt="" /></div>
<div>                                                        图2 多个应用程序使用FastString库</div>
<div><span>       </span>在这种情况下的另一个问题是，如果当前FastString库的厂商发现了程序中的缺陷，那么就没有任何办法可以替换已经存在的缺陷代码。一旦FastString的代码链接到了应用程序中，我们就不可能在用户的设备上替换这部分的代码。因此，库厂商不得不重新为每个应用程序的开发者广播发布新的库文件，并且希望他们能够重新的编译他们的应用程序，以便能够使用新的代码。很显然，这可真是一件麻烦的事情，一旦应用程序开发者链接了这个库文件，FastString便失去了模块化的特征。跟进一步说，这在嵌入式系统中是完全不可能的，在这里FastString的角色就是运行平台，我们总不能每一个应用程序都包含一个运行平台去啊。</div>
<div><strong><span style="font-size: medium;">3.<span>动态链接</span></span></strong></div>
<div><span>       </span>解决上面问题的一种技术是使用动态链接技术（Dynamic Link）将FastString包含起来，这种技术的典型应用是Windows操作系统中的动态链接库（DLL文件）。这种方法是将FastString源文件编译成特殊的独立的二进制文件，并强迫FastString将所有的接口从二进制文件中引用出去，建立相应的引出表，以便于在运行时把每个接口的名字映射到对应的二进制接口地址上。与此同时还需要为使用者生成相应的引入库，通过这个引入库FastString的使用者可以获得FastString中每个接口的符号。引入库中并没有包含实际的代码，它只是简单的包含FastString引出的符号名字。当客户链接引入库的时候，这些符号信息会加入到当前的可执行文件中，运行时动态的装载FastString二进制库文件，并在执行时调用相应的程序。当然这些需要一些辅助工具的支持，例如编译器的支持等。此时应用程序的结构如图3：</div>
<div><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-3.bmp" alt="" /></div>
<div>                                                                            图3 动态链接示意图</div>
<div><span>       </span>上图就是FastString在动态链接方式下的运行模式，这里面的引入库非常的小，所以可以忽略它占用的空间。在这种情况下，FastString的代码库就只需要一份了。运行时所有的应用程序调用同一个库中的内容，理论上当发现FastString中有缺陷的时候，我们可以更新FastString二进制组件而不影响应用程序。可以看到，我们已经迈出了重要一步，不过还没有完全解决我们所面临的问题。</div>
<div><strong><span style="font-size: medium;">4.<span>封装性</span></span></strong></div>
<div><span>       </span>我们现在已经找到了一种可以实现动态链接的方法，那么下一个问题则与封装有关。考虑这样的情形：一个组织使用了FastString，同时希望能够在2个月内完成开发和测试。假设在这两个月中，某些具有特殊的怀疑精神的开发人员打算在他们的应用程序上测试一下FastString的性能，以便于测试O(1)时间效率的搜索算法。令人惊讶的是Find方法的搜索速度很快，并且与字符串的长度无关，但是GetLength方法的速度不是很理想，因为在GetLength方法中使用的是strlen计算字符串的长度，它查找字符串中的NULL结束符，它的算法需要遍历正个字符串的内容，因此它的执行效率是O(n)，当字符串很长，而且调用次数很多的时候，执行的速度很慢。于是开发人员要求厂商提高GetLength操作的执行速度，使它在常数时间内完成。但是现在有一个问题，开发人员已经开发完成了他们的应用程序，他们不希望由于使用新的GetLength方法而更改任何现有的程序。而且其他的厂商可能已经发布了使用这个现有版本的基于FastString的产品，从任何方面将库厂商都不应该影响这些已经面世的产品。</div>
<div><span>       </span>这个时候我们要查看我们的FastString的实现，以便确定哪些可以改变，哪些不可以改变。幸运的是，我们已经要求使用者不能直接使用IFastString结构体中的内容，假设所有的使用者都遵循了这一约定，于是我们很快的修改了GetLength的方法，将头文件改成了如下的方式（未修改部分未列出）：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件第二版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#ifndef FASTSTRING_H_</div>
<div>#define FASTSTRING_H_</div>
<div> </div>
<div>// 要求使用者不能直接使用此结构体中的内容</div>
<div>typedef struct _IFastString {</div>
<div style="text-indent: 21pt;">char *m_pString;<span>   // </span>指向字符串的指针</div>
<div style="text-indent: 21pt;">int m_nLen;<span>       // </span>存储字符串的长度</div>
<div>} IFastString;</div>
<div> </div>
<div>#endif // FASTSTRING_H_</div>
</td>
</tr>
</tbody>
</table>
<div>将实现文件改成了如下方式（未修改部分未列出）：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件第二版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>// 创建目标字符串对象</div>
<div>void IFastString_ CreateObject (IFastString * pIFastString, char *pStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">IFastString *pMe = pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL || pStr == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_nLen = strlen(pStr);</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_pString = malloc(pMe-&gt;m_nLen +1);</div>
<div style="text-indent: 21.75pt;">strcpy(pMe-&gt;m_pString,pStr);</div>
<div>}</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>int IFastString_GetLength(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">IFastString *pMe = pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div> </div>
<div><span>    return pMe-&gt;m_nLen;</span></div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>很快的修改后重新发布了FastString的第二个版本。在这里一个显著的改进是在CreateObject时将字符串长度存储起来了，当用户调用GetLength方法时直接返回存储的长度。这样没有修改任何接口的内容，因此应用程序也就不需要修改了。</div>
<div><span>       </span>客户收到了第二版的FastString后，替换了FastString的动态链接库，重新编译链接全部的应用程序，测试后发现不但原始代码不需要任何修改，而且GetLength方法的速度也大大加快了。最终这个第二版的FastString会随着这个产品而发布到用户手中。在安装应用程序的时候，第二版的FastString会将第一版的替换掉。这通常不会有问题，因为修改并没有影响公开的接口，因该只会增强原先已经安装的使用FastString的应用程序的功能而以。</div>
<div><span>       </span>请想象这样的情形，当用户更新了第二版的FastString后，运行新版的应用程序，用户惊喜的发现程序运行的速度提高了。然后用户关闭了新的应用程序，而打开了另一个以前安装的使用旧版本FastSting的应用程序。现在的FastString已经替换成了第二版，因此用户发现这个应用程序的性能也增强了。然而不久异常出现了，系统出现了未知的错误。不过没关系，对于已经习惯了现代商业软件的人士来说，这不算什么问题，于是重新卸载并重新安装了两个应用程序，还是不起作用啊，异常依然发生！到底是怎么回事？</div>
<div><span>       </span>原因在于IFastString结构体的修改。在未修改前sizeof(IFastString) == 4，因为只有一个char *m_ pString变量（假设系统是32位的）。修改后sizeof(IFastString) == 8，增加了4个字节。新版本的软件已经重新编译了，因此相应的IFastString结构体已经增加了空间。但是对于使用第一版FastString编译的应用程序来说，此时在应用程序里面分配的IFastString的空间依然是4，于是当第一版的应用程序调用第二版FastString的时候，将本该属于其他用途的4个字节用作了m_nLen的区间，这是十分粗暴的，产生异常也就不足为奇了。</div>
<div><span>       </span>还记得前面的约定吗？我们要求FastString的使用者不可以直接对IFastString结构体中的数据进行直接操作，以达到应用程序与数据结构间的无关性。但实际上这样的约定基本上不可能被遵守，因为在实际中不管出于什么样的目的，总会有些开发者直接使用结构体中的内容（这些开发者使用的使FastString的C语言库文件形式，没有使用动态链接技术）。加上前面的异常，这一切的根源是我们没有一个实现二进制数据封装的方式。如果现在能够有一种可以将全部的数据结构封装在FastString内部的方法就好了。C语言是灵活的，只要我们找到了问题，我们就可以实现它。于是第三版的FastString新鲜出炉了，首先是头文件：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件第三版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#ifndef FASTSTRING_H_</div>
<div>#define FASTSTRING_H_</div>
<div> </div>
<div>typedef void IFastString;</div>
<div> </div>
<div>// 创建目标字符串对象</div>
<div>void IFastString_CreateObject(IFastString ** ppIFastString, char *pStr);</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>void IFastString_Release(IFastString *pIFastString);</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>int IFastString_GetLength(IFastString *pIFastString);</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>int IFastString_Find(IFastString *pIFastString, char *pFindStr);</div>
<div>#endif // FASTSTRING_H_</div>
</td>
</tr>
</tbody>
</table>
<div>接下来是实现的源文件：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件第三版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#include ”FastString.h”</div>
<div>#include &lt;string.h&gt;</div>
<div> </div>
<div>typedef struct _CFastString {</div>
<div style="text-indent: 21pt;">char *m_pString;<span>   // </span>指向字符串的指针</div>
<div style="text-indent: 21pt;">int m_nLen;<span>       // </span>存储字符串的长度</div>
<div>} CFastString;</div>
<div> </div>
<div>// 创建目标字符串对象</div>
<div>void IFastString_CreateObject (IFastString **ppIFastString, char *pStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = malloc(sizeof(CFastString));</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL || pStr == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_nLen = strlen(pStr);</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_pString = malloc(pMe-&gt;m_nLen +1);</div>
<div style="text-indent: 21.75pt;">strcpy(pMe-&gt;m_pString,pStr);</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">* ppIFastString = (IFastString *)pMe;</div>
<div>}</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>void IFastString_Release(IFastString *pIFastString)</div>
<div>{</div>
<div><span>    CFastString *pMe = (CFastString *)pIFastString;</span></div>
<div><span>    </span></div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe-&gt;m_pString)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    free(pMe-&gt;m_pString);</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">free(pMe)</div>
<div>}</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>int IFastString_GetLength(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div> </div>
<div><span>    return strlen(pMe-&gt;m_pString);</span></div>
<div>}</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>int IFastString_Find(IFastString *pIFastString, char *pFindStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">// 搜索算法省略，因为这里仅仅假设存在这样的一个搜索算法</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>在这个实现中，我们使用了CFastString做为FastString的内部数据结构，定义了void型的IFastString类型做为接口指针传递，还有重要的一条是通过CreateObject获得数据结构的存储空间。通过这样的实现方法，我们将全部的数据类型封装在了FastString库中，这样，无论新的还是老的应用程序，使用的都是统一的IFastString指针，真正的数据是在CreateObject中进行创建的，也就不会出现上面的两种情况了。对于FastString的客户来说，他们所能看到的就是IFastString的void类型和四个接口函数，内部的CFastString的结构已经被隐藏起来了。不过这个第三版的FastString修改了接口函数CreateObject，因此不能够与前两版兼容。不过不要紧，我们现在只是在说明一个更好的方法而已。</div>
<div><strong><span style="font-size: medium;">4.<span>虚拟函数表</span></span></strong></div>
<div><span>       </span>封装性的本质是实现了接口与实现之间在二进制层次的分离，第三版的FastString似乎已经解决了我们所面临的第二个问题。不过现在我们的接口仍然在使用着动态链接用的引入库文件，而且相应的动态链接库也需要提供由符号名到二进制函数地址映射的内容，为了支持这些特性，我们必须要修改相应的编译器才行。修改编译器，很复杂不是吗？</div>
<div><span>       </span>让我们再回到嵌入式系统上来吧，ARM CPU是在嵌入式系统中使用最广泛的CPU，因此相应的ARM编译器也是应用最广泛的，基本上成为了一种通用的编译器。我们怎么修改这个编译器呢？似乎难度有点大。更近一步的，嵌入式系统中大大小小的CPU有好多种，我们也不可能把所有的这些编译器都修改了啊，看来修改编译器的可能性不大。</div>
<div><span>       </span>又一次让我们体验到了理想与现实之间的差距！不过别灰心，看看我们现在的接口，它是二进制层面上的，我们能不能把这个引入库变成标准的C语言的头文件同时又能够实现接口与实现间的分离呢？如果真的能够实现这样的方法，那么将意味着我们可以通过通用编译器来实现动态链接的技术。这可真是令人兴奋，这个方法要比动态链接技术还要好。</div>
<div><span>       </span>按照这个思路进一步分析，如果将现在的第三版FastString使用的C头文件做为标准的接口文件，那么将意味着各个接口需要静态的链接到应用程序中，接口和实现之间还是没有实现分离，难道我们转了一圈又回到原点了？真的又回来了，不过，不同的是我们现在已经得到了第三版的FastString。现在我们已经知道了通过CreateObject来获得内部的空间，那么我们是否也可以通过一个函数来获得接口呢？可以，这个技术就是虚拟函数表（VTBL）。</div>
<div><span>       </span>这可真是“山重水复疑无路，柳暗花明又一村”啊，先看看我们这个第四版的FastString的头文件吧：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件第四版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#ifndef FASTSTRING_H_</div>
<div>#define FASTSTRING_H_</div>
<div> </div>
<div>typedef struct _IFastString IFastString;</div>
<div>typedef struct _IFastStringVtbl IFastStringVtbl;</div>
<div>typedef void (*PFNCreateObject)( IFastString **ppIFastString, char *pStr);</div>
<div> </div>
<div>struct _IFastString</div>
<div>{</div>
<div> struct IFastStringVtbl *pvt;</div>
<div>};</div>
<div> </div>
<div>struct _IFastStringVtbl</div>
<div>{</div>
<div style="text-indent: 21.75pt;">void (*Release) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*GetLength) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*Find) (IFastString *pIFastString, char *pFindStr);</div>
<div>};</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>#define IFASTSTRING_Release(p) ((IFastString*)p-&gt;pvt)-&gt;Release(p)</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>#define IFASTSTRING_GetLength(p) ((IFastString*)p-&gt;pvt)-&gt;GetLength(p)</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>#define IFASTSTRING_Find(p,s) ((IFastString*)p-&gt;pvt)-&gt;Find(p,s)</div>
<div>#endif // FASTSTRING_H_</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>接下来是C语言的源文件：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件第四版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#include ”FastString.h”</div>
<div>#include &lt;string.h&gt;</div>
<div> </div>
<div>typedef struct _CFastString {</div>
<div><span>    IFastStringVtbl *pvt; // </span>指向虚拟函数表的指针</div>
<div style="text-indent: 21pt;">char *m_pString;<span>    // </span>指向字符串的指针</div>
<div style="text-indent: 21pt;">int m_nLen;<span>        // </span>存储字符串的长度</div>
<div>} CFastString;</div>
<div> </div>
<div>// 函数声明</div>
<div>static void IFastString_Release(IFastString *pIFastString);</div>
<div>static int IFastString_GetLength(IFastString *pIFastString)</div>
<div>static int IFastString_Find(IFastString *pIFastString, char *pFindStr);</div>
<div> </div>
<div>IFastStringVtbl <a name="OLE_LINK9">gvtFastString</a> = { IFastString_Release,</div>
<div><span>                           IFastString_GetLength,</span></div>
<div><span>                           IFastString_Find</span></div>
<div><span>                          };</span></div>
<div> </div>
<div>// 创建目标字符串对象</div>
<div>void IFastString_CreateObject (IFastString **ppIFastString, char *pStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = malloc(sizeof(CFastString));</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL || pStr == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;pvt = &amp;gvtFastString;</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_nLen = strlen(pStr);</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_pString = malloc(pMe-&gt;m_nLen +1);</div>
<div style="text-indent: 21.75pt;">strcpy(pMe-&gt;m_pString,pStr);</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">* ppIFastString = (IFastString *)pMe;</div>
<div>}</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>static void IFastString_Release(IFastString *pIFastString)</div>
<div>{</div>
<div><span>    CFastString *pMe = (CFastString *)pIFastString;</span></div>
<div><span>    </span></div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    </span>return;</div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe-&gt;m_pString)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    free(pMe-&gt;m_pString);</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">free(pMe)</div>
<div>}</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>static int IFastString_GetLength(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div> </div>
<div><span>    return strlen(pMe-&gt;m_pString);</span></div>
<div>}</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>static int IFastString_Find(IFastString *pIFastString, char *pFindStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">// 搜索算法省略，因为这里仅仅假设存在这样的一个搜索算法</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>首先对这个第四版的FastString程序做一个说明。在FastString头文件中我们定义了两个类型：IFastString和IFastStringVtbl。IFastStringVtbl类型是虚拟函数表的类型，IFastString中包含了指向虚拟函数表的指针。在接口定义的时候，我们使用了((IFastString*)p-&gt;pvt)来调用虚拟函数表中的函数指针，这也说明了如果要使用接口，必须要提供IFastString的指针类型。可以看出Release、GetLength和Find已经实现了在C语言定义的接口与实现函数之间的分离。</div>
<div><span>       </span>接着看一下源文件中的情况。CFastString结构体与第三版的FastString不同的是增加了一个IFastStringVtbl类型的指针，而且这个指针在结构体的最顶部，如果将IFastString和CFastString对比一下我们可以发现他们都在顶部包含了IFastStringVtbl的指针，这就意味着CFastString是IFastString的超集。这一点是很重要的，我们可以看见在CreateObject函数中返回的IFastString指针其实是指向CFastString的指针的，只有CFastString是IFastString的超集的时候我们才可以这么做。在这个源文件中还定义了一个IFastStringVtbl的变量gvtFastString，并为这个变量初始化成了各个对应的函数，这个变量就使我们的虚拟函数表。虚拟函数表的示意图如下：</div>
<div><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-4.bmp" alt="" /></div>
<div>图4 虚拟函数表</div>
<div><span>       </span>在这个第四版的FastString中，我们可以看到，除了CreateObject成员之外，其余的三个成员函数都已经添加到了虚拟函数表中，而且这个虚拟函数表还可以随着需求的增加而进行无限的扩大，我们只付出了一个函数CreateObject的代价就实现了无限多个接口和实现之间的分离了。</div>
<div><span>       </span>由于用户需要使用CreateObject来获得IFastString的指针，因此我们没有办法将其与实现分离开，怎么办？现在只有这一根“线”还在困扰着我们，我们难道要功败垂成了吗？当然不能了。开动脑筋，回到我们应用程序的启动过程，对于一个程序，不管是由main函数或者其他的什么函数做为启动函数，都允许启动的时候传递参数，可能您已经想到了吧，我们把这个CreateObject函数做为参数传递给应用程序不就可以了吗？恍然大悟！这也就是为什么我们将CreateObject函数定义成了一个PFNCreateObject的函数类型的原因了，目的就是为了让使用者可以在应用程序中定义这种类型的函数指针。</div>
<div><span>       </span>现在我们的应用程序、接口和实现之间已经分离了，中间使用了CreateObject这根细线连接了起来，只要接口不变，应用程序和实现之间就不会有任何的联系，包括二进制层面和C语言层面的。只不过这要求我们应用程序和接口的实现之间需要使用同一种编译器，或许这就叫做有得有失吧，不过对于嵌入式系统来说这是必须的，因为没有哪一种编译器可以支持全部的嵌入式CPU。</div>
<div><strong><span style="font-size: medium;">5.<span>支持多个接口</span></span></strong></div>
<div><span>       </span>到现在为止所展示的技术已经解决了我们所面临的问题，不过对于一个平台来说不可能只有一个FastString接口，可能还有诸如FastNumber的接口。我们总不能把FastString和FastNumber两个接口的CreateObject都做为参数传递给应用程序的启动函数吧？看来我们现有的FastString需要进行一些扩展，来实现只传递一个参数给应用程序就可以创建多个接口的功能。在这里我们将增加一个叫做Shell的接口来管理其他的接口，相关的代码如下：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>shell.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#ifndef SHELL_H_</div>
<div>#define SHELL_H_</div>
<div> </div>
<div>#define CLASSID_FASTSTRING 0&#215;00000001</div>
<div>#define CLASSID_FASTNUMBER 0&#215;00000002</div>
<div> </div>
<div>typedef struct _IShell IShell;</div>
<div>typedef struct _IShellVtbl IShellVtbl;</div>
<div> </div>
<div>struct _IShell</div>
<div>{</div>
<div> struct IShellVtbl *pvt;</div>
<div>};</div>
<div> </div>
<div>struct _IShellVtbl</div>
<div>{</div>
<div style="text-indent: 21.75pt;">void (*CreateInstance) (IShell *pIShell,</div>
<div style="text-indent: 21.75pt;"><span>                    int nClassID, </span></div>
<div style="text-indent: 21.75pt;"><span>                    void **ppObj, </span></div>
<div style="text-indent: 21.75pt;"><span>                    unsigned int nUserData);</span></div>
<div>};</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>#define ISHELL_CreateInstance(p,c,pp,u) ((IShell*)p-&gt;pvt)-&gt;CreateInstance(p,c,pp,u)</div>
<div>#endif // SHELL_H_</div>
</td>
</tr>
</tbody>
</table>
<div>源文件如下：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>Shell.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#include ”Shell.h”</div>
<div> </div>
<div>typedef struct _CShell {</div>
<div><span>    IShellVtbl *pvt; // </span>指向虚拟函数表的指针</div>
<div>} CShell;</div>
<div> </div>
<div>// 函数声明</div>
<div>static void IShell_CreateInstance(IShell *pIShell,</div>
<div><span>                           int nClassID,</span></div>
<div><span>                           void **ppObj, </span></div>
<div><span>                           unsigned int nUserData);</span></div>
<div> </div>
<div>IShellVtbl gvtShell = { IShell_CreateInstance };</div>
<div> </div>
<div>// 创建Shell对象</div>
<div>void IShell_CreateObject (void**ppObj, unsigned int nUserData)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CShell *pMe = malloc(sizeof(CShell));</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;pvt = &amp;gvtShell;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">* ppObj = (void*)pMe;</div>
<div>}</div>
<div> </div>
<div>// 创建由ClsID指定的</div>
<div>static void IShell_CreateInstance(IShell *pIShell,</div>
<div><span>                           int nClassID,</span></div>
<div><span>                           void **ppObj, </span></div>
<div><span>                           unsigned int nUserData)</span></div>
<div>{</div>
<div><span>    CShell *pMe = (CShell *)pIShell;</span></div>
<div><span>    </span></div>
<div style="text-indent: 21.75pt;">if(pMe == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">switch(nClassID){</div>
<div style="text-indent: 21.75pt;"><span>    case CLASSID_FASTSTRING:</span></div>
<div style="text-indent: 21.75pt;"><span>        <a name="OLE_LINK12">IFastString_CreateObject((IFastString **)ppObj, (char *)nUserData);</a></span></div>
<div style="text-indent: 21.75pt;"><span>        break;</span></div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;"><span>    case CLASSID_FASTNUMBER:</span></div>
<div style="text-indent: 21.75pt;"><span>        IFastNumber_CreateObject((IFastNumber **)ppObj, nUserData);</span></div>
<div style="text-indent: 21.75pt;"><span>        break;</span></div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;"><span>    </span>default:</div>
<div style="text-indent: 21.75pt;"><span>        break;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>在这个Shell接口中，我们定义了一个接口函数CreateInstance。它的作用是通过参数nClassID来创建指定的接口实例。IShell_CreateObject函数用来创建Shell接口本身，在使用的时候必须由系统直接调用IShell_CreateObject来产生Shell对象，然后再通过Shell接口来创建其他的接口（如FastString）。同时在这里包含了一个在本书中尚未实现的接口FastNumber，使用它仅仅是为了方便举例而已，因此有兴趣的读者可以仿照FastString接口实现FastNumber接口。</div>
<div><span>       </span>从shell.h和shell.c文件中可以看到，Shell接口的实现方式与第四版的FastString实现方式是相同的。更进一步的，从CreateInstance接口函数的内部实现我们可以知道，它使用了一个Class ID来识别用户创建的是哪一个接口，并通过switch语句实现相关接口的CreateObject函数的调用。通过这样的Shell管理，应用程序只需要知道一个Shell接口的指针就可以创建其他的接口了。换句话说，在启动应用程序的时候，我们先调用IShell_CreateObject函数创建一个Shell指针，并将这个Shell指针做为参数传递给应用程序的启动函数，那么理所当然的，我们就可以在应用程序中使用Shell的接口ISHELL_CreateInstance来创建其他的接口了。通过这样的方式，我们不但可以实现接口的管理工作，而且同时也为接口的扩展性提供了足够的灵活性。</div>
<div><strong><span style="font-size: medium;">6.<span>接口的扩展性</span></span></strong></div>
<div><span>       </span>到现在为止所展示的技术使得用户可以通过调用统一的C语言声明的接口，实现动态的二进制库的装载，这样可以无限制的升级库程序而不影响已有的应用程序，并且客户也不需要重新编译他们基于当前库文件所开发的应用程序，这对于创建一个复杂的运行平台来说是非常有用的。然而，这个接口却不能够随着时间而变化。这是因为客户在编译的时候需要有精确的接口定义，对接口的任何变化都需要客户重新编译他们的应用程序，以适应这种变化。更为糟糕的是，改变接口的定义完全违背了我们对接口封装性的要求。即便是最无伤大雅的变化，比如修改了接口的用途但是保留接口函数的原形不变，也会导致应用程序不再发生作用。这意味着接口的定义绝对不能改变，它既是语义上的约定，同时也是二进制层次上的约定。为了拥有一个稳定的，行为可预测性的运行时环境，接口的不变性这一要求是十分重要的。</div>
<div><span>       </span>尽管接口具有不变性的原则，但是我们通常需要在一个接口定义好之后，希望能够加入原先设计时没有预测到的新功能。此时我们可以利用对虚拟函数表布局结构的知识，只是简单的把新的方法追加到现有接口的底部，就可以实现对接口的扩展。考虑下面的FastString接口声明：</div>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>typedef struct _IFastString IFastString;</div>
<div>typedef struct _IFastStringVtbl IFastStringVtbl;</div>
<div> </div>
<div>struct _IFastString</div>
<div>{</div>
<div> struct IFastStringVtbl *pvt;</div>
<div>};</div>
<div> </div>
<div>struct _IFastStringVtbl</div>
<div>{</div>
<div style="text-indent: 21.75pt;">void (*Release) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*GetLength) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*Find) (IFastString *pIFastString, char *pFindStr);</div>
<div>};</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>简单的修改接口vtbl的声明，在现有的结构体内增加新的接口函数的类型声明，这样得到的二进制声明结构是原有的声明的超集，因为新的方法总是出现在旧版本方法之后。在针对新方法的接口实现中，我们可以填充在这个结构体中的函数指针：</div>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>typedef struct _IFastString IFastString;</div>
<div>typedef struct _IFastStringVtbl IFastStringVtbl;</div>
<div> </div>
<div>struct _IFastString</div>
<div>{</div>
<div> struct IFastStringVtbl *pvt;</div>
<div>};</div>
<div> </div>
<div>struct _IFastStringVtbl</div>
<div>{</div>
<div><span>    // </span>第一版接口</div>
<div style="text-indent: 21.75pt;">void (*Release) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*GetLength) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*Find) (IFastString *pIFastString, char *pFindStr);</div>
<div style="text-indent: 21.75pt;">// 第二版接口</div>
<div style="text-indent: 21.75pt;">int (*FindN)( IFastString *pIFastString, char *pFindStr, int n);</div>
<div>};</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>这种方式完全可以正常工作。在第一版接口上开发的应用程序将忽略前三个接口之外的其他接口的信息。当老的应用程序使用第二版接口实现的二进制程序的时候，它仍然可以正常的工作。然而，新的客户总是希望可以使用新的方法FindN，以便于能够获得子字符串第N次出现的位置。如果此时应用程序的运行平台依然使用的是第一个版本的实现，那么不幸的，问题发生了。当调用一个未曾实现的接口时，显而易见的，程序崩溃了。</div>
<div><span>       </span>这项技术的问题是修改了公开的接口，从而影响了接口的封装性。就像是只修改了C语言函数的声明会产生编译错误一样，改变了二进制的接口结构也会引起运行时的代码错误。这意味着接口必须是不可改变的，一旦公开后就不能再变化。解决这个问题有两种方法：一是允许接口的实现暴露多个接口，或者换句话说就是如果需要扩展老的接口，那么就重新定义一组新的接口，这样的话就可以在不支持新接口的旧平台上运行的时候判断接口的有效性，当然，这要求应用程序要对创建接口时的异常进行处理；二是支持在运行时对接口版本的判断或者在应用程序和运行平台之间有一种版本的比较机制，比如通过提供一个可以获得接口版本的API来进行版本的比较工作。不管是使用哪一种方法，无疑都会增加开发的负担，包括接口的开发者和用户的开发者，因此最好的方法是尽可能的不要去修改已经定义好的接口。</div>
<div><strong><span style="font-size: medium;">7.<span>资源管理</span></span></strong></div>
<div><span>       </span>当我们在使用我们的接口的时候，我们还会遇到另外的一个问题，请看下面的代码：</div>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>IFastString *pFastString;</div>
<div>char TargetStr[] = “This is a test example only!”’</div>
<div> </div>
<div>ISHELL_CreateInstance(pShell, CLASSID_FASTSTRING, (void **)&amp;pFastString, (unsigned int)TargetStr);</div>
<div> </div>
<div>(void)FastString_Test(pFastString);</div>
<div><a name="OLE_LINK13">IFASTSTRING_Release(pFastString);</a></div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>相应的FastString_Test函数如下：</div>
<table style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>int FastString_Test(IFastString *pFastString)</div>
<div>{</div>
<div><span>    int nOffset;</span></div>
<div style="text-indent: 21.75pt;">nOffset = IFASTSTRING_Find(pFastString, ”test”);</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">IFASTSTRING_Release(pFastString);</div>
<div style="text-indent: 21.75pt;">return nOffset;</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>在这个例子里，pFastString在主函数中创建，同时做为参数传递给了FastString_Test函数，然后释放pFastString，这很正常，没有什么问题。在FastString_Test函数中调用了Find方法，并且在使用函数退出的时候释放了pFastString指针，这很正常，也没有什么问题。然而，当我们将两者结合起来的时候，问题出现了：主函数中释放了一次接口指针，而在FastString_Test函数中也释放了一次同样的接口指针。换句话说，在这个程序中由于开发者的疏忽，对同一个接口释放了两次，这将导致不可预测的异常发生。这里面的问题是在增加了对接口指针的引用的时候，没有相应的处理机制来记录当前实例引用的次数，也就是当前接口实例的一个资源管理的问题。</div>
<div><span>       </span>或许您可以说这个问题可以通过使用者的细心来避免，那么我们再来看另外一个问题：如果当前的接口是可以共用的一些函数，比如这个接口中的方法全部是诸如STRLEN之类的重定义助手函数接口，并且在创建接口的时候需要分配一些公用的内存空间，那么，我们在每一次创建这个接口实例的时候，都必须分配不一样的存储空间吗？如果我们这样做了，实际上不会有什么问题，但是会浪费存储空间，因为他们本来是可以全部共用的。况且，如果我们全部都使用同一个指针在各个函数之间调用，那么对于这个指针来说使用起来会很危险的，因为我们不知道每一个函数是怎样处理这个指针的，这可真是太糟糕了。</div>
<div><span>       </span>为了解决这个问题，一个可行的做法是为每一个接口增加一个引用计数的管理机制。在增加了这个机制之后的第五版FastString实现如下：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.h<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口声明文件第五版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#ifndef FASTSTRING_H_</div>
<div>#define FASTSTRING_H_</div>
<div> </div>
<div>typedef struct _IFastString IFastString;</div>
<div>typedef struct _IFastStringVtbl IFastStringVtbl;</div>
<div> </div>
<div>struct _IFastString</div>
<div>{</div>
<div> struct IFastStringVtbl *pvt;</div>
<div>};</div>
<div> </div>
<div>struct _IFastStringVtbl</div>
<div>{</div>
<div style="text-indent: 21.75pt;">int (*AddRef) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*Release) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*GetLength) (IFastString *pIFastString);</div>
<div style="text-indent: 21.75pt;">int (*Find) (IFastString *pIFastString, char *pFindStr);</div>
<div>};</div>
<div> </div>
<div>// 增加接口指针的引用计数</div>
<div>#define IFASTSTRING_AddRef(p) ((IFastString*)p-&gt;pvt)-&gt;AddRef(p)</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>#define IFASTSTRING_Release(p) ((IFastString*)p-&gt;pvt)-&gt;Release(p)</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>#define IFASTSTRING_GetLength(p) ((IFastString*)p-&gt;pvt)-&gt;GetLength(p)</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>#define IFASTSTRING_Find(p,s) ((IFastString*)p-&gt;pvt)-&gt;Find(p,s)</div>
<div>#endif // FASTSTRING_H_</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>相应的实现文件如下：</div>
<table style="background: #ffcc99; border-collapse: collapse;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 426.1pt; padding-top: 0cm; border: windowtext 1pt solid;" width="568" valign="top">
<div>FastString.c<strong><span style="font-size: 12pt;">– </span></strong><strong><span style="font-size: 12pt;">接口实现文件第五版</span></strong></div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; background: none transparent scroll repeat 0% 0%; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="568" valign="top">
<div>#include ”FastString.h”</div>
<div>#include &lt;string.h&gt;</div>
<div> </div>
<div>typedef struct _CFastString {</div>
<div><span>    IFastStringVtbl *pvt; // </span>指向虚拟函数表的指针</div>
<div style="text-indent: 21pt;">int m_nRef;</div>
<div style="text-indent: 21pt;">char *m_pString;<span>    // </span>指向字符串的指针</div>
<div style="text-indent: 21pt;">int m_nLen;<span>        // </span>存储字符串的长度</div>
<div>} CFastString;</div>
<div> </div>
<div>// 函数声明</div>
<div>static int IFastString_AddRef(IFastString *pIFastString);</div>
<div>static int IFastString_Release(IFastString *pIFastString);</div>
<div>static int IFastString_GetLength(IFastString *pIFastString)</div>
<div>static int IFastString_Find(IFastString *pIFastString, char *pFindStr);</div>
<div> </div>
<div>IFastStringVtbl gvtFastString = { IFastString_AddRef,</div>
<div><span>                           IFastString_Release,</span></div>
<div><span>                           IFastString_GetLength,</span></div>
<div><span>                           IFastString_Find</span></div>
<div><span>                          };</span></div>
<div> </div>
<div>// 创建目标字符串对象</div>
<div>void IFastString_CreateObject (IFastString **ppIFastString, unsigned int nUserData)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = malloc(sizeof(CFastString));</div>
<div style="text-indent: 21.75pt;">char *pStr = (char *)nUserData;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe == NULL || pStr == NULL)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;pvt = &amp;gvtFastString;</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_nLen = strlen(pStr);</div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_pString = malloc(pMe-&gt;m_nLen +1);</div>
<div style="text-indent: 21.75pt;">strcpy(pMe-&gt;m_pString,pStr);</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">pMe-&gt;m_nRef = 1;</div>
<div style="text-indent: 21.75pt;">* ppIFastString = (IFastString *)pMe;</div>
<div style="text-indent: 21.75pt;"> </div>
<div>}</div>
<div> </div>
<div>// 增加接口指针的引用计数</div>
<div>static int IFastString_AddRef(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">return (++pMe-&gt;m_nRef);</div>
<div>}</div>
<div> </div>
<div>// 释放目标字符串对象</div>
<div>static int IFastString_Release(IFastString *pIFastString)</div>
<div>{</div>
<div><span>    CFastString *pMe = (CFastString *)pIFastString;</span></div>
<div><span>    </span></div>
<div style="text-indent: 21.75pt;">if(&#8211;pMe-&gt;m_nRef &gt;0)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    return pMe-&gt;m_nRef;</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">if(pMe-&gt;m_pString)</div>
<div style="text-indent: 21.75pt;">{</div>
<div style="text-indent: 21.75pt;"><span>    free(pMe-&gt;m_pString);</span></div>
<div style="text-indent: 21.75pt;">}</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">free(pMe)</div>
<div>}</div>
<div> </div>
<div>// 获取目标字符串长度</div>
<div>static int IFastString_GetLength(IFastString *pIFastString)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div><span>    return strlen(pMe-&gt;m_pString);</span></div>
<div>}</div>
<div> </div>
<div>// 查找字符串，返回偏移量</div>
<div>static int IFastString_Find(IFastString *pIFastString, char *pFindStr)</div>
<div>{</div>
<div style="text-indent: 21.75pt;">CFastString *pMe = (CFastString *)pIFastString;</div>
<div style="text-indent: 21.75pt;"> </div>
<div style="text-indent: 21.75pt;">// 搜索算法省略，因为这里仅仅假设存在这样的一个搜索算法</div>
<div>}</div>
</td>
</tr>
</tbody>
</table>
<div><span>       </span>在第五版的FastString中，我们主要是增加了接口AddRef。这个接口是在增加指针引用的时候调用的，它仅仅增加了接口内部变量m_nRef。同时为了实现相应的机制，在Release方法内增加了对引用计数的条件判断：如果当前的引用计数不为零，则直接返回引用计数的值，否则释放创建接口实例时所分配的内存。这样，当我们在使用上面的FastString_Test函数之前，调用IFASTSTRING_AddRef方法，就解决了资源管理的问题了。</div>
<div><span>       </span>增加这个AddRef方法还有一定的人为因素，因为只要程序员能够足够的注意，那么就不会存在资源管理的问题。但是，人生不如意十有八九，我们不能将全部的希望都寄托在程序员的身上，谁都有犯错误的时候。因此增加了AddRef的约定，它与Release方法相对应，形成了一种对称的编程“美感”，约定了是要增加了对指针的引用就调用AddRef，对应的在在适当的位置使用Release释放指针引用。</div>
<div><span>       </span>细心的读者可能还会发现第五版的FastString的实现中有两处不一样：一是IFastString_CreateObject函数的参数变化了，由原来的char *类型成了现在的unsigned int类型，这样做的目的是为了统一在Shell程序中CreateObject的形式；二是FastString接口函数中if(pMe == NULL)的判断去掉了，我们知道，在第一版的FastString中这句判断是很有必要的，它可以检测当前指针的有效性，那么想象一下对于我们的虚拟函数表NULL指针意味着什么？根据我们已有的虚拟函数表的知识，调用的接口是基于IFastString指针的相对偏移量，例如使用NULL指针来调用Release接口，那么实际上调用的是基于0地址的4字节偏移位置的函数，只有天知道这个地址中存储的是什么东西！因此，为接口传递空指针的时候会不可避免的发生异常，根本就不可能执行到接口函数，所以相应的判断是没有任何意义的。相应的示意图如下：</div>
<div><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-5.bmp" alt="" /></div>
<div>图5 接口的偏移量</div>
<div><span>       </span>最后，再让我们清楚地看一下这种虚拟函数表所实现的总体框图吧，看看应用程序、接口定义以及接口实现之间的关系：</div>
<div><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/Gemsea/13-6.bmp" alt="" /></div>
<div>图6 应用程序、接口定义以及接口实现的关系</div>
<div><span>       </span>至此，我们已经完成了全部需要解决的问题，最终我们实现的第五版FastString就是BREW接口的实现方法，只不过在实现的细节上有所不同。同时，我也相信各位在阅读了第二部分之后，一定会对这一部分的介绍颇有感触。接下来我们就趁热打铁，介绍BREW实现方法的一些高级特性，其中涉及了面向对象和COM组件的相关知识，对于没有接触过这两部分内容的读者来说，阅读可能会有一定困难。不过我会尽我最大的努力，争取用最容易理解的方式来阐述这些特性。</div>
<div><strong><span style="font-size: medium;"><span>7.面向对象的特性</span></span></strong></div>
<div><span>       C</span>语言本身没有面向对象的特性，但是我们使用C语言开发的BREW就具有了面向对象的特性了。面向对象的主要特征是：数据抽象、继承和多态。数据抽象指的是使用一组数据和方法描述一个我们要表达的内容（对象），它的关键点在于将方法和数据结合也叫做封装；继承是指一个对象可以通过某种方式使用另一个对象中的方法和数据，它包含了语法上的继承和二进制层次的继承；多态是指通过虚拟函数实现的成员函数晚捆绑的特性，其核心的特征是成员函数的晚捆绑。</div>
<div><span>       BREW</span>具有良好的数据抽象特性，它将全部的数据封装在了接口实现的内部，只将接口函数暴露给外部使用。这种方式是实现数据封装的理想方式，我想这一点可以从前面的“封装性”一节看出来。因此，BREW已经具有了面向对象的第一个特性。</div>
<div><span>       </span>在这个最好的封装实现的基础上，根本没有任何数据直接暴露出来，因此，继承性就体现在接口的继承上面了。由于BREW是使用C语言实现的，因此没有办法实现语法上的直接继承，但是它实现了二进制层次上的继承。继承在二进制上的表现就是在本数据结构中兼容另一个数据结构。例如，假设结构体A中包含了成员int i，现在有结构体B包含了同样的int i类型的成员，并且后面紧跟了int j成员，此时B结构是A结构的超集，也可以说B结构继承了A结构。现在我们已经知道BREW接口的二进制结构，如果需要实现二进制的BREW继承，我们就可以通过定义一个接口A的超集来实现另一个接口B，此时我们就可以说这个接口B是从接口A继承来的。我们可以通过接口A的定义使用接口B中的方法。因此说，BREW具有面向对象的继承的特性，只不过不是在语法上，而是在二进制的数据结构层面。</div>
<div><span>       </span>面向对象的第三个特性就是多态，可以说这个特性是BREW天生的。我们知道BREW一开始就是通过VTBL来实现的，可以实现运行时的接口函数绑定（也就是迟绑定）。关于这里点我们可以从五个版本的FastString的实现中发现这一过程。晚捆绑与早捆绑的区别在于早捆绑在使用接口的时候再编译链接的时候就已经确切的知道每个接口函数的地址，这就类似于使用一个C语言的库；而晚捆绑则是在运行时才知道每个接口函数的确切地址，因为虚拟函数表是在运行时才赋值给相应的接口的。使用这种技术的一个动机是我们可以在运行的时候控制使用一个接口中的多个实现中的哪一个实现。如果当前FastString接口已经公开了，那么可能会有第三方的厂家按照这个接口规范，来实现一个更好的FastString接口。与最原始的FastString接口布局一样，新的实现的接口函数布局与老的一样，那么此时仅仅需要更新一个Class ID我们就可以切换到新的接口了。使用晚捆绑的另一个动机是，应用程序可以检测到当前的运行平台是否已经实现了此接口，并给予相应的处理，这样可以避免在接口为实现的平台上运行时引起致命的错误。</div>
<div><span>       </span>综上所述，BREW具有了面向对象的三个主要特性，因此说他是具有面向对象性质的一种开发平台。</div>
<div><strong><span style="font-size: medium;">8.<span>与COM</span><span>的比较</span></span></strong></div>
<div><span>       COM</span>是Windows平台上实现的一种跨语言的开发机制，目前在Windows平台的底层，许多功能都是通过COM机制来实现的。COM通过统一的、独立的接口定义语言（IDL：Interfase Definition Language）来定义统一的接口，并规定了相应的接口二进制规范，这样就可以按照这个二进制规范，通过各种不同的开发语言来实现COM程序的开发，而实现这种接口与实现之间完全分离的技术就是虚拟函数表（VTBL）。</div>
<div><span>       </span>熟悉COM开发的读者对BREW应该有一种似曾相识的感觉，没错，在我的定义中，BREW就是一个简单版本的COM。BREW与COM相比，它们的核心思想是十分一致的，都具有接口与实现分离的特性，都使用了VTBL的技术等等。它们的不同点主要表现在以下几个方面：</div>
<div><span>       </span>第一，它们的接口与实现间的分离程度不同。COM是接口和实现的完全分离，为此专门规范了统一的接口定义语言，因此而接口的实现可以采用任何一种开发语言，如C/C++和Java等。而BREW则为了简化开发，使用了C语言形式的接口定义，这样就使得BREW的应用程序和实现都需要基于同样规则的编译器。或者换句话说，COM实现是与开发语言无关的，而BREW的实现则是与语言相关的。</div>
<div><span>       </span>第二，它们的接口创建方式不同。COM通过Windows注册表，使用文本的名字寻找相应的Class ID（这个Class ID需要通过注册程序进行注册），例如FastString接口可以通过传递字符串“FastString”最为参数从而创建FastString接口，实现这个功能的基础是运行时的类型识别技术（RTTI，相关的内容可以参考VC的书籍）。而BREW则为了简便起见，仅仅通过Class ID来创建接口。</div>
<div><span>       </span>第三，它们的规范层次不同。COM是二进制层次的规范，只要符合COM的二件制规范，我们可以使用任何一种语言进行开发。而BREW则是一种开发语言上的规范（使用了统一的C语言接口定义）。当然，我们也可以把BREW做为一种二进制层次的规范，但是似乎这并不大适合于在嵌入式系统中应用程序，因为当前大部分嵌入式系统都是使用C语言来开发的。不过对于BREW应用程序来说，只要遵循BREW的调用约定，是可以使用其它语言开发的。这里就不详细的讨论这个问题了。</div>
<div><strong><span style="font-size: medium;"><span>9.小结</span></span></strong></div>
<div><span>       </span>本章介绍了BREW实现的来龙去脉，展示了BREW所需要解决的两个主要问题：如何启动程序以及如何调用平台中的函数。最终，我们通过五个版本的FastString事例解决了全部的问题。BREW的本质是通过虚拟函数表技术实现了接口定义与接口实现之间的分离，这样BERW应用程序就可以存储在文件系统中，并在运行的时候调用接口函数。可以这样说，BREW已经将C语言运用到了极至，理解了BREW的原理可以对程序的开发有更加深入的认识。</div>

	<h4>相关文章</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.donevii.com/post/817.html" title="在BREW程序中调用另一个mod的分析 (2009-05-17)">在BREW程序中调用另一个mod的分析</a> (0)</li>
	<li><a href="http://www.donevii.com/post/744.html" title="《深入BREW》 &#8211; 硬件基础 (2009-01-18)">《深入BREW》 &#8211; 硬件基础</a> (0)</li>
	<li><a href="http://www.donevii.com/post/820.html" title="How to run mod file that is loaded into HEAP (2009-05-17)">How to run mod file that is loaded into HEAP</a> (1)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/746.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>《深入BREW》 &#8211; 硬件基础</title>
		<link>http://www.donevii.com/post/744.html</link>
		<comments>http://www.donevii.com/post/744.html#comments</comments>
		<pubDate>Sat, 17 Jan 2009 18:17:37 +0000</pubDate>
		<dc:creator>gavinkwoe</dc:creator>
				<category><![CDATA[brew]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://www.donevii.com/?p=744</guid>
		<description><![CDATA[转至Gemsea大人的BLOG：http://blog.csdn.net/Gemsea
 硬件是软件的运行平台，没有硬件的支撑软件也将不复存在。您能想象没有显示器软件将如何显示图形，没有CPU软件将如何运行吗？反正我想象不到... ]]></description>
			<content:encoded><![CDATA[<p>转至Gemsea大人的BLOG：<a href="http://blog.csdn.net/Gemsea">http://blog.csdn.net/Gemsea</a></p>
<p> 硬件是软件的运行平台，没有硬件的支撑软件也将不复存在。您能想象没有显示器软件将如何显示图形，没有CPU软件将如何运行吗？反正我想象不到！但是如果把问题反过来问就问到本质了，软件运行需要哪些硬件支持呢？看图1.1：</p>
<p><span></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>CPU</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>RAM</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>ROM</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>输出设备</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>输入设备</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>存储设备</div>
</div>
</td>
</tr>
</tbody>
</table>
<p></span></p>
<div>图1.1 系统结构框图</div>
<div><span>       </span>我们抛开硬件的什么电器特性等等，去芜存菁，就是上面的这个图了。如果程序要运行没有CPU是不行的，CPU要快速的交换数据，没有RAM也是不行的。因此无论任何系统，CPU和RAM都是必不可少的。您一定会提醒我ROM不也是不变的吗？这种说法不完全对，因为在PC系统和嵌入式系统之间ROM的作用是不一样的。在PC系统中ROM就是那个BIOS芯片，是用来提供系统的启动代码和基本的输入输出功能的；而在嵌入式系统中，ROM存储了全部的代码，它已经将PC中的BIOS和硬盘的与代码相关的功能混合在一起了。</div>
<table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 77.4pt; padding-top: 0cm; border: windowtext 1pt solid;" width="103" valign="top">
<div>设备</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>PC系统典型硬件设备</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>嵌入式系统典型硬件设备</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>CPU</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>任何CPU</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>任何CPU</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>RAM</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>任何RAM</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>任何RAM</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>ROM</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>BIOS芯片</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>Flash芯片</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>存储设备</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>硬盘</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>Flash芯片</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>输入设备</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>键盘</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>键盘</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 77.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="103" valign="top">
<div>输出设备</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>显示卡+显示器</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 174.35pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="232" valign="top">
<div>LCD显示屏</div>
</td>
</tr>
</tbody>
</table>
<div><span>       PC</span>的ROM ——BIOS芯片可以采用Flash芯片，在这里之所以不写成Flash芯片是因为BIOS的作用和嵌入式系统的Flash作用不大一样，使用BIOS以示区分。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296135">1.1 CPU</a><span>和RAM</span></span></strong></div>
<div style="TEXT-INDENT: 21pt">从软件观点来讲，任何CPU和RAM都可以应用于各种系统中，不存在明显的区别，只要CPU可以执行指令控制设备就可以了。但是考虑到耗电以及体积（嵌入式设备通常要求耗电低、体积小）等问题，嵌入式系统就发展出了专用的CPU芯片。当前应用最广泛的是ARM CPU。ARM CPU是由英国的ARM公司设计的，由于其执行效率高，体积小，耗电少等特点被广泛应用于嵌入式系统。由于嵌入式系统要求高集成度，通常不会存在单独的CPU芯片，而是将CPU和很多的外围电路集成到一起，做成一块芯片，因此ARM采用授权的方式提供内核芯片设计，以便于使用者进行芯片的集成。</div>
<div style="TEXT-INDENT: 21pt">CPU按照次执行指令的数据带宽可以分为16位、32位、64位等。32位CPU一次只能处理32位，也就是4个字节的数据；而64位CPU一次就能处理64位即8个字节的数据。如果我们将总长128位的指令分别按照16位、32位、64位为单位进行编辑的话：旧的16位CPU（如Intel 80286 CPU）需要8个指令，32位的CPU需要4个指令，而64位CPU则只要两个指令。显然，在工作频率相同的情况下，64位CPU的处理速度比16位、32位的更快。</div>
<div style="TEXT-INDENT: 21pt">除了运算能力之外，与32位CPU相比，64位CPU的优势还体现在系统对内存的控制上。由于地址使用的是特殊的整数，而64位CPU的一个ALU（算术逻辑运算器）和寄存器可以处理更大的整数，也就是更大的地址。传统32位CPU的寻址空间最大为4GB，使得很多需要大容量内存的大规模的数据处理程序在这时都会显得捉襟见肘，形成了运行效率的瓶颈。而64位的处理器在理论上则可以达到1800万个TB（1TB=1024GB），将能够彻底解决32位计算系统所遇到的瓶颈现象。当然64位寻址空间也有一定的缺点：内存地址值随着位数的增加而变为原来的两倍，这样内存地址将在缓存中占用更多的空间，其他有用的数据就无法载入缓存，从而引起了整体性能一定程度的下降。</div>
<div style="TEXT-INDENT: 21pt">在进行系统设计时，会根据不同寻址能力的CPU来进行寻址空间的分配。由于CPU都是通过设备的寄存器（这个寄存器可以理解为设备本身带的RAM）来控制设备的，因此地址空间的划分就显得十分重要。例如，一个具有32位寻址能力的CPU不可能讲全部的地址空间都分配给RAM，好比PC系统需要为BIOS分配存储空间等。也就是说只要是需要CPU直接控制的外部设备都需要为其分配CPU地址空间。</div>
<div style="TEXT-INDENT: 21pt">RAM就是可以随机访问，快速读写的存储器。CPU可以直接从RAM中取得数据（CPU可以从所有分配了地址空间的设备寄存器中取得数据）或代码指令，因此RAM的访问速度将直接影响系统的性能。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296136">1.2 ROM</a><span>存储芯片</span></span></strong></div>
<div><span>       ROM</span>是每个计算机系统必不可少的，但是其实现的方式却不尽相同。在我们熟悉的PC系统中，ROM是一个称作BIOS（Base Input &amp; Output System）的芯片。CPU上电时会从ROM中读取指令，因此没有ROM的系统是不能够运行的，因为如果没有ROM，CPU将无法获得起始的执行指令。在PC系统中BIOS的作用除了提供起始指令以外，还会扫描硬件设备并初始化主板（Main Board）上的硬件接口。由于PC上的接口都遵循着一组通用的协议，因此BIOS就可以实现所有硬件接口的驱动（如USB接口、显示卡、键盘和鼠标等）和硬件的数据输入输出功能，这也是BIOS（基本输入输出系统）名称的由来了。在BIOS控制的硬件接口中也包含了硬盘的控制接口，在BIOS初始化完成后就会到硬盘主分区上查找启动文件（<em>注</em><em>3</em>），后面的事情就交给PC的操作系统了。这个过程请看图1.2。</div>
<div><span>       </span>通常，在硬盘内有一个主引导记录区，在安装操作系统的时候由操作系统写入Boot程序，BIOS就是取出这段程序然后执行。由于Boot程序是由操作系统写入的，因此从这个Boot程序开始，系统的运行权限就交由操作系统来控制了。以Windows2000操作系统为例，这段代码区域执行时会搜索名叫“NTLDR”的系统文件。之所以分成Boot程序和NTLDR文件的原因是硬盘的Boot Sector很小（只有466Bytes），不可能容纳全部的启动程序。</div>
<div><span>       </span>图1.2只是一个启动的示意图，在这里我并没有详细的列出每一个必须的步骤，因为我的目的只是让我们能够了解BIOS硬件芯片在系统中的作用。</div>
<div><span>       </span>对比PC的BIOS，嵌入式系统由于软件规模小，因此将引导代码和操作系统代码全部放到了系统的Flash芯片中了。正如我们所知道的，PC机上大部分的操作系统代码全部放在硬盘上，然后从硬盘上将程序载入内存执行。而嵌入式系统中目前大多数采用直接寻址的方式从Nor Flash芯片中读取代码并执行。因此，实际上嵌入式系统简化了PC系统的设计，将PC系统中的BIOS和硬盘代码全部集中到了一个Flash芯片上。因此BIOS虽然也可以使用Flash芯片，但是相对于嵌入式系统来说，他们的含义和作用却不同。</div>
<p><span></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>BIOS自检</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>显卡BIOS检测</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>CPU型号检测、内存测试</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>读取硬盘启动扇区</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>获取操作系统启动文件</div>
</div>
</td>
</tr>
</tbody>
</table>
<p></span></p>
<div>图1.2 PC开机流程</div>
<div style="TEXT-INDENT: 21pt">Flash芯片对于我们来说并不陌生，那些可以更新BIOS程序的BIOS芯片也是使用Flash芯片实现的，还有MP3用的SD卡等等也是Flash芯片。Flash芯片是一种可以多次擦写的存储芯片，广泛的应用于嵌入式系统。Flash的特点是耗电低，容量大（相对于嵌入式系统而言），写入之前需要先擦除（因为Flash芯片的存储单元只允许从1变到0）。当前流行的分为NOR Flash和NAND Flash。</div>
<div style="TEXT-INDENT: 21pt">NAND与NOR Flash的区别主要有：</div>
<div style="TEXT-INDENT: 21pt">1、NAND Flash的空间比Nor Flash大</div>
<div style="TEXT-INDENT: 21pt">2、NAND Flash的访问速度比Nor Flash快</div>
<div style="TEXT-INDENT: 21pt">3、NAND Flash只有Page访问模式，Nor Flash可以进行Page和直接地址访问（直接地址访问也就是CPU可以直接寻址，或者叫做随机访问）</div>
<div style="TEXT-INDENT: 21pt">4、NAND Flash允许有坏块，但是Nor Flash不能有坏块</div>
<div style="TEXT-INDENT: 21pt">5、NAND Flash比NOR Flash更加便宜</div>
<div style="TEXT-INDENT: 21pt">在嵌入式系统中，NOR 和NAND都可以做为代码区和文件系统区来使用。通常情况下NOR和NAND做为嵌入式文件系统区的时候都使用Page模式。Page模式允许一次读取多个字节，就像硬盘的最小读写单位是扇区一样，只不过Flash的最小读写单位叫做Page。Page模式下可以加快Flash的读写速度。由于NAND Flash只支持Page读写模式，因此使用NAND Flash做为代码区的时候需要外加控制电路。当前使用NAND做为代码区正在成为一种流行的趋势（因为NAND Flash成本更低），主要的实现方式有两种：一是添加仿真电路使得NAND Flash可以支持随机访问；二是增加一个类似硬盘的引导区（通常是第一个Page），系统启动的时候使用引导区的代码将全部NAND中的代码复制到RAM中执行。</div>
<div style="TEXT-INDENT: 21pt">当然，可以设想随着将来嵌入式操作系统的发展，动态载入内存的形式也许就会出现了，但是目前嵌入式系统仍然没有发展到这个地步。更进一步，当前应用于嵌入式系统的微型硬盘也已经出现了，或许更为复杂的操作系统也可以应用在嵌入式系统上了。</div>
<div style="TEXT-INDENT: 21pt">在这里我们主要介绍的ROM存储芯片是Flash，严格意义上说Flash并不能称作ROM，因为ROM是只读存储器（Read Only Memory），而Flash是一种可读可写的芯片。但是由于ROM“一次成型、终生不变”的特点，不便于升级换代，现在正逐渐的被Flash芯片所取代，但是其功能性的称谓“ROM”还在为大家所用。</div>
<div style="TEXT-INDENT: 21pt">在计算机系统中主要存在用户数据、程序数据和代码三种二进制内容。用户数据指用户文件，程序数据是指程序运行时需要修改或使用的非代码内容。下面将就PC系统和嵌入式系统中的这三种二进制内容做一个比较，请看下表：</div>
<table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 68.4pt; padding-top: 0cm; border: windowtext 1pt solid;" width="91" valign="top">
<div>二进制形态</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>PC系统</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>嵌入式系统</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 68.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="91" valign="top">
<div>用户数据</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>存储在文件系统中，典型的设备是硬盘</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>存储在文件系统中，典型的设备是Flash存储芯片</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 68.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="91" valign="top">
<div>程序数据</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>可读可写的数据存放在RAM中；只读数据存放在硬盘中，运行时与代码一起读入RAM</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>可读可写的数据存放在RAM中；只读数据存放在Flash中，与代码存储在同一个区域</div>
</td>
</tr>
<tr>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 68.4pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="91" valign="top">
<div>代码</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>存储在文件系统中的文件里，运行时读入RAM由CPU执行</div>
</td>
<td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 178.85pt; padding-top: 0cm; border-bottom: windowtext 1pt solid;" width="238" valign="top">
<div>如果存储在NOR Flash等可随机访问的空间中则CPU直接在芯片中取指令运行；如果存储在NAND Flash等不能随机访问的空间中则需要读入RAM中运行</div>
</td>
</tr>
</tbody>
</table>
<div style="TEXT-INDENT: 21pt">关于程序数据的详细情况将在编译器基础一节详细介绍。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296137">1.3 </a><span>输出设备</span></span></strong></div>
<div><span>       </span>输出设备有很多种，例如显示器、打印机，在这里我们主要讲一下显示设备。</div>
<div style="TEXT-INDENT: 21pt">任何显示设备都是点阵式的，至少目前是这样。还记得初次看见电视里显示的人物时内心的惊异，这个世界竟是如此神奇！后来知道了，如果我愿意，我可以买640*480个灯泡，组成一个640*480的方阵，然后控制每个灯泡的亮灭，我也可以显示一个人物。终于懂了，原来任何的显示设备都是基于这个原理实现的。我想关于这一点我没有必要再多说什么了，毕竟万变不离其宗嘛。</div>
<div><span>       </span>当前流行的显示设备有CRT显示器（也就是电脑上很大个头的那种显示器），LCD（液晶）等（虽然我在大学实验室里用的可以显示数字的LED灯也是显示设备，但是他太简单了）。CRT显示器经历了从球形到纯平的物理演变，LCD则经历了从黑白到彩色的变化。按照显示器每个点能够显示的颜色数目可以分为黑白两色、灰度、8位色、16位色、24位真彩色等显示设备。这个颜色数目就是所谓的色深（Color Depth），色深越大，每个点能够表达的颜色数就越多，这个点就是“象素”。</div>
<div><span>       </span>在嵌入式系统中主要使用LCD的显示设备，LCD会集成一个显示的存储空间，在这个空间中存储了对应的每个象素的值。例如16位色的LCD每个象素需要由2个字节来表示，如果显示屏幕的大小是100*100，那么就需要2*100*100 = 20000个字节的存储空间。程序正是通过更新这个存储空间中的内容来控制LCD的显示。</div>
<div style="TEXT-INDENT: 21pt">衡量LCD显示效果的还有象素间距，象素间距越小，画面就越细腻，显示效果越好。举个极端的例子，如果一个象素是整个LCD那么大，那就只能看见一个象素点的“灯泡”了，也就没法显示图像了。通过像素个数和每个点的大小就可以换算出显示屏的大小了，例如常用的xx英寸大小的屏幕等等。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296138">1.4 </a><span>输入设备</span></span></strong></div>
<div><span>       </span>输入设备也有很多种，最典型的是键盘和触摸屏。在这一节里，我将简单的介绍一下它们的实现原理。</div>
<div><span>       </span>键盘通常是一个矩阵式的电路，当按键按下的时候，接通电路产生信号，如图1.3：</div>
<p><span></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>1</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>2</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>3</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>A</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>B</div>
</div>
</td>
</tr>
</tbody>
</table>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td>
<div>
<div>C</div>
</div>
</td>
</tr>
</tbody>
</table>
<p></span></p>
<div>图1.3 键盘原理</div>
<div><span>       </span>图1.3是一个简版的键盘原理图，图中任何交叉点的横向和纵向都未连通，并假设只要交叉点连通，则相应的行和列就可以连通并发生状态改变。其中1、2、3和A、B、C连接在控制芯片上，通过扫描行和列，确定行的A、B、C是否连通，再扫描列1、2、3是否连通，这样就可以唯一确定一个点是否按下。千万注意，这只是一个示意图，并不是真正的键盘原理图。</div>
<div><span>       </span>触摸屏是近来应用越来越多的输入器件。典型触摸屏的工作部分一般由三部分组成：两层透明的阻性导体层、两层导体之间的隔离层、电极。阻性导体层选用阻性材料，如铟锡氧化物（ITO）涂在衬底上构成，上层衬底用塑料，下层衬底用玻璃。隔离层为粘性绝缘液体材料，如聚脂薄膜。电极选用导电性能极好的材料（如银粉墨）构成。</div>
<div><span>       </span>触摸屏在工作时，上下导体层相当于电阻网络。当某一层电极加上电压时，会在该网络上形成电压梯度。如有外力使得上下两层在某一点接触，则在电极未加电压的另一层可以测得接触点处的电压，从而知道接触点处的坐标。比如，在顶层的电极(X+,X－)上加上电压，则在顶层导体层上形成电压梯度，当有外力使得上下两层在某一点接触，在底层就可以测得接触点处的电压，再根据该电压与电极(X+)之间的距离关系，知道该处的X坐标。然后，将电压切换到底层电极（Y+,Y－）上，并在顶层测量接触点处的电压，从而知道Y坐标。通常有专门的控制芯片。很显然，触摸屏的控制芯片要完成两件事情：一是完成电极电压的切换；二是采集接触点处的电压值（即A/D）。虽然还有其他的实现方法，我就不赘述了，因为本书的目的不是讲解硬件的原理，而仅仅是让我们能够基本了解它们。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296139">1.5 </a><span>小结</span></span></strong></div>
<div><span>       </span>在这一章里介绍了各种硬件的特性和原理，其中包括了最小系统各种组件的介绍，为的是防止我们见到这些东西的时候会一头雾水，不知来由。只要我们见到这些硬件不再感到神秘，那么这个基础就算打好了。</div>
<div><strong><span style="font-size: medium;"><a name="_Toc137296140">思考题</a></span></strong></div>
<div><span>       </span>在PC计算机系统中硬盘、BIOS、RAM和嵌入式系统中的文件Flash、程序Flash、RAM之间有什么区别？它们在系统中的作用分别是什么？</div>

	<h4>相关文章</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.donevii.com/post/817.html" title="在BREW程序中调用另一个mod的分析 (2009-05-17)">在BREW程序中调用另一个mod的分析</a> (0)</li>
	<li><a href="http://www.donevii.com/post/746.html" title="《深入BREW》 &#8211; BREW原理 (2009-01-18)">《深入BREW》 &#8211; BREW原理</a> (1)</li>
	<li><a href="http://www.donevii.com/post/820.html" title="How to run mod file that is loaded into HEAP (2009-05-17)">How to run mod file that is loaded into HEAP</a> (1)</li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.donevii.com/post/744.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
