ARM 编程技巧.

Slides:



Advertisements
Similar presentations
现代电子技术实验 ——综合实验之单片机部分
Advertisements

C语言程序设计 主讲教师 :张群燕 电话:
第一章 C语言概述 计算机公共教学部.
编译原理上机实习
微机原理与接口技术 第二章 ARM微处理器硬件结构
2017/3/22 如何用C 来完成SN8系列芯片的程序设计 2017/3/22.
大连理工大学软件学院 软件工程系 赖晓晨 计算机组成与结构 大连理工大学软件学院 软件工程系 赖晓晨
新世代計算機概論 第14章 程式語言.
ARM及Thumb指令集.
ARM 架构.
C语言程序设计 第十二章 位运算.
Introduction to the C Programming Language
第一章 C语言概述.
主讲教师:吴琼 微信群:C语言2016 QQ群: 密码scu2016 昵称:“真名+学号”
嵌入式系统讲义 第3章 ARM指令系统 周国运
指令集架構 計算機也跟人類一樣,需要提供一套完整的語言讓人們跟它充分溝通,以完成正確的計算工作。
Scope & Lifetime 前言 Local Scope Global Functions & Objects
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
第六章 运行时存储空间的组织和管理 术语 本章内容 讨论一个活动记录中的数据布局 程序执行过程中,所有活动记录的组织方式 过程的活动
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Object-Oriented Programming in C++ 第一章 C++的初步知识
第三章 C++中的C 面向对象程序设计(C++).
College of Computer Science & Technology
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
第4章 汇编语言程序设计 汇编语言源程序格式 汇编语言上机过程 汇编语言与C语言混合编程技术.
嵌入式体系结构与应用 第三章-ARM指令系统(ARMv4T).
Ch9 Communicating with Hardware
周国运 Keil C51应用 主 页:
ARM處理器 定址方式.
C++语言程序设计 第二章 C++简单程序设计.
第五章 C/C++及汇编语言的混合编程 5.1 ARM C/C++编译器 5.2 在C/C++程序中内嵌汇编指令
嵌入式系统教案 武汉创维特信息技术有限公司 2019/1/18.
(第2版).
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
(第2版).
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
合泰半导体股份有限公司 技术讲座 - Holtek V3 C Compiler介绍 主讲人:王幼端 2017/06/15.
Holtek C Compiler V3--advanced
ARM 架构.
ARM 架构.
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
ARM及Thumb指令集 (练习).
第3章 ARM微處理器的指令集.
第 二 章 数据类型、运算符与表达式.
ARM Developer Suite 介 绍.
ARM指令集 Author : Steve Furber Advisor: Mei-Ling Chiang Speaker: 徐翔宇
嵌入式系统教案 武汉创维特信息技术有限公司 2019/4/29.
Oop8 function函式.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
開放電腦計劃 報告人:陳鍾誠 2011 年 8 月 20 日 台灣開源人年會 COSCUP 2011 – 中研院
第5章 函 数.
C语言程序设计 李祥 QQ:
C++语言程序设计教程 第2章 数据类型与表达式 第2章 数据类型与表达式 制作人:杨进才 沈显君.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 类型、对象、运算符和表达式.
ARM简介及BootLoader介绍 黄大荣
#include <iostream.h>
第四章 函数 丘志杰 电子科技大学 计算机学院 软件学院.
第二章ADS1.2开发环境创建与简介.
第十二章 位运算.
单片机应用技术 (C语言版) 第4章 C51程序设计入门
第3章 目录 1.简介 2.ARM7TDMI 3.ARM7TDMI的模块和内部框图 4.体系结构直接支持的数据类型 5.处理器状态
Introduction to the C Programming Language
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
變數與資料型態  綠園.
嵌入式系统教案 武汉创维特信息技术有限公司 2019/10/1.
Presentation transcript:

ARM 编程技巧

Agenda ARM 编译器优化 C/C++和汇编混合模式编程 使用ARM编译器编码 局部和全局数据讨论

