ARM编程技巧

合集下载

arm gcc敲代码编译

arm gcc敲代码编译

arm gcc敲代码编译GCC(GNU Compiler Collection)是一套由GNU项目开发的编程语言编译器,它支持多种编程语言,如C、C++、Objective-C、Fortran、Java等。

GCC是自由软件,也是GNU操作系统的一部分。

在使用GCC编译器时,我们可以使用命令行来进行编译和链接操作。

下面我们以C语言为例,介绍GCC的一些常用选项和相关操作。

1. 编译代码GCC的编译过程分为四个阶段:预处理、编译、汇编和链接。

我们可以使用以下命令将C源文件(source.c)编译为可执行文件(output):```gcc -o output source.c```其中,-o选项用于指定输出文件的名称。

如果没有指定-o选项,则默认输出文件名为a.out。

2. 指定编译器版本如果我们在系统中安装了多个版本的GCC,可以使用以下命令来指定使用的编译器版本:```gcc-<version> -o output source.c```其中,<version>表示所需的版本号。

例如,如果要使用GCC 9.3.0进行编译,可以使用命令gcc-9.3.0。

3. 调试选项在进行C代码调试时,我们可以使用GCC的一些调试选项来生成符号表并打印调试信息。

以下是一些常用的选项:- -g:生成调试信息。

- -O0:关闭优化。

- -O1:开启轻微优化。

- -O2:开启中等级别优化。

- -O3:开启最高级别优化。

例如,我们可以使用以下命令来生成带调试信息的可执行文件:```gcc -g -o output source.c```4. 优化选项GCC提供了多个优化选项,以便我们对代码进行优化。

以下是一些常用的优化选项:- -O0:关闭优化。

- -O1:开启轻微优化。

- -O2:开启中等级别优化。

- -O3:开启最高级别优化。

例如,我们可以使用以下命令进行最高级别优化的编译:```gcc -O3 -o output source.c```5. 静态链接如果我们想将所有的库都打包到可执行文件中,可以使用以下命令进行静态链接:```gcc -static -o output source.c```其中,-static选项用于指定静态链接。

基于ARM的高效C语言编程.

基于ARM的高效C语言编程.

基于ARM的高效C语言编程引言ARM处理器以其高性能、低功耗、低成本等优势被广泛应用于各种成功的32位嵌入式系统中。

提高执行速度和减小代码尺寸是嵌入式软件设计的关键需求。

尽管大多数的ARM编译器和调试器都带有性能优化工具,但是为了保证其正确性,编译器必须是稳妥和安全的,而且它还受到处理器自身结构的限制。

因此,编程人员必须在理解编译器工作特点的基础上来实现代码优化。

代码的优化方法较多,本文针对函数优化方法进行阐述。

1 函数局部变量的数据类型局部变量包括函数内局部变量、函数参数、函数返回值。

由于ARM数据操作都是32位,即使数据本身只需要8位或16位,对于这三类局部变量也应尽可能使用32位的数据类型int或lONg,以提高代码执行效率。

下面以简单求和函数为例进行分析。

函数add1计算包含10个字的数组array的累加和,add2与add1功能相同,只是将函数add1的参数array类型改为16位的short,函数内局部变量i 类型改为8位的char,sum改为16位的short。

add1、add2的C源代码如下:int add1(int *array){unsigned int i;int sum=0;for(i=0;i<10;i++)sum=sum+array[i];return sum;}short add2(short *array){char i;short sum=0;for(i=0;i<10;i++)sum= sum+array[i];return sum;}add1经编译产生的汇编代码:add1mov r2,r0mov r0,#0mov r1,#0add1_loopldr r3,[r2,r1,lsl #2]add r1,r1,#1cmp r1,#0x0aadd r0,r3,r0bcc add1_loopmov pc,r14add2经编译产生的汇编代码:add2mov r2,r0mov r0,#0mov r1,#0add2_loop。

嵌入式编程(二):ARM单片机如何将函数定义到指定程序地址

嵌入式编程(二):ARM单片机如何将函数定义到指定程序地址

嵌⼊式编程(⼆):ARM单⽚机如何将函数定义到指定程序地址在单⽚机编程使⽤中,会涉及到将某些函数定义到指定的code区。

此时需要对⼯程⽂件进⾏配置修改才可完成。

