历史上的今天
返回首页

历史上的今天

今天是:2025年04月07日(星期一)

正在发生

2021年04月07日 | 高效的C编程之:C编译器及其优化(上)

2021-04-07 来源:eefocus

本章将帮助读者在ARM处理器上编写高效的C代码。本章涉及的一些技术不仅适用于ARM处理器,也适用于其他RISC处理器。本章首先从ARM编译器及其优化入手,讲解C编译器在优化代码时所碰到的一些问题。理解这些问题,将有助于编写出在提高执行速度和减少代码尺寸方面更高效的C源代码。


本章假定读者熟悉C语言,并且有一些汇编语言编程方面的知识。有关ARM编程的详细信息,请参阅本书的相关章节。


14.1C编译器及其优化


本章主要讲解C编译器在代码优化时遇到的一些问题。要编写高效的C语言源代码,必须了解C编译器对什么形式的代码有所改动,编译器涉及的处理器结构的限制,以及一些特殊的C编译器的限制。


14.1.1为编译器选择处理器结构


在编译C源文件时,必须为编译器指定正确的处理器类型。这样可以使编译的代码最大限度地利用处理器的硬件结构,如对半字加载(HalfwordLoad)、存储指令(StoreInstructions)和指令调度(InstructionScheduling)的支持。所以编译程序时,应该尽量准确地告诉编译器该代码是运行在什么类型的处理器上。有些处理器类型编译器是不能直接支持,如SA-1100,这时可以使用与该类型处理器为同一指令集的基本处理器,比如对于SA-100,可以使用StrongARM。


注意


指定目标处理器可能使代码与其他ARM处理器不兼容。例如,编译时指定了ARMv6体系结构的代码,可能不能运行在ARM920T的处理器上(如果代码中使用了ARMv6体系结构中特有的指令)。


选择处理器类型可以使用--cpuname编译选项。该选项生成用于特定ARM处理器或体系结构的代码。


如果name是处理器名称。


·输入名称必须和ARM数据表中所示严格一致,例如ARM7TDMI。该选项不接受通配符字符。有效值是任何ARM6或更高版本的ARM处理器。


·选择处理器操作会选择适当的体系结构、浮点单元(FPU)以及存储结构。


·某些--cpu选择暗含--fpu选择。例如,当使用--arm选项编译时,--cpuARM1136JF-S暗含--fpuvfpv2。隐式FPU只覆盖命令行上出现在--cpu选项前面的显式--fpu选项。如果没有指定--fpu选项和--cpu选项,则使用--fpusoftvfp。


14.1.2调试选项


如果在编译C源程序时,设置了调试选项,这将很大程度地影响最终代码的大小和执行效率。因为带调试信息的代码映像,为了能够在调试程序时正确地显示变量或设置断点,包含很多冗余的代码和数据。所以如果想最大限度地提供程序执行效率、减少代码尺寸,就要在编译源文件时,去除编译器的调试选项。


以下选项指定调试表生成方法。


·-g(--debug):该选项启用生成当前编译的调试表。无论是否使用-g选项,编译器都生成的代码是相同的。惟一差别是调试表的存在与否。编译器是否对代码进行优化是由-O选项指定调的。默认情况下,使用-g选项等价于使用:-g-dwarf2--debug_macros。


注意


编译程序时,只使用-g选项而没有使用优化选项,编译器会提示警告信息。


·--no_debug:该选项禁止生成当前编译的调试表。这是默认选项。


·--no_debug_macros:当与-g一起使用时,该选项禁止生成预处理程序宏定义的调试表条目(Entry)。这会减小调试映像的大小。-gt-p是-gtp的同义字。


--debug_macros当与-g一起使用时,该选项启用生成预处理程序宏定义的调试表条目。这是默认选项,会增加调试映像的大小。一些调试程序忽略预处理程序条目。


14.1.3优化选项


使用-Onum选择编译器的优化级别。优化级别分别为。


·-O0:除一些简单的代码编号之外,关闭所有优化。使用该编译选项可以提供最直接的优化信息。


