您好,欢迎访问三七文档
1TMTHEARCHITECTUREFORTHEDIGITALWORLDARM编程技巧2TM2103v04C/C++CompilerHints&TipsAgendaARM编译器优化C/C++和汇编混合模式编程使用ARM编译器编码局部和全局数据讨论3TM3103v04C/C++CompilerHints&Tips优化级别使用的编译器优化级别是可选择的-O0---DEBUG关闭大多数优化.最好的调试信息,最少的优化-O1---DEBUGREL多数优化选项许可给一个满意的调试,好的代码密度-O2---RELEASE(default)完全的优化有限的调试信息,最好的代码密度为代码大小或运行速度的优化,可选择:-Ospace(默认的)或-Otime.使用-g选像可包含源码级调试信息4TM4103v04C/C++CompilerHints&TipsADS编译器在所有级别中执行一些简单的优化i.e.-O0,-O1,-O2下面是一个例子:即使用-O0,多余的表达式也被清除了:ATPCS标准中子程序结果返回规则结果为32位整数,R0返回结果为64位整数,R0,R1返回位数更多时,用内存来传递……自动优化intf(int*p){return(*p==*p);}armcc-c-O0fMOVr1,r0MOVr0,#1MOVpc,lr注意:在这种情况下,可使用C的关键字volatile强制使用这些变量5TM5103v04C/C++CompilerHints&Tips使用“volatile”intf(volatileint*p){return(*p==*p);}armcc-cfLDRr1,[r0]LDRr0,[r0]CMPr1,r0MOVNEr0,#0MOVEQr0,#1MOVpc,lrintf(int*p){return(*p==*p);}fMOVr0,#1MOVpc,lrarmcc-c这个代码用的编译级别是:-o26TM6103v04C/C++CompilerHints&Tips下面是一个冗余代码清除的例子,他只用了-o1的优化选项:冗余代码的清除intdummy(){inta=10,b=20;intc;c=a+b;return0;}armcc-c-O1dummyMOVr0,#0MOVpc,lr7TM7103v04C/C++CompilerHints&Tips指令编排指令编排在高级优化选项中是有效的(-O1,-O2).指令的重新编排是为了使要运行的代码更适合对应的核为arm9和以后的处理器提高吞吐量(一般可达到4%),并防止互锁(interlock)选择处理器可决定使用的运算法则,在默认情况下,使用针对ARM9的优化方案(对ARM7的运行没有影响)例如:intf(int*p,intx){return*p+x*3;}没用指令编排(-O0)使用指令编排(-O1,-O2)ADDr1,r1,r1,LSL#1LDRr0,[r0,#0]LDRr0,[r0,#0]ADDr1,r1,r1,LSL#1ADDr0,r0,r1;interlockonARM9ADDr0,r0,r1MOVpc,lrMOVpc,lrarmcc–cpuarm7tdmiarmcc–cpuarm9tdmi8TM8103v04C/C++CompilerHints&TipsTail-callOptimization嵌套优化可避免在函数级里的不必要的返回在可能的情况下BL译码成B在高级优化里有效(-O1,-O2).intmain(){intx=f();:}intf(){inty=g();returny;}intg(){return10;}BgBLf:MOVr0,#10MOVpc,lrBLf:STRlr,[sp,#-4]!BLgMOVr1,r0MOVr0,r1LDRpc,[sp],#4MOVr0,#10MOVpc,lr嵌套优化9TM9103v04C/C++CompilerHints&Tips内嵌函数(inline)内嵌可通过删除子函数调用的开销来提高性能这个inline关键字显示哪个函数将被内嵌在高级优化选项中,ADS1.2编译器默认自动内嵌-Oautoinline(default-O2)-Ono_autoline(defaultfor-O0,-O1)哪个函数是否被内嵌取决于:他们是否被__inline标示优化的级别-Otime/-Ospace函数被调用的次数如果函数在别的模块中不被调用,一个好的建议是用static标识函数,否则,编译器将在内嵌译码里把该函数编译乘非内嵌的加代码的长度使调试信息更复杂Example...10TM10103v04C/C++CompilerHints&TipsInlineexampleintbar(inta){a=a+5;returna;}intfoo(inti){i=bar(i);i=i-2;i=bar(i);i++;returni;}barADDr0,r0,#5MOVpc,lrfooSTRlr,[sp,#-4]!BLbarSUBr0,r0,#2BLbarADDr0,r0,#1LDRpc,[sp],#4__inlineintbar(inta){a=a+5;returna;}intfoo(inti){i=bar(i);i=i-2;i=bar(i);i++;returni;}fooADDr0,r0,#5SUBr0,r0,#2ADDr0,r0,#5ADDr0,r0,#1MOVpc,lr内嵌例子11TM11103v04C/C++CompilerHints&TipsAgendaARM编译器的优化C/C++和汇编混合模式编程使用ARM编译器编码局部和全局数据讨论12TM12103v04C/C++CompilerHints&TipsC和汇编的混合编程C/C++和汇编能很容易的混合:可实现在c中无法实现的处理器功能使用新的或不支持的指令产生更高效的代码直接链接变量和程序确定符合程序调用规范输入/输出相关的符号编译器也可包含内嵌汇编大多数arm指令集都可实现寄存器操作数可支持任意的c/c++的表达式内嵌汇编代码可由编译器的优化器来传递13TM13103v04C/C++CompilerHints&TipsATPCS(arm/thumb程序调用规范)r8r9/sbr10/slr11r12r13/spr14/lrr15/pcr0r1r2r3r4r5r6r7寄存器变量必须保护作为函数传递的参数值Scratchregister(corruptible)StackPointerLinkRegisterProgramCounter编译器使用一套规则的来设置寄存器的用法ARM-ThumbProcedureCallStandardorATPCS(orAPCS)CPSR标志位可被函数调用所破坏任何和编译过的代码交互工作的汇编码在接口层必须满足ATPCS的规范Register-如果RWPI选项有效,作为栈的基地址-如果软件堆栈检查有效,作为栈的限制值-可作为临时的一个值栈一样来使用-子程序内部调用的可改写的寄存器-程序计数器14TM14103v04C/C++CompilerHints&Tips在C程序中调用汇编在汇编程序中用exportname来定义在C程序中直接调用,用EXTERN声明正常链接externvoidmystrcopy(char*d,constchar*s);intmain(void){constchar*src=“Source”;chardest[10];...mystrcopy(dest,src);...}AREAStringCopy,CODE,READONLYEXPORTmystrcopymystrcopyLDRBr2,[r1],#1STRBr2,[r0],#1CMPr2,#0BNEmystrcopyMOVpc,lrEND这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用PUSH/POP来保护CALL15TM15103v04C/C++CompilerHints&Tips内嵌汇编允许使用一些不能由编译器自动生成的指令:MSR/MRS新的指令协处理器指令通常在关联的内嵌函数中使用使用C变量代替寄存器不是一个真正的汇编文件通过优化器实现ADSFAQ入口“UsingtheInlineAssembler”#defineQ_Flag0x08000000//Bit27__inlinevoidClear_Q_flag(void){inttemp;__asm{MRStemp,CPSRBICtemp,temp,#Q_FlagMSRCPSR_f,temp}}__inlineintmult16(shorta,shortb,intc){inttemp;__asm{SMLABBtemp,a,b,c}returntemp;}16TM16103v04C/C++CompilerHints&TipsAgendaARM编译器的优化C/C++和汇编混合模式编程使用ARM编译器编码局部和全局数据讨论17TM17103v04C/C++CompilerHints&Tips参数传递开始四个字大小的参数直接使用寄存器的R0-R3来传递(快速且高效的)更多的信息可参看ATPCS如果需要更多的参数,将使用堆栈。(需要额外的指令和慢速的存储器操作)所以通常限制参数的个数,使它为4或更少。如果不可避免,把常用的参数前4个放在R0-R3中Example...18TM18103v04C/C++CompilerHints&TipsParameterPassing(4parameters)intfunc1(inta,intb,intc,intd){returna+b+c+d;}intcaller1(void){returnfunc1(1,2,3,4);}func10x000000:ADDr0,r0,r10x000004:ADDr0,r0,r20x000008:ADDr0,r0,r30x00000c:MOVpc,lrcaller10x000014:MOVr3,#40x000018:MOVr2,#30x00001c:MOVr1,#20x000020:MOVr0,#10x000024:Bfunc1ParameterPassing(4parameters)19TM19103v04C/C++CompilerHints&TipsParameterPassing(6parameters)ParameterPassing(6parameters)func20x000000:STRlr,[sp,#-4]!0x000004:ADDr0,r0,r10x000008:ADDr0,r0,r20x00000C:ADDr0,r0,r30x000010:LDMIBsp,{r12,r14}0x000014:ADDr0,r0,r120x000018:ADDr0,r0,r140x00001C:LDRpc,{sp},#4caller20x000020:STMFDsp!,{r2,r3,lr}0x000024:MOVr3,#60x000028:MOVr2,#50x00002C:STMIAsp,{r2,r3}0x000030:MOVr3,#40x000034:MOVr2,#30x000038:MOVr1,#20x00003C:MOVr0,#10x000040:BLfunc20x000044:LDMFDsp!,{r2,r3,pc}intfunc2(inta,intb,intc,int,d,inte,intf){returna+b+c+d+e+f;}intcaller2(void){returnfunc1(1,2,3,4,5,6);}Thiscodeiscompiledwith“-O2-Ono_autoinline”20TM20103v04C/C++CompilerHints&Tips循环终止在for(),while()do…while
本文标题:ARM编程技巧
链接地址:https://www.777doc.com/doc-23711 .html