优化级别 使用的编译器优化级别是可选择的 -O0---DEBUG -O1---DEBUGREL 关闭大多数优化. 最好的调试信息,最少的优化 -O1---DEBUGREL 多数优化选项许可 给一个满意的调试,好的代码密度 -O2---RELEASE (default) 完全的优化 有限的调试信息,最好的代码密度 为代码大小或运行速度的优化,可选择: -Ospace (默认的)或 -Otime. 使用-g 选像可包含源码级调试信息

自动优化 ADS 编译器在所有级别中执行一些简单的优化 下面是一个例子:即使用-O0,多余的表达式也被清除了: i.e. -O0, -O1, -O2 下面是一个例子:即使用-O0,多余的表达式也被清除了: ATPCS标准中子程序结果返回规则 结果为32位整数,R0返回 结果为64位整数,R0,R1返回 位数更多时,用内存来传递 …… int f(int *p) { return (*p = = *p); } f MOV r1, r0 MOV r0, #1 MOV pc, lr armcc -c -O0 注意:在这种情况下,可使用C的关键字volatile 强制使用这些变量

使用 “volatile” 这个代码用的编译级别是:-o2 int f(int *p) { f return (*p = = *p); } f MOV r0,#1 MOV pc,lr armcc -c f LDR r1,[r0] LDR r0,[r0] CMP r1,r0 MOVNE r0,#0 MOVEQ r0,#1 MOV pc,lr int f(volatile int *p) { return (*p = = *p); } armcc -c 这个代码用的编译级别是:-o2

冗余代码的清除 下面是一个冗余代码清除的例子,他只用了-o1的优化选项: dummy MOV r0, #0 MOV pc, lr int dummy() { int a=10, b=20; int c; c=a+b; return 0; } dummy MOV r0, #0 MOV pc, lr armcc -c -O1

指令编排 指令编排在高级优化选项中是有效的(-O1, -O2). 例如: 没用指令编排 (-O0) 使用指令编排 (-O1,-O2) 指令的重新编排是为了使要运行的代码更适合对应的核 为arm9和以后的处理器提高吞吐量(一般可达到4%),并防止互锁(interlock) 选择处理器可决定使用的运算法则,在默认情况下,使用针对ARM9的优化方案 (对ARM7的运行没有影响) 例如: int f(int *p, int x) { return *p + x * 3; } 没用指令编排 (-O0) 使用指令编排 (-O1,-O2) ADD r1,r1,r1,LSL #1 LDR r0,[r0,#0] LDR r0,[r0,#0] ADD r1,r1,r1,LSL #1 ADD r0,r0,r1 ; interlock on ARM9 ADD r0,r0,r1 MOV pc,lr MOV pc,lr armcc –cpu arm7tdmi armcc –cpu arm9tdmi