·-O1:关闭严重影响调试效果的优化功能。使用该编译选项,编译器会移除程序中未使用到的内联函数和静态函数。如果与--debug一起使用,该选项可以在较好的代码密度下,给出最佳调试视图。


·-O2:生成充分优化代码。如果与--debug一起使用,调试效果可能不令人满意,因为目标代码到源代码的映射可能因为代码优化而发生变化。


如果不生成调试表,这是默认优化级别。


·-O3:最高优化级别。使用该优化级别,使生成的代码在时间和空间上寻求平衡。该选项常和-Ospace和-Otime配合使用。


·-O3–Otime:使用该选项编译的代码比-O2–Otime选项编译的代码,在执行速度上要快,但占用的空间也更大。


·-O3-Ospace:产生的代码比使用-O2-Ospace选项产生的代码尺寸小,但执行效率可能会差。


如果要使编译的代码更侧重于代码的尺寸或执行效率(两者往往不可兼得),可以使用下面的编译选项。


·-Ospace:指示编译程序执行优化,以延长执行时间为代价减小映像大小。例如,由外部函数调用代替内联函数。如果代码大小比性能更重要,则使用该选项。这是编译器的默认设置。


·-Otime:指示编译程序执行优化,以增大映像大小为代价缩短执行时间。如果执行时间比代码大小更重要,则使用该选项。例如,它编译:


while(expression)body;


为:


if(expression){


dobody;


while(expression);


}


如果既不指定-Otime也不指定-Ospace,则编译器默认使用-Ospace。可使用-Otime编译代码中对时间要求严格的部分,使用-Ospace编译其余部分。但不能在同一编译程序调用中同时指定-Otime和-Ospace。


14.1.4AAPCS选项


ARM结构过程调用标准AAPCS(ProcedureCallStandardfortheARMArchitecture)是ARM体系结构二进制接口ABI(ApplicationBinaryInterfacefortheARMArchitecture【BSABI】)标准的一部分。使用该标准可以很方便的执行C和汇编语言的相互调用。


编译程序时,使用--apcs选项可以指定所使用得AAPCS标准的版本。如果没有指定--apcs或--cpu选项,则编译器使用下面默认编译选项。


--apcs/noswst/nointer/noropi/norwpi--cpuARM7TDMI--fpusoftvfp


有关AAPCS的详细信息,请参加ARM相关文档。


14.1.5编译选项对代码生成影响示例


本节举例说明编译器的优化选项如何影响代码生成。


1.使用-O0选项


下面的例子显示了即使使用-O0编译选项对代码进行编译时,有些冗余代码还是会被编译器自动清除。


intf(int*p)


{


return(*p==*p);


}


使用armcc-c-O0对源程序进行编译,生成的汇编代码如下所示。


f


MOVr1,r0


MOVr0,#1


MOVpc,lr


通过上面的例子可以看到,编译出的最终代码中没有加载(Load)指针P的值,变量*p被编译器优化掉了。如果不想让编译器对变量*p做优化,可以使用“volatile”对变量进行声明。下面的例子,显示了将变量声明为“volatile”类型后,使用armcc编译(-O2的优化级别)后的结果。


f


LDRr1,[r0]


LDRr0,[r0]


CMPr1,r0


MOVNEr0,#0


MOVEQr0,#1


MOVpc,lr


另外,编译的代码中的“MOVr1,r0”并没有实际意义,只是为了方便调试程序时设置断点使用。


推荐阅读

史海拾趣

浙江凡华(FANHAR)公司的发展小趣事

对于计数型10键键盘编码译码显示电路,网友可能会有多个方面的问题,以下是一些常见问题及其回答:

一、设计基础与原理

问题1:计数型10键键盘编码译码显示电路的基本组成是什么?

回答:计数型10键键盘编码译码显示电路主要由三部分组成:键盘编码电路、译码电路和显示电路。键盘编码电路负责将按键的输入转换为对应的编码信号;译码电路则将该编码信号还原为可识别的信息或数据;最后,显示电路将译码后的信息以可视化的方式呈现出来。