本期针对ARM平台单⽚机做出说明介绍1.测试⽬标将函数Communication_Test定义到Code区的指定地址0x1000位置2.测试环境LKT4304加密芯⽚算法⼯程、KEIL-ARM编译软件、3.实现步骤3.1 使⽤KEIL软件导⼊LKT4304算法⼯程(KEIL软件基本操作不再敷述,如不清楚请⾃⾏百度)3.2 在App_Main.c⽂件中声明测试函数Communication_Test:extern void Communication_Test(u8 *in,u8 *out,u8 len);3.3 在App_fun.c⽂件中实现测试函数Communication_Test:void Communication_Test(u8 *in,u8 *out,u8 len);{u8 i;for(i=0;i < len;i++)out[i]= in[i]+1;}3.4 在App_Main.c⽂件中调⽤测试函数Communication_Test,此处省略3.5 编译算法⼯程后,在\LKT4304_AppDemo\Out\Lst\路径下找到 LKT4304_AppDemo.map,打开该⽂件。

3.6 寻找到Communication_Test编译后存储的地址。

本例中,编译后的默认地址如 图1所⽰。

图1. 默认编译链接地址3.7 回到算法⼯程,选择Project->Options for Target ...->Linker,点击Edit按钮调出sc⽂件,如图2所⽰图2. 打开sc⽂件3.8 在ARM_App.sc⽂件中,Code区起始地址是0x30000,如下图所⽰:图3.sc⽂件中定义的Code区将函数Communication_Test定义到Code区的指定地址0x1000位置,需要在 App_fun.c⽂件中增加 void Communication_Test(u8 *in,u8 *out,u8 len) __attribute__((section(".ARM.__at_0x00031000"))); 这样⼀句代码。

arm 汇编 指令

arm 汇编 指令

arm 汇编指令ARM汇编指令是一种用于编写ARM处理器程序的语言。

ARM处理器广泛应用于嵌入式系统和移动设备等领域。

ARM汇编指令与x86汇编指令有所不同,它基于RISC(精简指令集计算机)架构。

下面是一些基本的ARM汇编指令:1. 数据传输指令:用于在寄存器之间传输数据。

例如:- mov:将数据从一个寄存器传输到另一个寄存器。

- ldr:将数据从内存传输到寄存器。

2. 算术指令:用于执行加法、减法、乘法和除法等操作。

例如:- add:加法操作。

- sub:减法操作。

- mull:乘法操作。

- div:除法操作。

3. 逻辑指令:用于执行逻辑操作,如与、或、非等。

例如:- and:与操作。

- or:或操作。

- xor:异或操作。

4. 移位指令:用于对数据进行左移、右移或无符号右移。

例如:- lsr:无符号右移。

- asr:带符号右移。

- ror:循环右移。

5. 比较指令:用于比较两个寄存器的值。

例如:- cmp:比较两个寄存器的值,若相等则返回0,否则返回1。

6. 跳转指令:用于改变程序的执行流程。

例如:- b:条件跳转。

- bl:无条件跳转。

- bx:带状态跳转。

7. 循环指令:用于实现循环操作。

例如:- loop:内部循环。

- ldp:外部循环。

8. 调用指令:用于实现函数调用。

例如:- blx:带状态调用。

- bx:不带状态调用。

9. 系统调用指令:用于实现与操作系统交互的功能。

例如:- swi:执行系统调用。

10. 存储器访问指令:用于访问内存数据。

例如:- str:将数据存储到内存。

- ldr:从内存中加载数据。

以上仅为ARM汇编指令的一部分,实际上,ARM汇编指令还有很多其他功能。

为了更好地理解和使用ARM汇编指令,可以参考相关的教程和手册,并进行实际操作。

有这10个关键点,在ARM下高效C编程没问题!

有这10个关键点,在ARM下高效C编程没问题!

有这10个关键点,在ARM下高效C编程没问题!
通过一定的办法来编写C程序,可以协助C编译器生成执行速度更快的代码。

下面就是一些与性能相关的关键点:
1.对局部变量、函数参数和返回值要用法signed和unsigned int类型。

这样可以避开类型转换,而且可高效地用法ARM的32位数据操作命令。

2.最高效的循环体形式是减计数到零(counts down to zero)的
do-while循环。

3.绽开重要的循环来削减循环的开销。

4.不要依靠编译器来优化掉重复的存储器拜访。

指针别号会阻挡编译器
的这种优化。

5.尽可能把函数参数的个数限制在4个以内。

假如函数参数都存放在寄
存器内,那么函数调用就会快得多。

6.按元素尺寸从小到大罗列的办法来支配结构体,特殊是在thumb模式
下编译。

7.不要用法位域,可以用掩码和规律操作来替代。

8.避开除法,可以用倒数的乘法来替代。