Tail-call Optimization 嵌套优化 Tail-call Optimization 嵌套优化可避免在函数级里的不必要的返回 在可能的情况下BL 译码成B 在高级优化里有效(-O1, -O2). int main() { int x = f(); : } int f() { int y = g(); return y; } int g() { return 10; } BL f : STR lr,[sp,#-4]! BL g MOV r1,r0 MOV r0,r1 LDR pc,[sp],#4 MOV r0, #10 MOV pc, lr B g BL f : MOV r0, #10 MOV pc, lr

内嵌函数(inline) 内嵌可通过删除子函数调用的开销来提高性能 这个 inline 关键字显示哪个函数将被内嵌 在高级优化选项中,ADS 1.2 编译器默认自动内嵌 -Oautoinline (default -O2) -Ono_autoline (default for -O0,-O1) 哪个函数是否被内嵌取决于: 他们是否被 __inline标示 优化的级别 -Otime / -Ospace 函数被调用的次数 如果函数在别的模块中不被调用,一个好的建议是用static标识函数,否则,编译器将在内嵌译码里把该函数编译乘非内嵌的 加代码的长度 使调试信息更复杂 Example...

内嵌例子 Inline example int bar(int a) { a=a+5; return a; } int foo(int i) i=bar(i); i=i-2; i++; return i; bar ADD r0,r0,#5 MOV pc,lr foo STR lr,[sp,#-4]! BL bar SUB r0,r0,#2 ADD r0,r0,#1 LDR pc,[sp],#4 __inline int bar(int a) { a=a+5; return a; } int foo(int i) i=bar(i); i=i-2; i++; return i; foo ADD r0,r0,#5 SUB r0,r0,#2 ADD r0,r0,#1 MOV pc,lr

Agenda ARM编译器的优化 C/C++和汇编混合模式编程 使用ARM编译器编码 局部和全局数据讨论

C和汇编的混合编程 C/C++ 和汇编能很容易的混合: 直接链接变量和程序 编译器也可包含内嵌汇编 可实现在c中无法实现的处理器功能 使用新的或不支持的指令 产生更高效的代码 直接链接变量和程序 确定符合程序调用规范 输入/输出相关的符号 编译器也可包含内嵌汇编 大多数arm指令集都可实现 寄存器操作数可支持任意的c/c++的表达式 内嵌汇编代码可由编译器的优化器来传递

ATPCS(arm/thumb程序调用规范) Register 编译器使用一套规则的来设置寄存器的用法 ARM-Thumb Procedure Call Standard or ATPCS (or APCS) CPSR 标志位可被函数调用所破坏 任何和编译过的代码交互工作的汇编码在接口层必 须满足ATPCS的规范 r0 r1 作为函数传递的参数值 r2 r3 r4 r5 r6 寄存器变量 必须保护 r7 r8 r9/sb - 如果 RWPI选项有效,作为栈的基地址 r10/sl - 如果软件堆栈检查有效,作为栈的限制值 r11 Scratch register (corruptible) - 子程序内部调用的可改写的寄存器 r12 Stack Pointer Link Register Program Counter r13/sp r14/lr - 可作为临时的一个值栈一样来使用 r15/pc - 程序计数器

在C程序中调用汇编 这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用PUSH/POP来保护 在汇编程序中用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 END extern void mystrcopy(char *d, const char *s); int main(void) { const char *src = “Source”; char dest[10]; ... mystrcopy(dest, src); ... } CALL 这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用PUSH/POP来保护

内嵌汇编 允许使用一些不能由编译器自动生成的指令: 通常在关联的内嵌函数中使用 使用C变量代替寄存器 #define Q_Flag 0x08000000 // Bit 27 __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; { SMLABB temp,a,b,c return temp; 允许使用一些不能由编译器自动生成的指令: MSR / MRS 新的指令 协处理器指令 通常在关联的内嵌函数中使用 使用C变量代替寄存器 不是一个真正的汇编文件 通过优化器实现 ADS FAQ 入口 “Using the Inline Assembler”

Agenda ARM编译器的优化 C/C++和汇编混合模式编程 使用ARM编译器编码 局部和全局数据讨论

参数传递 开始四个字大小的参数直接使用寄存器的R0-R3来传递(快速且高效的) 更多的信息可参看ATPCS 如果需要更多的参数,将使用堆栈。(需要额外的指令和慢速的存储器操作) 所以通常限制参数的个数,使它为4或更少。 如果不可避免,把常用的参数前4个放在R0-R3中 Example...

Parameter Passing (4 parameters) int func1(int a, int b, int c, int d) { return a+b+c+d; } int caller1(void) return func1(1,2,3,4); func1 0x000000 : ADD r0,r0,r1 0x000004 : ADD r0,r0,r2 0x000008 : ADD r0,r0,r3 0x00000c : MOV pc,lr caller1 0x000014 : MOV r3,#4 0x000018 : MOV r2,#3 0x00001c : MOV r1,#2 0x000020 : MOV r0,#1 0x000024 : B func1

Parameter Passing (6 parameters) func2 0x000000 : STR lr, [sp,#-4]! 0x000004 : ADD r0,r0,r1 0x000008 : ADD r0,r0,r2 0x00000C : ADD r0,r0,r3 0x000010 : LDMIB sp,{r12,r14} 0x000014 : ADD r0,r0,r12 0x000018 : ADD r0,r0,r14 0x00001C : LDR pc,{sp},#4 caller2 0x000020 : STMFD sp!,{r2,r3,lr} 0x000024 : MOV r3,#6 0x000028 : MOV r2,#5 0x00002C : STMIA sp,{r2,r3} 0x000030 : MOV r3,#4 0x000034 : MOV r2,#3 0x000038 : MOV r1,#2 0x00003C : MOV r0,#1 0x000040 : BL func2 0x000044 : LDMFD sp!,{r2,r3,pc} int func2(int a,int b,intc, int,d,int e,int f) { return a+b+c+d+e+f; } int caller2(void) return func1(1,2,3,4,5,6); This code is compiled with “-O2 -Ono_autoinline”

循环终止 在for(), while() do…while()的循环中,用减到0代替加到某个值。 比如,用下面的代替 : for (loop = 1; loop <= total; loop++) //(ADD,CMP) 代替为: for (loop = total; loop != 0; loop--) //(SUBS) 尽量减少循环的次数 代码小,且使用更少的寄存器 Example...

Count down Loop Termination Count up int fact1(int limit) { int i; int fact = 1; for (i = 1; i <= limit; i++) fact = fact * i; } return fact; Count down int fact2(int limit) { int i; int fact = 1; for (i = limit; i != 0; i--) fact = fact * i; } return fact; fact2 0x000000 : MOVS r1,r0 0x000004 : MOV r0,#1 0x000008 : MOVEQ pc,lr 0x00000c : MUL r0,r1,r0 0x000010 : SUBS r1,r1,#1 0x000014 : BNE 0x0c 0x000018 : MOV pc,lr fact1 0x000000 : MOV r2,#1 0x000004 : MOV r1,#1 0x000008 : CMP r0,#1 0x00000c : BLT 0x20 0x000010 : MUL r2,r1,r2 0x000014 : ADD r1,r1,#1 0x000018 : CMP r1,r0 0x00001c : BLE 0x10 0x000020 : MOV r0,r2 0x000024 : MOV pc,lr This code is compiled with “-O2 -Otime”

除法操作(1) ARM核不含除法硬件 一些除法操作在编译时作为特例来处理 除法通常用一个运行库函数来实现 除2操作,被左移代替 运行需要很多的周期 unsigned div(unsigned a, unsigned b) { return (b / a); } div B __rt_udiv 一些除法操作在编译时作为特例来处理 除2操作,被左移代替 unsigned div2(unsigned b) { return (b / 2); } div2 MOV r0,r0,LSR #1 MOV pc,lr

除法操作 (2) 在 -O1和-O2 (使用 -Otime), 其他的常量将使用一个标准的乘法序列来完成 例如: 实时除法程序 使用CLZ指令 只有V5te体系结构才有效。 用下面的办法来选择 C - #pragma import __use_realtime_division Assembler - IMPORT __use_realtime_division unsigned div10(unsigned c) { return (c / 10); } div10 MOV r1,r0 LDR r0,=0xCCCCCCCD UMULL r2,r1,r0,r1 MOV r0,r1,LSR #3 MOV pc,lr

余数 – 模算法 余数的操作符 ‘%’, 通常使用模算法 如果这个值的模不是2的n次幂,它将花费大量的时间和代码空间 避免这种情况发生的办法使用if()作状态检查 比如说:count的范围是0到59 count = (count+1) % 60; 用下面的句子代替 if (++count >= 60) count = 0; modulo ADD r1,r0,#1 MOV r0,#0x3c BL __rt_udiv MOV r0,r1 test_and_reset ADD r0,r0,#1 CMP r0,#0x3c MOVCS r0,#0 这个代码用“-O1 -Ospace”编译

浮点 软件浮点库 (fplib) 浮点协处理器 软件浮点仿真 (FPE) VFP (and FPA) 实际上是硬件协处理器和仿真的混合 默认:-fpu softvfp (or softfpa) 浮点协处理器 VFP (ARM10 and ARM9) -fpu vfp (or vfpv1 or vfpv2) FPA (eg ARM7 500fe) - now obsolete -fpu fpa 软件浮点仿真 (FPE) 通过未定义的异常来捕获协处理器指令 VFP (and FPA) 实际上是硬件协处理器和仿真的混合 要求支持代码去实现混合运算 在AFS 1.3 和以后的版本里有VFP的 支持代码, 在ADS的FPA里. 在thumb代码使用fp处, vfp系统用-fpu softvfp+vfp编译 使用 -auto_float_constants 预防常量被处理为双精度类型,关闭警告用 -Wk. Example...

Floating point examples float foo(float num1, float num2) { float temp, temp2; temp = num1 + num2; temp2 = num2 * num2; return temp2-temp; } armcc float.c armcc -fpu vfpv2 float.c foo STMFD sp!,{r3-r5,lr} MOV r4,r1 BL _fadd MOV r5,r0 MOV r0,r4 MOV r1,r4 BL _fmul MOV r1,r5 LDMFD sp!,{r3-r5,lr} B _fsub 使用浮点库 foo FADDS s0,s0,s1 FMULS s1,s1,s1 FSUBS s0,s1,s0 MOV pc,lr 使用协处理器指令

Agenda ARM 编译器优化 C/C++和汇编混合模式编程 使用ARM编译器编码 局部和全局数据

变量类型 全局和静态变量保留在RAM里 局部变量通常放在寄存器中,用来快速且高效的处理 需使用loads/stores访问外部存储器 局部变量通常放在寄存器中,用来快速且高效的处理 如果编译器的寄存器分配算法认为超过现有的寄存器数量,将把变量压入栈中 对局部变量,用 word-sized (int) 代替 halfword 和 byte: 为了确保不受其他条件的影响,可特别指定使用32-bit寄存器变量.

变量大小 int wordsize(int a) wordsize { 0x000000 : MOV r0,r0,LSL #1 return (a*2); 0x000004 : MOV pc,lr } short halfsize(short b) halfsize { 0x000008 : MOV r0,r0,LSL #17 return (b*2); 0x00000c : MOV r0,r0,ASR #16 } 0x000010 : MOV pc,lr char bytesize(char c) bytesize { 0x000014 : MOV r0,r0,LSL #25 return (c*2); 0x000018 : MOV r0,r0,LSR #24 } 0x00001c : MOV pc,lr

堆栈的用法 C/C++代码的堆栈使用,堆栈用来保留: 注意: 子程序的返回地址 ‘溢出’的局部变量 局部数组和结构体 函数越小越好: (更少的变量,更少的‘溢出‘); 更少数量的‘live’变量 (比如:函数里每个点保存的有用的数据) 避免使用大的局部结构体或数组 (使用malloc/free代替) 避免递归

当要对堆栈使用情况进行估计时,使用‘worst case’ 堆栈使用估计 链接使用 -callgraph 显示静态堆栈的开销(html文件). 编译时使用软件堆栈检查 -apcs /swst 在栈结束点设置 watchpoint 测试堆栈 定义大的栈 填充某个值,看覆盖了多少,从而判定栈的使用情况 ARMulator映射文件 拒绝访问栈下面的区域,栈溢出将导致一个data abort异常 stackuse.c ARMulator模式, 跟踪堆栈的大小,用ARMulator的统计来输出报告 当要对堆栈使用情况进行估计时,使用‘worst case’

(Zero bytes of padding) 全局数据布局 全局数据保存在存储器里,不是寄存器 需要load / store指令来访问 用物理尺寸的边界对齐 ADS 1.2 会优化在一个模块里的全局数据的布局 用-Ono_data_reorder 将关闭排序 e.g. 声明的数据 char short char one; short two; char three; int four; Declared alignment 12 bytes (4 bytes of padding) char int char short Optimal alignment 8 bytes (Zero bytes of padding) ADS 1.1+ 将自动 用此风格排序 int

不对齐访问 ARM硬件需要在自然尺寸的边界访问内存 不对齐访问 需要必须告诉编译器,让它产生适当的指令序列 使用 __packed 属性 Word访问在word尺寸 Halfword访问在halfword尺寸 Byte访问在byte尺寸 不对齐访问 遗留代码 特定协议 需要必须告诉编译器,让它产生适当的指令序列 使用 __packed 属性 可能导致多字节访问代替单字节访问 用LDM指令的结果有2 字,转变为生成单字 不对齐数据的访问所产生的意外的结果取决于指令的使用 将是不可预知的

指针的对齐 必须非常小心指针的对齐 可能导致程序的失败 STMFD r13!,{r4,r14} LDR r4,0x58 LDR r1,[r4,#0] LDR r0,[r4,#4] LDMIA r1,{r2,r3,r12} STMIA r0,{r2,r3,r12} LDR r0,[r4,#8] MOV r2,#0xc BL __rt_memcpy STR r0,[r4,#4] LDR r1,0x5c STR r0,[r1,#0] LDMFD r13!,{r4,pc} memcpy inline’d #include <string.h> int *a = (int *)0x1000; int *b = (int *)0x2000; char *c = (char *)0x3001; __packed int *d; void foo (void) { memcpy (b,a,12); memcpy (c,a,12); b = (int *)c; memcpy (b,a,12); d = (__packed int *)c; memcpy ((void *)d,a,12); } memcpy called memcpy inline’d unsafely memcpy called safely

结构的打包 _packed 限定的数据为1字节对齐 不实现字节对齐调整 很高的访问代价,不会节省存储空间 int short U_int U_int __packed struct mystruct { int aligned_i; short aligned_s; int unaligned_i; }; extern struct mystruct S; struct mystruct { int aligned_i; short aligned_s; __packed int unaligned_i; }; extern struct mystruct S; PREFER... 在结构里定义打包的元素代替结构的打包 他将帮助减小访问输出的结构的开销 ADS FAQ 入口: Aligned v. unaligned accesses and use of __packed int short

优化的指针基地址 b a a 和 b 被定义为模块内用的数据 a 和 b 被定义为外部的 LDR r2, [pc,#12] extern int a; extern int b; void foo (int x, int y) { a = x; b = y; } 注意:在用-o0时无效 LDR r2, [pc,#8] STR r0, [r2,#0] STR r1, [r2,#4] MOV pc, lr DCD “base address of a and b” a 和 b 被定义为模块内用的数据 int a; int b; void foo (int x, int y) { a = x; b = y; } b a LDR r2, [pc,#12] STR r0, [r2,#0] LDR r3, [pc,#8] STR r1, [r3,#0] MOV pc, lr DCD “address of a” DCD “address of b” a 和 b 被定义为外部的

优化外部全局指针 如果全局数据放在结构体里,每个元素的访问将自动的在基指针上偏移 把数据放在多个逻辑结构体内,代替一个大的结构 在结构体里的元素将按大小的边界对齐 编译器不对结构体重新排列 把数据放在多个逻辑结构体内,代替一个大的结构 ‘#define’ 将对主应用代码的改变隐藏起来 #define value mystruct.value Example...

外部全局变量 data.c code.c Assembler output int a; int b; extern int a; extern int b; int main(void) { return a+b; } main LDR r0,0x000080c0 000080ac LDR r1,0x000080c4 000080b0 LDR r0,[r0,#0] 000080b4 LDR r1,[r1,#0] 000080b8 ADD r0,r0,r1 000080bc MOV pc,lr 000080c0 DCD 0x000083d4 000080c4 DCD 0x000083d8 extern struct data mystruct; int main(void) { return mystruct.a+mystruct.b; } struct data int a; int b; }mystruct; main LDR r0,0x000080bc 000080ac LDR r1,[r0,#0] 000080b0 LDR r0,[r0,#4] 000080b4 ADD r0,r1,r0 000080b8 MOV pc,lr 000080bc DCD 0x000083cc

测验 1) 默认的优化级别是什么? 2)给tail-call优化有什么好处 3) 在函数调用时,管理寄存器用法的标准的名字是什么? 1) 默认的优化级别是什么? 2)给tail-call优化有什么好处 3) 在函数调用时,管理寄存器用法的标准的名字是什么? 4) 在参数传递时,被推荐的最大的量是多少? 5) 为什么在arm里要尽可能避免使用除法? 6) __packed的效果是什么?

参考 需要更多的信息,请看: ADS 1.2 Compilers and Libraries Guide Section 2 : C and C++ Compilers Section 3 : ARM Compiler Reference ADS 1.2 Developer Guide Chapter 4: Mixing C, C++ and Assembly Language Application Note 34, Writing Efficient C Application Note 36, Declaring Global Data in C