问题2:编码和译码在数字电路中的作用是什么?

回答:编码是将信息或数据转换为二进制代码的过程,以便在数字系统中进行监测、控制、传输等操作。而译码则是编码的逆过程,即将二进制代码还原为原始的信息或数据,以便进行显示或进一步处理。在计数型10键键盘编码译码显示电路中,编码和译码是实现按键输入到显示输出的关键步骤。

二、技术实现细节

问题3:如何实现10键键盘的编码?

回答:实现10键键盘的编码通常可以采用优先编码器。优先编码器能够识别多个输入信号中的最高优先级信号,并将其转换为对应的编码输出。在10键键盘中,可以将10个按键的输入信号接入优先编码器的输入端,通过编码器的内部逻辑处理,得到按键对应的编码输出。

问题4:译码器如何选择以满足显示需求?

回答:译码器的选择应根据显示需求来确定。对于计数型10键键盘编码译码显示电路,如果显示的是十进制数字,则应选择能够处理十进制数的译码器,如74LS48等。此外,还需要考虑译码器的输入位数、输出类型(如共阳极或共阴极)以及驱动能力等因素,以确保译码器能够满足显示电路的要求。

问题5:显示电路如何设计以兼容不同显示器?

回答:显示电路的设计应兼顾译码器、驱动器和显示器三部分。首先,根据译码器的输出选择合适的驱动器来驱动显示器。驱动器的选择应考虑显示器的类型(如七段数码管、LED点阵等)、工作电压和电流等因素。其次,根据显示器的特性设计显示电路,包括确定显示方式(如静态显示或动态显示)、设置显示亮度等。最后,通过连接译码器、驱动器和显示器,实现按键输入到显示输出的完整电路。

三、常见问题与解决方案

问题6:如何解决按键冲突问题?

回答:按键冲突是指多个按键同时按下时,电路无法正确识别所有按键的状态。在计数型10键键盘编码译码显示电路中,可以通过采用优先编码器来避免按键冲突问题。因为优先编码器能够识别最高优先级的按键信号,并忽略其他低优先级的按键信号。此外,还可以通过软件算法来进一步处理按键冲突问题,如设置按键去抖动时间、检测按键按下和释放的时间差等。

问题7:如何提高电路的抗干扰能力?

回答:提高电路的抗干扰能力可以从多个方面入手。首先,选择具有良好抗干扰性能的元器件和电路布局方式;其次,在电路设计中加入滤波、去耦等电路来抑制干扰信号;最后,通过软件算法来识别和排除干扰信号的影响。此外,还可以采用屏蔽、接地等外部措施来进一步提高电路的抗干扰能力。

以上是对计数型10键键盘编码译码显示电路中网友可能提出的问题及其回答的总结。在实际应用中,还需要根据具体需求和条件进行灵活调整和优化。

Concurrent Logic公司的发展小趣事

随着公司规模的扩大,Concurrent Logic开始寻求国际合作。他们与日本、韩国和欧洲的几家公司签订了技术合作协议,共同开发新一代的并行处理解决方案。这些合作为公司带来了更广阔的市场和更多的资源,推动了技术的进一步创新。

AKM [Asahi Kasei Microsystems]公司的发展小趣事

在取得初步成功后,Concurrent Logic开始扩展其产品线。他们不仅开发了多款针对不同应用场景的并行处理芯片,还进军了与并行计算紧密相关的其他硬件领域,如高性能的服务器和存储设备。这些新产品的研发和上市,进一步增强了公司在市场上的竞争力。

CONEC公司的发展小趣事

1978年,CONEC在利普施塔特创立,标志着公司电子业务的起点。创立初期,公司可能面临着资金、技术和市场等多方面的挑战。然而,凭借着对电子行业的深刻理解和坚定的创业决心,CONEC逐渐在市场中站稳脚跟。1980年,DIN EN 60603系列产品的成功上线生产,为公司赢得了初步的声誉和市场认可,为后续的发展奠定了坚实基础。