9.避开边界不对齐的数据。

假如数据有可能边界不对齐,那么就要用法char *指针类型来拜访。

10.在C编译器中用法内嵌汇编可以利用到C编译器原来不支持的命令或优化。

一、数据类型用法上的优化
1.局部变量
一个char类型的数据比int类型的数据占用更小的寄存器空偶尔者更小的ARM堆栈空间。

这两种设想对于ARM来说,都是错误的。

全部的ARM寄存器都是32位的,全部的堆栈入口起码是32位的。

当我们执行i++,要利用当i=255后,i++=0这个条件时,可以把它定义为char 类型。

2.函数参数
第1页共7页。

arm指令and用法

arm指令and用法

arm指令and用法ARM指令和用法ARM指令是一种用于处理器的机器指令集,它是一种低级的指令集,用于控制和操作计算机的硬件。

ARM指令在嵌入式系统和移动设备中得到广泛应用。

本文将介绍ARM指令的基本结构和一些常用的指令用法。

一、ARM指令的基本结构ARM指令的基本结构由操作码和操作数组成。

操作码用于指定操作的类型,而操作数则包含了执行操作所需的数据。

ARM指令的操作码和操作数的位数可以根据需要进行变化,其中包括了16位的Thumb 指令和32位的ARM指令。

下面将详细介绍ARM指令的用法。

1. 数据传输指令数据传输指令用于在寄存器之间传输数据。

其中,LDR(Load Register)指令用于将内存数据装载到寄存器中,而STR(Store Register)指令则将寄存器中的数据存储到内存中。

数据传输指令的格式如下:```LDR Rd, [Rn, #offset]STR Rd, [Rn, #offset]```其中,Rd表示目标寄存器,Rn表示基址寄存器,offset表示偏移量。

2. 算术运算指令算术运算指令用于执行各种基本的算术运算,包括加法、减法、乘法和除法等。

这些指令用于对寄存器中的数据进行运算,并将结果存储到指定的寄存器中。

以下是一些常用的ARM算术运算指令:```ADD Rd, Rn, RmSUB Rd, Rn, RmMUL Rd, Rn, Rm```其中,Rd表示目标寄存器,Rn和Rm表示源寄存器。

3. 分支指令分支指令用于实现程序的跳转和循环控制。

ARM架构的分支指令非常灵活,可以根据条件条件进行分支,例如等于零、不等于零和溢出等。

以下是一些常用的ARM分支指令:```B labelBEQ labelBLT label```其中,B指令用于无条件跳转,BEQ指令用于等于零时跳转,BLT指令用于小于零时跳转。

二、ARM指令的应用领域ARM指令被广泛应用于各种领域,特别是嵌入式系统和移动设备。

ARM汇编快速入门教程

ARM汇编快速入门教程

ARM汇编快速入门教程本文主要分享如何快速上手(ARM)(汇编)开发的经验、汇编开发中常见的Bug以及Debug方法、用的Convolu(ti)on Dephtwise 算子的汇编实现相对于(C++)版本的加速效果三方面内容。

01前言(神经网络)模型能够在移动端实现快速推理离不开高性能算子,直接使用ARM汇编指令来进行算子开发无疑会大大提高算子的运算性能。

初次接触汇编代码可能会觉得其晦涩难懂然后望而却步,但ARM 汇编开发一旦入门就会觉得语言优美简洁,如果再切换到ARM INTRIS (IC)指令开发反而觉得没有直接写汇编码来的方便。

我会在第一节分享纯小白如何快速上手ARM汇编开发的经验,第二节会列举在汇编开发中常见的Bug以及Debug方法,第三节会展示常用的Convolution Dephtwise算子的汇编实现相对于C++版本的加速效果。

如果你已经能很熟练地使用ARM汇编指令进行开发了,可以跳过第一节。

02从简单函数上手学习汇编开发重要的一点是通过学习现有函数的汇编代码来实现自己的需求我写的第一个汇编算子是MaxPooling算子,算子本身的计算过程非常简单。

但当我开始实现MaxPooling的汇编代码时,我不知道第一行代码怎么写,不知道开头和结尾怎么写,不知道中间的计算逻辑怎么写。

当时我就在MNN库的source文件夹下面找到了一份逻辑简单的、自己非常熟悉的Relu算子当做参照来实现MaxPooling. 之所以我(推荐)用一个逻辑简单的、自己非常熟悉的算子当做学习汇编的模版,是因为当算子的计算逻辑简单时,我们才能把注意力放在汇编函数的声明、传参、读取数据、存储结果、返回等等这些大的流程上面,至于内部的函数实现(如何计算一行数据的最大值,如何去计算一个(寄存器)中所有数据的累加和等等)可以暂时不去关注。

