<?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>对影成三人 &#187; program</title>
	<atom:link href="http://ichaochao.com/tag/program/feed/" rel="self" type="application/rss+xml" />
	<link>http://ichaochao.com</link>
	<description></description>
	<lastBuildDate>Wed, 04 Jan 2012 06:58:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>DSP中数的定标</title>
		<link>http://ichaochao.com/2008/07/03/dsp_q15/</link>
		<comments>http://ichaochao.com/2008/07/03/dsp_q15/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 08:03:13 +0000</pubDate>
		<dc:creator>chaochao</dc:creator>
				<category><![CDATA[假装懂技术]]></category>
		<category><![CDATA[DSP]]></category>
		<category><![CDATA[program]]></category>

		<guid isPermaLink="false">http://ichaochao.com/2008/07/03/dsp_q15/</guid>
		<description><![CDATA[在TI的文档&#60;spru402 _TMS320C62x DSP Library Programmer&#8217;s Reference&#62;中，提到了Q格式。关于这个，我手上的两本书，都没有提到，而TI的这个文档里也只是在附录里简单说明了一下。大意是：DSPLIB函数一般都使用Q15格式。其实这个Q15确切的说是Q0.15。格式是Qm.n，m指小数点前（即整数部分）的数的个数，n指小数点后（即小数部分）的数的个数，再加上最高位是符号位，这样Q15就是一个16位的word。它表示的范围是（1，-1）。它表示的数分辨率是2的-15次方，数是用2的补码来表示的。   

&#160;
如此，既然可以有Q.15，那也可以有Q.31，当然也可以有Q3.12这样形式的。可以看出，不同的Q所表示的数不仅范围不同，而且精度也不相同。Q越大，数值范围越小，但精度越高；相反，Q越小，数值范围越大，但精度就越低。范围与精度是一对不可调和的矛盾，实际应用中，只能视实际需要来取平衡。
有了Q格式，就可以用定点DSP来计算浮点数。   
&#8212;&#8212;&#8212;-&#160; 关于补码相关知识的温故知新 &#8212;&#8212;&#8212;-   
原码就是这个数本身的二进制形式。如：00000001 就是+1 10000001 就是-1。    反码表示法规定：正数的反码与其原码相同；负数的反码是对其原码逐位取反，但符号位除外。    补码表示法规定：正数的补码与其原码相同；负数的补码是在其反码的末位加1。
补码的意义：   （1）补码统一正0和负0    （2）补码中符号位要与有效值部分一起进行运算。    （3）使减法运算转换为加法运算。 [a-b]补=[a]补+[-b]补
链接1：关于补码的详细介绍
链接2：DSP定点算数运算
]]></description>
			<content:encoded><![CDATA[<p>在TI的文档&lt;spru402 _TMS320C62x DSP Library Programmer&#8217;s Reference&gt;中，提到了Q格式。关于这个，我手上的两本书，都没有提到，而TI的这个文档里也只是在附录里简单说明了一下。大意是：DSPLIB函数一般都使用Q15格式。其实这个Q15确切的说是Q0.15。格式是Qm.n，m指小数点前（即整数部分）的数的个数，n指小数点后（即小数部分）的数的个数，再加上最高位是符号位，这样Q15就是一个16位的word。它表示的范围是（1，-1）。它表示的数分辨率是2的-15次方，数是用2的补码来表示的。   </p>
<p><span id="more-156"></span></p>
<p>&#160;</p>
<p>如此，既然可以有Q.15，那也可以有Q.31，当然也可以有Q3.12这样形式的。可以看出，不同的Q所表示的数不仅范围不同，而且精度也不相同。Q越大，数值范围越小，但精度越高；相反，Q越小，数值范围越大，但精度就越低。范围与精度是一对不可调和的矛盾，实际应用中，只能视实际需要来取平衡。</p>
<p>有了Q格式，就可以用定点DSP来计算浮点数。   </p>
<p>&#8212;&#8212;&#8212;-&#160; 关于补码相关知识的温故知新 &#8212;&#8212;&#8212;-   </p>
<p>原码就是这个数本身的二进制形式。如：00000001 就是+1 10000001 就是-1。    <br />反码表示法规定：正数的反码与其原码相同；负数的反码是对其原码逐位取反，但符号位除外。    <br />补码表示法规定：正数的补码与其原码相同；负数的补码是在其反码的末位加1。</p>
<p>补码的意义：   <br />（1）补码统一正0和负0    <br />（2）补码中符号位要与有效值部分一起进行运算。    <br />（3）使减法运算转换为加法运算。 [a-b]补=[a]补+[-b]补</p>
<p>链接1：<a href="http://hi.baidu.com/maytao/blog/item/52fab4544ae1521e3a2935e3.html" target="_blank">关于补码的详细介绍</a></p>
<p>链接2：<a href="http://www.61ic.com/Article/FAQ/soft/200610/6791.html" target="_blank">DSP定点算数运算</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ichaochao.com/2008/07/03/dsp_q15/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>C语言高效编程的几招(转)</title>
		<link>http://ichaochao.com/2008/07/01/c_program/</link>
		<comments>http://ichaochao.com/2008/07/01/c_program/#comments</comments>
		<pubDate>Tue, 01 Jul 2008 00:09:56 +0000</pubDate>
		<dc:creator>beethoven</dc:creator>
				<category><![CDATA[假装懂技术]]></category>
		<category><![CDATA[program]]></category>

		<guid isPermaLink="false">http://ichaochao.com/?p=149</guid>
		<description><![CDATA[引 言：
编写高效简洁的C语言代码，是许多软件工程师追求的目标。本文就工作中的一些体会和经验做相关的阐述，不对的地方请各位指教。

第1招：以空间换时间
计算机程序中最大的矛盾是空间和时间的矛盾，那么，从这个角度出发逆向思维来考虑程序的效率问题，我们就有了解决问题的第1招——以空间换时间。
例如：字符串的赋值。
方法A，通常的办法：
#define LEN 32
char string1 [LEN];
memset (string1,0,LEN);
strcpy (string1,“This is a example!!”）;
方法B：
const char string2[LEN] =“This is a example!”;
char * cp;
cp = string2 ;
(使用的时候可以直接用指针来操作。)
从上面的例子可以看出，A和B的效率是不能比的。在同样的存储空间下，B直接使用指针就可以操作了，而A需要调用两个字符函数才能完成。B的缺点在于灵 活性没有A好。在需要频繁更改一个字符串内容的时候，A具有更好的灵活性；如果采用方法B，则需要预存许多字符串，虽然占用了大量的内存，但是获得了程序 执行的高效率。
如果系统的实时性要求很高，内存还有一些，那我推荐你使用该招数。
该招数的变招——使用宏函数而不是函数。举例如下：
方法C：
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
int BIT_MASK(int __bf)
{
return ((1U &#60;&#60; (bw ## __bf)) &#8211; 1) &#60;&#60; (bs ## __bf);
}
void SET_BITS(int __dst, int __bf, int __val)
{
__dst = ((__dst) &#38; ~(BIT_MASK(__bf))) &#124; \
(((__val) &#60;&#60; (bs <a href="http://ichaochao.com/2008/07/01/c_program/" class="more-link">More &#62;</a>]]></description>
			<content:encoded><![CDATA[<p class="p4"><strong>引 言：</strong><br />
编写高效简洁的C语言代码，是许多软件工程师追求的目标。本文就工作中的一些体会和经验做相关的阐述，不对的地方请各位指教。<br />
<span id="more-149"></span></p>
<p class="p4"><strong>第1招：以空间换时间</strong></p>
<p class="p4">计算机程序中最大的矛盾是空间和时间的矛盾，那么，从这个角度出发逆向思维来考虑程序的效率问题，我们就有了解决问题的第1招——以空间换时间。<br />
例如：字符串的赋值。<br />
方法A，通常的办法：<br />
#define LEN 32<br />
char string1 [LEN];<br />
memset (string1,0,LEN);<br />
strcpy (string1,“This is a example!!”）;<br />
方法B：<br />
const char string2[LEN] =“This is a example!”;<br />
char * cp;<br />
cp = string2 ;<br />
(使用的时候可以直接用指针来操作。)</p>
<p class="p4">从上面的例子可以看出，A和B的效率是不能比的。在同样的存储空间下，B直接使用指针就可以操作了，而A需要调用两个字符函数才能完成。B的缺点在于灵 活性没有A好。在需要频繁更改一个字符串内容的时候，A具有更好的灵活性；如果采用方法B，则需要预存许多字符串，虽然占用了大量的内存，但是获得了程序 执行的高效率。</p>
<p class="p4">如果系统的实时性要求很高，内存还有一些，那我推荐你使用该招数。</p>
<p class="p4">该招数的变招——使用宏函数而不是函数。举例如下：<br />
方法C：<br />
#define bwMCDR2_ADDRESS 4<br />
#define bsMCDR2_ADDRESS 17<br />
int BIT_MASK(int __bf)<br />
{<br />
return ((1U &lt;&lt; (bw ## __bf)) &#8211; 1) &lt;&lt; (bs ## __bf);<br />
}<br />
void SET_BITS(int __dst, int __bf, int __val)<br />
{<br />
__dst = ((__dst) &amp; ~(BIT_MASK(__bf))) | \<br />
(((__val) &lt;&lt; (bs ## __bf)) &amp; (BIT_MASK(__bf))))<br />
}</p>
<p class="p4">SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);<br />
方法D：<br />
#define bwMCDR2_ADDRESS 4<br />
#define bsMCDR2_ADDRESS 17<br />
#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)<br />
#define BIT_MASK(__bf) (((1U &lt;&lt; (bw ## __bf)) &#8211; 1) &lt;&lt; (bs ## __bf))<br />
#define SET_BITS(__dst, __bf, __val) \<br />
((__dst) = ((__dst) &amp; ~(BIT_MASK(__bf))) | \<br />
(((__val) &lt;&lt; (bs ## __bf)) &amp; (BIT_MASK(__bf))))</p>
<p class="p4">SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);</p>
<p class="p4">函数和宏函数的区别就在于，宏函数占用了大量的空间，而函数占用了时间。大家要知道的是，函数调用是要使用系统的栈来保存数据的，如果编译器里有栈检查 选项，一般在函数的头会嵌入一些汇编语句对当前栈进行检查；同时，CPU也要在函数调用时保存和恢复当前的现场，进行压栈和弹栈操作，所以，函数调用需要 一些CPU时间。而宏函数不存在这个问题。宏函数仅仅作为预先写好的代码嵌入到当前程序，不会产生函数调用，所以仅仅是占用了空间，在频繁调用同一个宏函 数的时候，该现象尤其突出。</p>
<p class="p4">D方法是我看到的最好的置位操作函数，是ARM公司源码的一部分，在短短的三行内实现了很多功能，几乎涵盖了所有的位操作功能。C方法是其变体，其中滋味还需大家仔细体会。</p>
<p class="p4"><strong>第2招：数学方法解决问题</strong></p>
<p class="p4">现在我们演绎高效C语言编写的第二招——采用数学方法来解决问题。</p>
<p class="p4">数学是计算机之母，没有数学的依据和基础，就没有计算机的发展，所以在编写程序的时候，采用一些数学方法会对程序的执行效率有数量级的提高。<br />
举例如下，求 1~100的和。<br />
方法E<br />
int I , j;<br />
for (I = 1 ;I&lt;=100; I ++）{<br />
j += I;<br />
}<br />
方法F<br />
int I;<br />
I = (100 * (1+100)) / 2</p>
<p class="p4">这个例子是我印象最深的一个数学用例，是我的计算机启蒙老师考我的。当时我只有小学三年级，可惜我当时不知道用公式 N×（N+1）/ 2 来解决这个问题。方法E循环了100次才解决问题，也就是说最少用了100个赋值，100个判断，200个加法（I和j）；而方法F仅仅用了1个加法，1 次乘法，1次除法。效果自然不言而喻。所以，现在我在编程序的时候，更多的是动脑筋找规律，最大限度地发挥数学的威力来提高程序运行的效率。</p>
<p class="p4"><strong>第3招：使用位操作</strong></p>
<p class="p4">实现高效的C语言编写的第三招——使用位操作，减少除法和取模的运算。</p>
<p class="p4">在计算机程序中，数据的位是可以操作的最小数据单位，理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的，或者做数据变换使用，但是，灵活的位操作可以有效地提高程序运行的效率。举例如下：<br />
方法G<br />
int I,J;<br />
I = 257 /8;<br />
J = 456 % 32;<br />
方法H<br />
int I,J;<br />
I = 257 &gt;&gt;3;<br />
J = 456 &#8211; (456 &gt;&gt; 4 &lt;&lt; 4);</p>
<p class="p4">在字面上好像H比G麻烦了好多，但是，仔细查看产生的汇编代码就会明白，方法G调用了基本的取模函数和除法函数，既有函数调用，还有很多汇编代码和寄存 器参与运算；而方法H则仅仅是几句相关的汇编，代码更简洁，效率更高。当然，由于编译器的不同，可能效率的差距不大，但是，以我目前遇到的MS C ,ARM C 来看，效率的差距还是不小。相关汇编代码就不在这里列举了。<br />
运用这招需要注意的是，因为CPU的不同而产生的问题。比如说，在PC上用这招编写的程序，并在PC上调试通过，在移植到一个16位机平台上的时候，可能会产生代码隐患。所以只有在一定技术进阶的基础下才可以使用这招。</p>
<p class="p4"><strong>第4招：汇编嵌入</strong></p>
<p class="p4">高效C语言编程的必杀技，第四招——嵌入汇编。</p>
<p class="p4">“在熟悉汇编语言的人眼里，C语言编写的程序都是垃圾”。这种说法虽然偏激了一些，但是却有它的道理。汇编语言是效率最高的计算机语言，但是，不可能靠着它来写一个操作系统吧?所以，为了获得程序的高效率，我们只好采用变通的方法 ——嵌入汇编，混合编程。</p>
<p class="p4">举例如下，将数组一赋值给数组二,要求每一字节都相符。<br />
char string1[1024],string2[1024];<br />
方法I<br />
int I;<br />
for (I =0 ;I&lt;1024;I++)<br />
*(string2 + I) = *(string1 + I)<br />
方法J<br />
#ifdef _PC_<br />
int I;<br />
for (I =0 ;I&lt;1024;I++)<br />
*(string2 + I) = *(string1 + I);<br />
#else<br />
#ifdef _ARM_<br />
__asm<br />
{<br />
MOV R0,string1<br />
MOV R1,string2<br />
MOV R2,#0<br />
loop:<br />
LDMIA R0!, [R3-R11]<br />
STMIA R1!, [R3-R11]<br />
ADD R2,R2,#8<br />
CMP R2, #400<br />
BNE loop<br />
}<br />
#endif</p>
<p class="p4">方法I是最常见的方法，使用了1024次循环；方法J则根据平台不同做了区分，在ARM平台下，用嵌入汇编仅用128次循环就完成了同样的操作。这里有 朋友会说，为什么不用标准的内存拷贝函数呢?这是因为在源数据里可能含有数据为0的字节，这样的话，标准库函数会提前结束而不会完成我们要求的操作。这个 例程典型应用于LCD数据的拷贝过程。根据不同的CPU，熟练使用相应的嵌入汇编，可以大大提高程序执行的效率。</p>
<p class="p4">虽然是必杀技，但是如果轻易使用会付出惨重的代价。这是因为，使用了嵌入汇编，便限制了程序的可移植性，使程序在不同平台移植的过程中，卧虎藏龙，险象环生！同时该招数也与现代软件工程的思想相违背，只有在迫不得已的情况下才可以采用。切记，切记。</p>
<p class="p4">使用C语言进行高效率编程，我的体会仅此而已。在此以本文抛砖引玉，还请各位高手共同切磋。希望各位能给出更好的方法，大家一起提高我们的编程技巧。</p>
]]></content:encoded>
			<wfw:commentRss>http://ichaochao.com/2008/07/01/c_program/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

