嵌入式系统基础-第6章--ARM程序设计_第1页
嵌入式系统基础-第6章--ARM程序设计_第2页
嵌入式系统基础-第6章--ARM程序设计_第3页
嵌入式系统基础-第6章--ARM程序设计_第4页
嵌入式系统基础-第6章--ARM程序设计_第5页
已阅读5页,还剩73页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章ARM 本章的主要内容 1 ARM汇编语言程序设计 2 ARM程序的框架结构 3 C语言程序对汇编程序的调用 4 ARM与C语言混合程序设计 6 1ARM工程 由于C语言便于理解 有大量的支持库 所以它是当前ARM程序设计所使用的主要编程语言 对硬件系统的初始化 CPU状态设定 中断使能 主频设定以及RAM控制参数初始化等C程序力所不能及的底层操作 还是要由汇编语言程序来完成 用汇编语言或C C 语言编写的程序叫做源程序 对应的文件叫做源文件 一个ARM工程应由多个文件组成 其中包括扩展名为 S的汇编语言源文件 扩展名为 C的C语言源文件 扩展名为 CPP的C 源文件 扩展名为 H的头文件等 ARM工程的各种源文件之间的关系 以及最后形成可执行文件的过程如下 汇编语言源文件 汇编器 目标文件 C C 语言源文件 编译器 目标文件 头文件 C C 库文件 连接器 可执行文件 ARM提供的开发工具CodeWarriorforARM中包含的编译器如下 除了C和C 编译器 CodeWarriorforARM开发工具还提供了汇编器ARMASM 编译器负责生成目标文件 它是一种包含了调试信息的ELF格式文件 编译器还要生成列表文件等相关文件 各种源文件先由编译器和汇编器将它们分别编译或汇编成汇编语言文件及目标文件 连接器负责将所有目标文件连接成一个文件并确定各指令的确定地址 从而形成最终可执行文件 连接器有三个功能 1 生成与地址相关的代码 把所有文件连接成一个可执行文件 2 根据程序员所指定的选项 为程序分配地址空间 3 给出连接信息 以说明连接过程和连接结果 6 2ARM汇编语言程序设计 6 2 1段 汇编语言编写的程序叫做汇编语言源程序 包含源程序的文件叫做汇编语言程序文件 一个工程可以有多个源文件 汇编源文件的扩展名为 S 在ARM Thumb 汇编语言程序中 通常以段为单位来组织代码 段是具有特定名称且功能相对独立的指令或数据序列 根据段的内容 分为代码段和数据段 一个汇编程序至少应该有一个代码段 当程序较长时 可以分割为多个代码段和数据段 以下是一个汇编语言程序段的基本结构 AREAInit CODE READONLY 只读的代码段InitENTRY 程序入口点startLDRR0 0X3FF5000LDRR1 0XFFSTRR1 R0 LDRR0 0X3FF5008LDRR1 0X01STRR1 R0 END 段结束 6 2 2分支程序设计 具有两个或两个以上可选执行路径的程序叫做分支程序 1 普通分支程序设计 使用带有条件码的指令可以很容易地实现分支程序 例 编写一个分支程序段 如果寄存器R5中的数据等于10 就把R5中的数据存如寄存器R1 否则把R5中的数据分别存储寄存器R0和R1 1 用条件指令实现的分支程序段 CMPR5 10MOVNER0 R5MOVR1 R5 2 用条件转移指令来实现分支 CMPR5 10BEQdoequalMOVR0 R5doequalMOVR1 R5 例 编写一个程序段 当寄存器R1中的数据大于R2中数据时 将R2中的数据加10存入寄存器R1 否则将R2中数据加5存入寄存器R1 CMPR1 R2ADDHIR1 R2 10ADDLSR1 R2 5 2 多分支 散转 程序设计 程序分支点上有多于两个以上的执行路径的程序叫做多分支程序 利用条件测试指令或跳转表可以实现多分支程序 例 编写一个程序段 判断寄存器R1中数据是否为10 15 12 22 如果是 则将R0中的数据加1 否则将R0设置为0XF MOVR0 0TEQR1 10TEQNER1 15TEQNER1 12TEQNER1 22ADDEQR0 R0 1MOVNER0 0XF 当多分支程序的每个分支所对应的是一个程序段时 常常把各个分支程序段的首地址依次存放在一个叫做跳转地址表的存储区域 然后在程序的分支点处使用一个可以将跳转表中的目标地址传送到PC的指令来实现分支 一个具有3个分支的跳转地址表示意图如下 MOVR0 NADRR5 JPTBLDRPC R5 R0 LSL 2 JPTAB 跳转表DCDFUN0DCDFUN1ECDFUN2FUN0 分支FUN0的程序段FUN1 分支FUN1的程序段FUN2 分支FUN2的程序段 3 带ARM Thumb状态切换的分支程序设计 在ARM程序中经常需要在程序跳转的同时还要进行处理器状态的转移 即从ARM指令程序段跳转到Thumb指令程序段 或相反 为了实现这个功能 系统提供了一条专用的 可以实现4GB空间范围内的绝对跳转交换指令BX 下面是一段从ARM指令程序段跳转到Thumb指令程序的状态切换例程 ARM指令程序CODE32 ADDR0 Into Thumb 1BXR0 Thumb指令程序CODE16Into Thumb 下面是一段从Thumb指令程序段跳转到ARM指令程序的状态切换例程 Thumb指令程序CODE16 ADDR5 Back to ARMBXR0 ARM指令程序CODE32Back to ARM 6 2 3循环程序设计 当条件满足时 需要重复执行同一个程序段做同样工作的程序叫做循环程序 被重复执行的程序段叫做循环体 需要满足的条件叫做循环条件 循环程序有两种结构 DO WHILE结构和DO UNTIL结构 DO WHILE结构 DO UNTIL结构 在汇编语言程序设计中 常用的是DO UNTIL结构循环程序 MOVR1 10LOOP SUBR1 R1 1BNELOOP 例 编写一个程序 把首地址为DATA SRC的80个字的数据复制到首地址为DATA DST的目标数据块中 LDRR1 DATA SRCLDRR0 DATA DSTMOVR10 10LOOPLDMIAR1 R2 R9 STMIAR0 R2 R9 SUBSR10 R10 1BNELOOP 6 2 4子程序及其调用 1 子程序的调用与返回 人们把这种可以多次反复调用的 能完成指定功能的程序段称为 子程序 把调用子程序的程序称为 主程序 为进行识别 子程序的第1条指令之前必须赋予一个标号 以便其他程序可以用这个标号调用子程序 在ARM汇编语言程序中 主程序一般通过BL指令来调用子程序 该指令在执行时完成如下操作 将子程序的返回地址存放在连接寄存器LR中 同时将程序计数器PC指向子程序的入口点 为使子程序执行完毕能返回主程序的调用处 子程序末尾处应有MOV B BX STMFD等指令 并在指令中将返回地址重新复制到PC中 在调用子程序的同时 也可以使用R0 R3来进行参数的传递和从子程序返回运算结果 例 一个使用MOV指令实现返回的子程序 relay MOVPC LR 使用B指令实现返回的子程序 relay BLR 例 一个使用BL指令调用子程序的汇编语言缘程序的基本结构 AERAInit CODE READONLYENTRYstartLDRR0 0X3FF5000LDRR1 0XFFSTRR1 R0 LDRR0 0X3FF5008LDRR1 0X01STRR1 R0 BLPR PR MOVPC LR END 2 子程序中堆栈的使用 relaySTMFDR13 R0 R12 LR 压入堆栈 子程序代码LDMFDR13 R0 R12 PC 弹出堆栈并返回 6 2 5汇编程序访问全局C变量 一般来说 汇编语言程序与C语言程序不在同一个文件上 所以实质上这是一个引用不同文件定义的变量问题 解决这个问题的办法就是使用关键字IMPORT和EXPORT 例 下面是一个汇编代码的函数 它引用了一个在其他文件中定义的全局变量globvar 将其加2后写回globvar AREAglobvar CODE READONLYEXPORTasmsubrouttineIMPORTglobvarAsmsubrouttineLDRR1 globvarLDRR0 R1 ADDR0 R0 2STRR0 R1 MOVPC LREND 6 3ARM程序框架 在应用系统的程序设计中 若所有的编程任务均用汇编语言来完成 其工作量是可想而知的 这样做也不利于系统升级或应用软件移植 通常汇编语言部分完成系统硬件的初始化 高级语言部分完成用户的应用 执行时 首先执行初始化部分 然后再跳转到C C 部分 整个程序结构显得清晰明了 容易理解 程序的基本结构如下 硬件初始化的汇编语言程序 特权模式 Bmain 完成用户任务的C C 程序 用户模式 跳转 6 3 1初始化程序部分 由于在用于完成初始化任务的汇编语言程序中需要在特权模式下做一些诸如修改CPSR等特权操作 所以不能过早地进入用户模式 通常 初始化过程大致会经历如下所示的一些模式变化 启动 管理模式svc 其他特权模式 用户模式usr 汇编语言程序段 6 3 2初始化部分与主应用程序部分的衔接 当所有的系统初始化工作完成之后 就需要把程序流程转入主应用程序 最简单的方法是 在汇编语言程序末尾使用跳转指令B或BL直接从启动代码转移到C C 程序入口 Bmain 跳转到C C 程序 同时在汇编文件中有如下代码 IMPORTmain 完整的汇编语言程序如下 IMPORTmainAREAInit CODE READONLYENTRYLDRR0 0X3FF000LDRR1 0XE7FFFF80STRR1 R0 LDRSP 0X3EE1000BLmainEND C程序如下 voidmain void 6 3 3ARM开发环境提供的程序框架 为方便工程开发 ARM公司的开发环境ARMADS为用户提供了一个可以选用的应用程序框架 该框架把为用户程序做准备工作的程序分成了启动代码和应用程序初始化两部分 用于硬件初始化的汇编语言部分叫做启动代码 用于应用程序初始化的C部分叫做初始化部分 整个程序如下所示 IMPORT main启动代码B main 应用程序初始化 主用程序 main main 6 4C与汇编之间的函数调用 在ARM工程中 C程序调用汇编函数和汇编程序调用C函数是经常发生的事情 为此人们制定了ARM Thumb过程调用标准ATPCS ARM ThumbProcedureCallStandard 6 4 1ATPCS简介 1 堆栈与寄存器在函数调用中的作用 函数是通过寄存器和堆栈来传递参数和返回函数值的 下面是C语言程序调用C函数的情况 intAddInt intx inty ints s x y returns 在C程序中 主函数main 调用该函数的方法如下 voidmain void AddInt a b 调用 ARM编译器使用的函数调用规则就是ATPCS标准 ATPCS标准既是ARM编译器的规则 也是设计可被C程序调用的汇编函数的编写规则 2 ATPCS关于堆栈和寄存器的使用规则 ATPCS规定 ARM的数据堆栈为FD型堆栈 即递减满堆栈 ATPCS标准规定 对于参数个数不多于4的函数 编译器必须按参数在列表中的顺序 自左向右为它们分配寄存器R0 R3 其中函数返回时 R0还被用来存放函数的返回值 如果函数的参数多于4个 那么多余的参数则按自右向做的顺序压入数据堆栈 即参数入栈顺序与采纳书顺序相反 下表列举了ARM Thumb过程调用标准规定的寄存器的名称和使用方法 寄存器的别名和特殊名称都是ARM编译器和汇编器预定义的 用户可以直接使用 6 4 2C程序可调用汇编函数实例 下面是一个用汇编语言编写的函数 该函数把R1指向的数据块复制到R0指向的存储快 AREAstrcopy CODE READONLYEXPORTstrcopystrcopyLDRBR2 R1 1STRBR2 R0 1CMPR2 0BNEstrcopyMOVPC LREND 根据ATPCS的C语言程序调用汇编函数 参数由左向右依次传递给寄存器R0 R3的规则 可知汇编函数strcopy在C程序中原型应该为 voidstrcopy char d constchar s 在C语言文件中 调用strcopy函数的方法如下 externvoidstrcopy char d constchar s intmain void constchar src source chardest 10 strcopy dest src 6 4 3汇编程序调用C函数实例 现有C函数g 如下 intg inta intb intc intd inte returna b c d e 汇编函数f中调用C函数g 以实现下面的功能 整个汇编函数f的代码如下 intf inti return g i 2 i 3 i 4 i 5 i EXPORTfAREAf CODE READONLYIMPORTg 声名g为外部引用符号STRLR SP 4 断点存入堆栈ADDR1 R0 R0 R1 i 2ADDR2 R1 R0 R2 i 3ADDR3 R1 R2 R3 i 5STRR3 SP 4 将 R3 即第5个参数i 5存入堆栈ADDR3 R1 R1 R3 i 4 BLg 调用C函数g 返回值在寄存器R0中ADDSP SP 4 清栈RSBR0 R0 0 函数f的返回值 R0 0 R0 LDRPC SP 4 恢复断点并返回END 6 5C C 语言和汇编语言的混合编程 除了上面介绍的函数调用方法之外 ARM编译器armcc中含有内嵌汇编器还允许在C程序中内联或嵌入式汇编代码 以提高程序的效率 6 5 1内联汇编 1 定义内联汇编程序 所谓内联汇编程序 就是在C程序中直接编写汇编程序段而形成一个语句块 这个语句块可以使用除了BX和BLX之外的全部ARM指令来编写 从而可以使程序实现一些不能从C获得的底层功能 其格式为 asm 汇编语句块 例 voidenable IRQ void inttmp asm 声名内联汇编代码 MRStmp CPSRBICtmp tmp 0 x80MSRCPSR c tmp 2 内联汇编的限制 内联汇编与真实汇编之间有很大区别 会受到很多限制 1 它不支持Thumb指令 除了程序状态寄存器PSR之外 不能直接访问其他任何物理寄存器等 2 如果在内联汇编程序指令中出现了以某个寄存器名称命名的操作数 那么它 被叫做虚拟寄存器 而不是实际的物理寄存器 编译器在生成和优化代码的过程中 会给每个虚拟寄存器分配实际的物理寄存器 但这个物理寄存器可能与在指令中指定的不同 唯一的一个例外就是状态寄存器PSR 任何对PSR的引用总是执行指向物理PSR 3 在内联汇编代码中不能使用寄存器PC R15 LR R14 和SP R13 任何试图使用这些寄存器的操作都会导致出现错误消息 4 鉴于上述情况 在内联汇编语句块中最好使用C或C 变量作为操作数 5 虽然内联汇编代码可以更改处理器模式 但更改处理器模式会禁止使用C操 作数或对已编译C代码的调用 直到将处理器模式恢复为原设置之后 6 5 2嵌入式汇编 嵌入式汇编程序是一个编写在C程序外的单独汇编程序 该程序段可以像函数那样被C程序调用 与内联汇编不同 嵌入式汇编具有真实汇编的所有特性 数据交换符合ATPCS标准 同时支持ARM和Thumb 所以它可以对目标处理器进行不受限制的低级访问 但是不能直接引用C C 的变量 用 asm声明的嵌入式汇编程序像C函数那样可以有参数和返回值 定义一个嵌入式汇编函数的语法格式为 asmreturn typefunction name parameter list 汇编程序段 return type 函数返回值类型 function name 函数名 parameter list 函数参数列表 嵌入式汇编在形式上看起来就像使用关键字 asm进行了声

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论