您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 其它行业文档 > 嵌入式处理器原理及应用-Chapter8-ARM程序设计2015
第八章ARM程序设计共95页2主要内容共95页38.1ARM工程由于C语言便于理解,有大量的支持库,所以它是当前ARM程序设计所使用的主要编程语言。对硬件系统的初始化、CPU状态设定、中断使能、主频设定以及RAM控制参数初始化等C程序力所不能及的底层操作,还是要由汇编语言程序来完成。一个ARM工程应由多个文件组成,其中包括扩展名为.S的汇编语言源文件、扩展名为.C的C语言源文件,扩展名为.CPP的C++源文件、扩展名为.H的头文件等。共95页4ARM工程的各种源文件之间的关系,以及最后形成可执行文件的过程如下:8.1ARM工程(续)共95页4共95页5编译器负责生成目标文件,它是一种包含了调试信息的ELF格式文件。ELF(ExecutableandLinkingFormat):可执行链接格式。它是UNIX系统实验室(USL)作为应用程序二进制接口(ApplicationBinaryInterface(ABI)而开发和发布的。工具接口标准委员会(TIS)选择了正在发展中的ELF标准作为工作在32位INTEL体系上不同操作系统之间可移植的二进制文件格式。编译器还要生成列表文件等相关文件:8.1ARM工程(续)文件扩展名说明.h头文件.oELF格式的目标文件.s汇编代码文件.lst错误及警告信息列表文件共95页6各种源文件先由编译器和汇编器将它们分别编译或汇编成汇编语言文件及目标文件。链接器负责将所有目标文件连接成一个文件并确定各指令的确定地址,从而形成最终可执行文件。8.1ARM工程(续)(1)生成与地址相关的代码,把所有文件连接成一个可执行文件;(2)根据程序员所指定的选项,为程序分配地址空间;(3)给出链接信息,以说明链接过程和结果。链接器有三个功能:共95页78.2ARM汇编语言程序设计8.2.1段在ARM(Thumb)汇编语言程序中,通常以段为单位来组织代码。段是具有特定名称且功能相对独立的指令或数据序列。因此根据段的内容,分为代码段和数据段。一个汇编程序至少应该有一个代码段,当程序较长时,可以分割为多个代码段和数据段。共95页8以下是一个汇编语言程序段的基本结构:AREAInit,CODE,READONLY;只读的代码段InitENTRY;程序入口点startLDRR0,=0X3FF5000LDRR1,=0XFF;或MOVR1,#0XFFSTRR1,[R0]LDRR0,=0X3FF5008LDRR1,=0X01;或MOVR1,#0X01STRR1,[R0]…….END;段结束共95页98.2.2分支程序设计具有两个或两个以上可选执行路径的程序叫做分支程序。1、普通分支程序设计使用带有条件码的指令可以很容易地实现分支程序。例1:编写一个分支程序段,如果寄存器R5中的数据等于10,就把R5中的数据存入寄存器R1;否则把R5中的数据分别存入寄存器R0和R1。NY共95页10(1)用条件指令实现的分支程序段CMPR5,#10MOVNER0,R5MOVR1,R5(2)用条件转移指令来实现分支程序段CMPR5,#10BEQdoequalMOVR0,R5doequalMOVR1,R5NY共95页11例2:编写一个程序段,当寄存器R1中的数据大于R2中数据时,将R2中的数据加10存入寄存器R1;否则将R2中数据加5存入寄存器R1。1、普通分支程序设计(续)CMPR1,R2ADDHIR1,R2,#10ADDLSR1,R2,#5(1)HI:无符号数大于,LS:无符号数小于或等于;(2)GT:带符号数大于,LE:带符号数小于或等于。共95页122、多分支(散转)程序设计程序分支点上有多于两个以上的执行路径的程序叫做多分支程序。利用条件测试指令或跳转表可以实现多分支程序。共95页13例3:编写一个程序段,判断寄存器R1中数据是否为10、15、12、22。如果是,则将R0中的数据加1;否则将R0设置为0XF。MOVR0,#0TEQR1,#10TEQNER1,#15TEQNER1,#12TEQNER1,#22ADDEQR0,R0,#1MOVNER0,#0XF共95页14当多分支程序的每个分支所对应的是一个程序段时,常常把各个分支程序段的首地址依次存放在一个叫做跳转地址表的存储区域,然后在程序的分支点处使用一个可以将跳转表中的目标地址传送到PC的指令来实现分支。2、多分支(散转)程序设计(续)共95页15一个具有3个分支的跳转地址表MOVR0,N;N为表项序号0~2ADRR5,JPTABLDRPC,[R5,R0,LSL#2]JPTAB;跳转表DCDFUN0DCDFUN1DCDFUN2FUN0…..;分支FUN0的程序段FUN1…..;分支FUN1的程序段FUN2…..;分支FUN2的程序段共95页163、带ARM/Thumb状态切换的分支程序设计在ARM程序中经常需要在程序跳转的同时还要进行处理器状态的转移,即从ARM指令程序段跳转到Thumb指令程序段(或相反)。为了实现这个功能,系统提供了一条专用的、可以实现4GB空间范围内的绝对跳转交换指令BX。跳转目标地址高31位1/0031103110TRmPC(R15)CPSRARM/Thumb选择位0——ARM1——Thumb;Thumb指令程序CODE16…..ADRR5,Back_to_ARMBXR0…..;ARM指令程序CODE32Back_to_ARM…….共95页17从ARM指令程序段跳转到Thumb指令程序的状态切换例程:;ARM指令程序CODE32…..ADRR0,Into_Thumb+1BXR0…..;Thumb指令程序CODE16Into_Thumb…….从Thumb指令程序段跳转到ARM指令程序的状态切换例程:共95页18DO-WHILE结构DO-UNTIL结构8.2.3循环程序设计共95页19LDRR1,=DATA_SRCLDRR0,=DATA_DSTMOVR10,#10LOOPLDMIAR1!,{R2-R9}STMIAR0!,{R2-R9}SUBSR10,R10,#1BNELOOP例4:编写一个程序,把首地址为DATA_SRC的80个字的数据复制到首地址为DATA_DST的目标数据块中。在汇编语言程序设计中,常用的是DO-UNTIL结构循环程序。MOVR1,#10LOOP…….SUBSR1,R1,#1BNELOOP共95页201、子程序的调用与返回人们把可以多次反复调用的、能完成指定功能的程序段称为“子程序”。把调用子程序的程序称为“主程序”。为进行识别,子程序的第1条指令之前必须赋予一个标号,以便其他程序可以用这个标号调用子程序。8.2.4子程序及其调用在ARM汇编语言程序中,主程序一般通过BL指令来调用子程序。该指令在执行时完成如下操作:将子程序的返回地址存放在连接寄存器LR中,同时将程序计数器PC指向子程序的入口点。共95页21在调用子程序的同时,也可以使用R0~R3来进行参数的传递和从子程序返回运算结果。例5:使用MOV指令实现返回的子程序。relay…..MOVPC,LR1、子程序的调用与返回(续)例6:使用B指令实现返回的子程序。relay…..BLR为使子程序执行完毕能返回主程序的调用处,子程序末尾处应有MOV、B、BX、LDMFD等指令,并在指令中将返回地址重新复制到PC中。共95页22例7:一个使用BL指令调用子程序的汇编语言源程序的基本结构。AERAInit,CODE,READONLYENTRYstartLDRR0,=0X3FF5000LDRR1,=0XFFSTRR1,[R0]LDRR0,=0X3FF5008LDRR1,=0X01STRR1,[R0]BLPR…….1、子程序的调用与返回(续)PR……MOVPC,LR……END共95页232、子程序中堆栈的使用relaySTMFDR13!,{R0~R12,LR};压入堆栈……;子程序代码LDMFDR13!,{R0~R12,PC};弹出堆栈并返回共95页248.2.5汇编程序访问全局C变量一般来说,汇编语言程序与C语言程序不在同一个文件上,所以实质上这是一个引用不同文件定义的变量问题。解决这个问题的办法就是使用关键字IMPORT和EXPORT。在C程序中声明的全局变量可以被汇编程序通过地址间接访问,具体访问方法如下。1、使用IMPORT伪指令声明该全局变量;2、使用LDR指令读取该全局变量的内存地址,通常该全局变量的内存地址值存放在程序的数据缓冲池中;3、根据该数据的类型,使用相应的LDR指令读取该全局变量的值;使用相应的STR指令修改该全局变量的值。共95页变量数据类型对应的LDR/STR指令无符号char类型LDRB/STRB无符号short类型LDRH/STRHint类型LDR/STR有符号char类型LDRSB/STRSB有符号short类型LDRSH/STRSH小于8个字的结构型变量LDM/STM结构型变量的数据成员使用相应的LDR/STR指令来访问,这时必须知道该数据成员相对于结构型变量开始地址的偏移量共95页26例、下面是一个汇编代码的函数,它引用了一个在其他文件中定义的全局变量globvar,将其加2后写回globvar。AREAglobals,CODE,READONLYEXPORTasmsubrouttineIMPORTglobvarAsmsubrouttineLDRR1,=globvarLDRR0,[R1]ADDR0,R0,#2STRR0,[R1]MOVPC,LREND共95页278.3ARM程序框架在应用系统的程序设计中,若所有的编程任务均用汇编语言来完成,其工作量是可想而知的,这样做也不利于系统升级或应用软件移植。通常汇编语言部分完成系统硬件的初始化;高级语言部分完成用户的应用。执行时,首先执行初始化部分,然后再跳转到C/C++部分。程序的基本结构如下:共95页27硬件初始化的汇编语言程序(特权模式)Bmain完成用户任务的C/C++程序(用户模式)共95页288.3.1初始化程序部分通常,初始化过程大致会经历如下所示的一些模式变化。由于在用于完成初始化任务的汇编语言程序中需要在特权模式下做一些诸如修改CPSR等特权操作,所以不能过早地进入用户模式。管理模式svc其他特权模式用户模式usr共95页298.3.2初始化部分与主应用程序部分的衔接当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序。最简单的方法是,在汇编语言程序末尾使用跳转指令B或BL直接从启动代码转移到C/C++程序入口。汇编语言程序:IMPORTmainAREAInit,CODE,READONLYENTRYLDRR0,=0X3FF0000LDRR1,=0XE7FFFF80STRR1,[R0]LDRSP,=0X3EE1000BLmainENDC程序:voidmain(void){…..}共95页30为方便工程开发,ARM公司的开发环境ARMADS为用户提供了一个可以选用的应用程序框架。该框架把为用户程序做准备工作的程序分成了启动代码和应用程序初始化两部分。用于硬件初始化的汇编语言部分叫做启动代码;用于应用程序初始化的C部分叫做初始化部分。8.3.3ARM开发环境提供的程序框架共95页IMPORT__main启动代码B__main应用程序初始化main()主应用程序共95页318.4C与汇编之间的函数调用在ARM工程中,C程序调用汇编函数和汇编程序调用C函数是经常发生的事情。为此人们制定了ARM-Thumb过程调用标准ATPCS(ARM-ThumbProcedureCallStandard)。ATPCS标准既是ARM编译器使用的函数调用规则,也是设计可被C程序调用的汇编函数的编写规则。共95页321、堆栈与寄存器在函数调用中的作用函数是通过寄存器和堆栈来传递参数和返回函数值的。下面是C语言程序调用C函数的情况。intAddInt(intx,inty){ints;s=x+y;returns;}8.4.1ATPCS简介voidmain(void){……AddInt(a,b);//调用……}共95页332、
本文标题:嵌入式处理器原理及应用-Chapter8-ARM程序设计2015
链接地址:https://www.777doc.com/doc-2440621 .html