上海超致公司的发展小趣事

作为一家有社会责任感的企业,上海超致始终关注环境保护和可持续发展。公司积极推广绿色生产技术和资源循环利用方案,减少生产过程中的能源消耗和废弃物排放。同时,上海超致还积极参与社会公益活动,为社区和环境贡献自己的力量。这种对社会责任的关注和担当使得上海超致在电子行业中树立了良好的形象。

Connective Peripherals Pte Ltd公司的发展小趣事

随着技术的不断积累和创新,上海超致在功率半导体领域取得了重大突破。公司成功推出了全球首款量产SJ-IGBT产品,这一产品具有电流密度大、综合器件性能优的特点,在硅基成本下实现了性能的显著提升。此外,上海超致还不断拓宽产品线,产品广泛应用于太阳能微逆变器、车载OBC、充电桩、UPS电源等多个领域。这些产品的推出不仅满足了市场的需求,也进一步提升了公司的市场竞争力。

问答坊 | AI 解惑

检测绝缘栅极双极型晶体管(IGBT)好坏的简易方法

1、判断极性首先将万用表拨在R×1KΩ挡,用万用表测量时,若某一极与其它两极阻值为无穷大,调换表笔后该极与其它两极的阻值仍为无穷大,则判断此极为栅极(G)。其余两极再用万用表测量,若测得阻值为无穷大,调换表笔后测量阻值较小。在测量阻值 ...…

查看全部问答>

很奇怪的问题 wince 串口测试应用程序 writefile(...)函数没有执行完就失败了,然后程序死掉了。

串口测试的writefile(...)函数没有执行完就失败了,没有任何返回结果。writefile的下一个语句做断点,没有执行到。 if(hComm!=INVALID_HANDLE_VALUE&&dwCharToWrite!=0)         {           &nbs ...…

查看全部问答>

终于研发成功

终于研发成功,cpu是s3c2410,64M   SDRAM,网口为cs8900 flash(k9f1208 64m)   实现了只用nand flash 就可以启动引导vxworks. 公司送bsp及全套开发文档 ,另可配公司的开发板 有意着QQ联系641328010 请注明 arm…

查看全部问答>

STC12LE5206AD 程序将引脚置为0 却检测到为高

有谁能够帮忙解决下啊? 本人qq:853887107…

查看全部问答>

RT_THREAD中的异常与中断

  异常是导致处理器脱离正常运行转向执行特殊代码的任何事件,如果系统不及时处理,系统轻则出错,重着导致系统毁灭性的瘫痪。所以正确地处理异常避免错误的发生是提高软件的鲁棒性重要的一方面,对于嵌入式系统更加如此。 异常可以分成两类 ...…

查看全部问答>

DIY导航避障车规整贴

DIY导航避障车小组今日下午展开第一次例会,在本次例会中大家集中讨论了无线的选择,避障的选择等等部分,并对小车进行了前景规划,以谷歌的自动驾驶车为终极目标,大家积极发言例会持续了一个半小时,并表示未来会采用各种新技术。下次再来把细节 ...…

查看全部问答>

11.06【每周讨论】软文——春风化雨、润物无声

您知道“软文”的含义吗?什么,不知道。赶紧百度一下吧,别被OUT了 [ 本帖最后由 longxtianya 于 2011-11-6 20:19 编辑 ]…

查看全部问答>

分享一些收集的msp430方面的书籍

最近接触了一下msp430的单片机从网上搜集了一些书籍希望对大家有帮助。…

查看全部问答>

泰克2012年度春季创新论坛北京站见闻

    4月24日阴雨天气,阿牛哥上午9点去北京朝阳区五洲皇冠大酒店参加泰克2012年度春季创新论坛。热情的工程师们朋友已经在会场里聆听泰克的测试测量行业趋势观点,泰克领先测试测量方案,还有一些工程师朋友在展厅参观泰克最新 ...…

查看全部问答>

全球智能机Q2出货1.5亿部 中兴进前五

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 …

查看全部问答>