学习一个新的东西时,我们找的例子模版不能过于复杂,因为这会导致我们将注意力放在例子本身的实现细节中,而忽略了如何去入门,这样会增加我们的学习成本。

ARM汇编语言编程详解

ARM汇编语言编程详解

ARM汇编语言编程详解硅谷芯微嵌入式学院技术贡献网址:4.1 汇编语言使用汇编语言编写程序,它的特点是程序执行速度快,程序代码生成量少,但汇编语言是一种不易学习的编程语言,并且可读性较差,这种语言属于低级语言。

每一种汇编语言对应每一款芯片,使用这种语言需要对硬件有深刻的了解。

在通常情况下,可以使用汇编语言编写驱动程序、需要严格计算执行时间的程序以及需要加速执行的程序。

先介绍一个例子来说明ARM汇编程序的格式。

例1 计算20+8,结果放入R0寄存器。

AREA Buf, DATA, READWRITE ;声明数据段Buf Count DCB 20 ;定义一个字节单元Count AREA Example, CODE, READONLY ;声明代码段ExampleENTRY ;标识程序入口CODE32 ;声明32位ARM指令STARTLDRB R0, Count ;R0 = Count =20MOV R1, #8 ;R1 = 8ADD R0, R0, R1 ;R0 = R0 + R1B STARTEND例1中定义了两个段:数据段Buf和代码段Example 。

数据段中定义了字节单元Count,其中Count用来保存一个被加数;代码段中包含了所有源程序代码,程序中首先读取Count字节单元的内容,然后与立即数8相加,计算结果保存到R0中。

由例1可见,ARM汇编语言的源程序是分段的,由若干个段组成一个源程序。

源程序的一般格式为:AREA name1, attr ;声明特定的段标号语句1 ;语句...语句nAREA name2, attr标号语句n+1...语句n+mEND ;结束符每一个段都有一个名字,并且段名是唯一的。

每个段以符号AREA作为段的开始,以碰到下一个符号AREA 作为该段的结束。

段都有自己的属性,如是代码段(CODE)还是数据段(DATA),是只读(READONLY )还是可读写(READWRITE)?这些属性可以在attr栏中设定。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

大多数arm指令集都可实现 寄存器操作数可支持任意的c/c++的表达式 内嵌汇编代码可由编译器的优化器来传递
TM
103v04 C/C++ Compiler Hints & Tips
12
12
ATPCS(arm/thumb程序调用规范)
Register r0 r1 r2 r3
作为函数传递的参数值

在高级优化选项中,ADS 1.2 编译器默认自动内嵌

-Oautoinline (default -O2) -Ono_autoline (default for -O0,-O1)

哪个函数是否被内嵌取决于:


他们是否被 __inline标示 优化的级别 -Otime / -Ospace 函数被调用的次数
编译器使用一套规则的来设置寄存器的用法 ARM-Thumb Procedure Call Standard or ATPCS (or APCS) CPSR 标志位可被函数调用所破坏 任何和编译过的代码交互工作的汇编码在接口层必 须满足ATPCS的规范
寄存器变量 必须保护
r4 r5 r6 r7 r8 r9/sb r10/sl r11 r12 r13/sp r14/lr r15/pc
TM
4
4
使用 “volatile”
int f(int *p) { return (*p = = *p); }
f armcc -c MOV r0,#1 MOV pc,lr
f int f(volatile int *p) { return (*p = = *p); }
armcc -c
LDR LDR CMP MOVNE MOVEQ MOV
func2 0x000000 : STR 0x000004 : ADD 0x000008 : ADD lr, [sp,#-4]! r0,r0,r1 r0,r0,r2
r1,[r0] r0,[r0] r1,r0 r0,#0 r0,#1 pc,lr

这个代码用的编译级别是:-o2
5
5
103v04 C/C++ Compiler Hints & Tips
TM
冗余代码的清除

下面是一个冗余代码清除的例子,他只用了-o1的优化选项:
int dummy() { int a=10, b=20; int c; c=a+b; return 0; }
0x00001c : MOV
0x000020 : MOV 0x000024 : B
r1,#2
r0,#1 func1
103v04 C/C++ Compiler Hints & Tips
TM
18
18
Parameter Passing (6 parameters)

Parameter Passing (6 parameters)
extern void mystrcopy(char *d, const char *s); int main(void) { const char *src = “Source”; char dest[10]; ... mystrcopy(dest, src); ...
CALL
}
END
这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用 PUSH/POP来保护
LDR ADD ADD MOV r0,[r0,#0] r1,r1,r1,LSL #1 r0,r0,r1 pc,lr
armcc –cpu arm7tdmi
103v04 C/C++ Compiler Hints & Tips
armcc –cpu arm9tdmi
TM
7
7
Tail-call Optimization 嵌套优化
lr,[sp,#-4]! g r1,r0 r0,r1 pc,[sp],#4 g
MOV MOV
r0, #10 pc, lr
BL :
f
MOV MOV
r0, #10 pc, lr
103v04 C/C++ Compiler Hints & Tips
TM
8
8
内嵌函数(inline)

内嵌可通过删除子函数调用的开销来提高性能 这个 inline 关键字显示哪个函数将被内嵌
-O0---DEBUG

关闭大多数优化. 最好的调试信息,最少的优化
-O1---DEBUGREL

多数优化选项许可 给一个满意的调试,好的代码密度
完全的优化 有限的调试信息,最好的代码密度
-O2---RELEASE (default)


为代码大小或运行速度的优化,可选择: -Ospace (默认的)或 -Otime. 使用-g 选像可包含源码级调试信息
int f(int *p) { return (*p = = *p); }
f
armcc -c -O0
MOV r1, r0 MOV r0, #1 MOV pc, lr
注意:在这种情况下,可使用C的关键字volatile 强制使用这些变量
103v04 C/C++ Compiler Hints & Tips
103v04 C/C++ Compiler Hints & Tips
TM
3
3
自动优化

ADS 编译器在所有级别中执行一些简单的优化

i.e. -O0,
-O1, -O2

下面是一个例子:即使用-O0,多余的表达式也被清除了:

ATPCS标准中子程序结果返回规则

结果为32位整数,R0返回 结果为64位整数,R0,R1返回 位数更多时,用内存来传递 ……
int foo(int i) { i=bar(i); i=i-2; i=bar(i); i++; return i; }
__inline int bar(int a) { a=a+5; return a; } int foo(int i) { i=bar(i); i=i-2; i=bar(i); i++; return i; }
TM
103v04 C/C++ Compiler Hints & Tips
13
13
在C程序中调用汇编

在汇编程序中用export name来定义 在C程序中直接调用,用EXTERN声明 正常链接
AREA StringCopy, CODE, READONLY EXPORT mystrcopy mystrcopy LDRB r2, [r1], #1 STRB r2, [r0], #1 CMP r2, #0 BNE mystrcopy MOV pc, lr
armcc -c -O1
dummy MOV r0, #0 MOV pc, lr
103v04 C/C++ Compiler Hints & Tips
TM
6
6
指令编排

指令编排在高级优化选项中是有效的(-O1, -O2).

指令的重新编排是为了使要运行的代码更适合对应的核 为arm9和以后的处理器提高吞吐量(一般可达到4%),并防止互锁(interlock) 选择处理器可决定使用的运算法则,在默认情况下,使用针对ARM9的优化方案 (对ARM7的运行没有影响)
103v04 C/C++ Compiler Hints & Tips
TM
11
11
C和汇编的混合编程

C/C++ 和汇编能很容易的混合:

可实现在c中无法实现的处理器功能 使用新的或不支持的指令 产生更高效的代码

直接链接变量和程序


确定符合程序调用规范 输入/输出相关的符号

编译器也可包含内嵌汇编
ARM 编程技巧
T
H
E
A
R
C
H
I
T
E
C
T
U
R
E
F
O
R
T TM
H
E
D
I
G
I
T
A
L
W
O
R1 L
D
Agenda

ARM 编译器优化
C/C++和汇编混合模式编程
使用ARM编译器编码 局部和全局数据讨论
103v04 C/C++ Compiler Hints & Tips
TM
2译器优化级别是可选择的
r0,r0,r1 r0,r0,r2 r0,r0,r3 pc,lr
int func1(int a, int b,
int c, int d) { return a+b+c+d;
}
caller1 0x000014 : MOV 0x000018 : MOV r3,#4 r2,#3
int caller1(void) { return func1(1,2,3,4); }

__inline void Clear_Q_flag (void) { int temp; __asm { MRS temp, CPSR BIC temp, temp, #Q_Flag MSR CPSR_f, temp } } __inline int mult16(short a, short b, int c) { int temp; __asm { SMLABB temp,a,b,c } return temp; }
相关文档
最新文档