arm嵌入式原理技术及应用ch-4.ppt

上传人:本田雅阁 文档编号:2889731 上传时间:2019-06-02 格式:PPT 页数:75 大小:394.52KB
返回 下载 相关 举报
arm嵌入式原理技术及应用ch-4.ppt_第1页
第1页 / 共75页
arm嵌入式原理技术及应用ch-4.ppt_第2页
第2页 / 共75页
arm嵌入式原理技术及应用ch-4.ppt_第3页
第3页 / 共75页
arm嵌入式原理技术及应用ch-4.ppt_第4页
第4页 / 共75页
arm嵌入式原理技术及应用ch-4.ppt_第5页
第5页 / 共75页
点击查看更多>>
资源描述

《arm嵌入式原理技术及应用ch-4.ppt》由会员分享,可在线阅读,更多相关《arm嵌入式原理技术及应用ch-4.ppt(75页珍藏版)》请在三一文库上搜索。

1、2019/6/2,2010.12,陈 赜,ARM嵌入式技术原理与应用, 13135699803,2019/6/2,第四章 ARM汇编程序设计,2019/6/2,了解与熟悉ADS下的伪操作和宏指令以及它的应用 了解与熟悉GNU下的伪操作和宏指令以及它的应用 熟悉ARM ATPCS 能够利用汇编语言进行简单的程序设计,2019/6/2,1. 伪指令、伪操作和宏指令概念,伪指令是汇编语言程序里的特殊指令助记符,在汇编时被合适的机器指令替代。 伪操作为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编过程起作用,不参与程序运行。,4.1. 汇编伪指令和宏指令,2019/6/2,宏指令通过伪操作定

2、义的一段独立的代码。在调用它时将宏体插入到源程序中。也就是常说的宏。 说明:所有的伪指令、伪操作和宏指令,均与具体的开发工具中的编译器有关,当前主要采用ARM公司的“ADS/SDT IDE”开发工具,所以后面的讨论,均是基于ARM公司的开发工具。,2019/6/2,2 . ARM汇编伪指令,ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替。ARM伪指令有四条,分别是: ADR:小范围的地址读取伪指令。 ADRL:中等范围的地址读取伪指令。 LDR:大范围的地址读取伪指令。 NOP:空操作伪指令。,20

3、19/6/2,(1) ADR小范围的地址读取 ADR伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。 ADR伪指令功能的实现方法:在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现此ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 语法格式: ADRcond register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围是参考P212,2019/6/2,例1: (0x20) ADR R1,Delay Delay (0x64) MOV R0,

4、R14 使用ADR将程序标号Delay所表示的地址存入R1。,编译后的反汇编代码: ADD R1,PC,#0x3C MOV R0,R14,PC+0x3C =0x20+0x08+0x3C =0x64,2019/6/2,例2:查表 ADR R0,D_TAB ;加载转换表地址 LDRB R1,R0,R2 ;使用R2作为参数,进行查表 D_TAB DCB 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92,2019/6/2,(2)ADRL中等范围的地址读取 ADRL伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。

5、 ADRL伪指令功能实现方法:在汇编编译器编译源程序时,ADRL被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 语法格式: ADRLcond register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围参考P212,2019/6/2,例3: (0x20) ADRL R1,Delay Delay (0x64) MOV R0,R14 使用ADRL将程序标号Delay所表示的地址存入R1。,编译后的反汇编代码: ADD R1,PC,#0x3C ADD R1,R1,#0 MOV R0,R14,ADRL伪指令被汇编成两条指令,尽管第

6、2条指令并没有意义。,2019/6/2,(3)LDR 大范围的地址读取 LDR伪指令功能:用于加载32位立即数或一个地址值到指定的寄存器。 LDR伪指令功能实现方法:在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。 若加载的常数未超过MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令; 否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。,2019/6/2,语法格式: LDRcond register,=expr 其中: Register:加载的目标寄存器。 expr:32位常量或地址表达式。,2019/6/2,例4: (0x060) L

7、DR R1,=Delay Delay (0x102) MOV R0,R14 ,使用LDR将程序标号Delay所表示的地址存入R1。,编译后的反汇编代码: LDR R1,stack Delay MOV R0,R14 LTORG stack DCD 0x102,LDR伪指令被汇编成一条LDR指令,并在文字池中定义一个常量,该常量为标号Delay的地址。,2019/6/2,注意: 从指令位置到文字池的偏移量必须小于4KB。 与ARM指令的LDR的区别:伪指令LDR的参数有“=”号。,2019/6/2,(4)NOP空操作伪指令 NOP伪指令功能实现方法:在汇编时将被替代成ARM中的空操作,比如可能是“

8、MOV R0,R0”指令等。 用途:NOP可用于延时操作。 语法格式: NOP 例:延时子程序 Delay NOP ;空操作 NOP NOP SUBS R1,R1,#1 ;循环次数减1 BNE Delay MOV PC,LR,2019/6/2,3. ARM汇编伪操作,ADS编译环境下的伪操作可分为以下几类: 符号定义(Symbol Definition)伪操作 数据定义(Data Definition)伪操作 汇编控制(Assembly Control)伪操作 其它(Miscellaneous)伪操作,2019/6/2,(1) 符号定义伪操作,GBLA,GBLL,GBLS:声明全局变量。 LC

9、LA,LCLL,LCLS:声明局部变量。 SETA,SETL,SETS:给变量赋值。 RLIST:为通用寄存器列表定义名称。,2019/6/2,(2) 数据定义伪操作,LTORG:声明一个数据缓冲池的开始 SPACE:分配一块字节内存单元,并用0初始化 DCB:分配一段字节内存单元,并初始化 DCD、DCDU:分配一段字内存单元,并初始化 MAP:定义一个结构化的内存表的首地址 FIELD:定义结构化内存表中的一个数据域,2019/6/2, MAP、 FIELD、 SPACE MAP 0x100, R0 ;定义结构化内存表首地址的值为0x100R0 A FIELD 16 ;定义A的长度为16字

10、节,位置为0x110+R0 LTORG ;定义数据缓冲池从当前位置开始分配4200字节的内存单元,并初始化为0。,2019/6/2,LTORG 用于声明一个数据缓冲池(文字池)的开始。 语法格式: LTORG 例:start BL func ; func LDR R1,=0x8000 ;子程序 MOV PC,LR ;子程序返回 LTORG ;定义数据缓冲池从当前位置开始分配4200字节的内 存单元,并初始化为0。 END 默认数据缓冲池为空,2019/6/2,注意: LTORG伪操作通常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器不会错误地将数据缓冲池中的数据当作指令来执行。 通

11、常ARM汇编编译器把数据缓冲池放在代码段的最后面,即下一个代码段开始之前,或者END伪操作之前。,2019/6/2, DCB也可以用符号”=”表示 用于定义并且初始化一个或者多个字节的内存区域。 语法格式: label DCB expr,expr 或 label = expr,expr 其中expr表示: -128到255之间的一个数值常量或者表达式。 一个字符串。 注意:当DCB后面紧跟一个指令时,可能需要使用ALIGN确保指令是字对齐的。,2019/6/2,例: short DCB 1 ;为short分配了一个字节,并初始化为1。 string DCB “string”,0 ;构造一个以0

12、 结尾的字符串,2019/6/2,DCD、DCDU分配一段字内存单元 (1)DCD 分配一段字对齐的内存单元 用于分配一段字对齐的内存单元,并初始化。 DCD也可以用符号”&”表示 语法格式: label DCD expr,expr 或 label & expr,expr 其中: expr :数字表达式或程序中的标号。 注意:DCD伪操作可能在分配的第一个内存单元前插入填补字节以保证分配的内存是字对齐的。,2019/6/2,例: data1 DCD 2,4,6 ;为data1分配三个字,内容初始化为2,4,6 data2 DCD label+4 ;初始化data2为label+4对应的地址 (

13、2)DCDU 分配一段字非严格对齐的内存单元 DCDU与DCD的不同之处在于DCDU分配的内存单元并不严格字对齐。,2019/6/2,(3)汇编控制伪操作,IF,ELSE及ENDIF:有条件选择汇编 WHILE及WEND:有条件循环(重复)汇编 MACRO,MEND及MEXIT:宏定义汇编,2019/6/2,(4)其它伪操作,AREA:定义一个代码段或数据段 CODE16、CODE32:告诉编译器后面的指令序列位数 ENTRY:指定程序的入口点 ALIGN:将当前的位置以某种形式对齐 END:源程序结尾 EQU:为数字常量、基于寄存器的值和程序中的标号定义一个字符名称。,2019/6/2, E

14、XPORT、GLOBAL:声明源文件中的符号可以被其他源文件引用 IMPORT、EXTERN:声明某符号是在其他源文件中定义的 GET、INCLUDE:将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 INCBIN:将一个文件包含到当前源文件中,而被包含的文件不进行汇编处理,2019/6/2,1)AREA 用于定义一个代码段或是数据段。 语法格式: AREA sectionname,attr ,attr 其中: sectionname:为所定义的段的名称。 attr:该段的属性。具有的属性为: CODE:定义代码段。 DATA:定义数据段。 READONLY:指定本段

15、为只读,代码段的默认属性。 READWRITE:指定本段为可读可写,数据段的默认属性。,2019/6/2,ALIGN:指定段的对齐方式为2expression。expression的取值为031。 COMMON:指定一个通用段。该段不包含任何用户代码和数据。 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0。 注意:一个大的程序可包含多个代码段和数据段。一个汇编程序至少包含一个代码段。,2019/6/2,2)CODE16和CODE32 CODE16告诉汇编编译器后面的指令序列为16位的Thumb指令。 CODE32告诉汇编编译器后面的指

16、令序列为32位的ARM指令。 语法格式: CODE16 CODE32 注意:CODE16和CODE32只是告诉编译器后面指令的类型,该伪操作本身不进行程序状态的切换。,2019/6/2,例: AREA ChangeState, CODE, READONLY ENTRY CODE32 ;下面为32位ARM指令 LDR R0,=start+1 BX R0 CODE16 ;下面为16位Thumb指令 start MOV R1,#10 . END,;切换到Thumb状态,并跳转到start处执行,2019/6/2,3)ENTRY 指定程序的入口点。 语法格式: ENTRY 注意: 一个程序(可包含多个

17、源文件)中至少要有一个ENTRY(可以有多个ENTRY),但一个源文件中最多只能有一个ENTRY(可以没有ENTRY),2019/6/2,4)ALIGN ALIGN伪操作通过填充0将当前的位置以某种形式对齐。 语法格式: ALIGN expr,offset 其中: expr:一个数字,表示对齐的单位。这个数字是2的整数次幂,范围在20231之间。 如果没有指定expr,则当前位置对齐到下一个字边界处。 Offset:偏移量,可以为常数或数值表达式。不指定offset表示将当前位置对齐到以expr为单位的起始位置。,2019/6/2,例1: short DCB 1 ;本操作使字对齐被破坏 ALI

18、GN ;重新使其为字对齐 MOV R0,1 例2: ALIGN 8 ;当前位置以2个字的方式对齐,2019/6/2,5)END END伪操作告诉编译器已经到了源程序结尾。 语法格式: END 注意: 每一个汇编源程序都必须包含END伪操作,以表明本源程序的结束。,2019/6/2,6)EQU EQU伪操作为数字常量、基于寄存器的值和程序中的标号定义一个字符名称。 语法格式: name EQU expr,type 其中: name:为expr定义的字符名称。 expr:基于寄存器的地址值、程序中的标号、32位的地址常量或者32位的常量。表达式,为常量。 type:当expr为32位常量时,可以使

19、用type指示expr的数据的类型。取值为: CODE32 CODE16 DATA,2019/6/2,例: abcd EQU 2 ;定义abcd符号的值为2 abcd EQU label+16 ;定义abcd符号的值为(label+16) abcd EQU 0x1c,CODE32 ;定义abcd符号的值为绝对地址 ;值0x1c,而且此处为ARM指令,2019/6/2,7)EXPORT及GLOBAL 声明一个源文件中的符号,使此符号可以被其他源文件引用。 语法格式: EXPORT/GLOBAL symbol weak 其中: symbol:声明的符号的名称。(区分大小写) weak:声明其他同名

20、符号优先于本符号被引用。 例: AREA example,CODE,READONLY EXPORT DoAdd DoAdd ADD R0,R0,R1,2019/6/2,8)IMPORT及EXTERN 声明一个符号是在其他源文件中定义的。 语法格式: IMPORT symbolweak EXTERN symbolweak 其中: symbol:声明的符号的名称。,2019/6/2,weak: 当没有指定此项时,如果symbol在所有的源文件中都没有被定义,则连接器会报告错误。 当指定此项时,如果symbol在所有的源文件中都没有被定义,则连接器不会报告错误,而是进行下面的操作。 如果该符号被B或

21、者BL指令引用,则该符号被设置成下一条指令的地址,该B或BL指令相当于一条NOP指令。 其他情况下此符号被设置成0。,2019/6/2,9)GET及INCLUDE 将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 指令格式: GET filename INCLUDE filename 其中: filename:包含的源文件名,可以使用路径信息(可包含空格)。 例:GET d:armfile.s,2019/6/2,10)INCBIN 将一个文件包含到当前源文件中,而被包含的文件不进行汇编处理 指令格式: INCBIN filename 其中: filename:被包含的

22、文件名称,可使用路径信息(不能有空格)。 适用情况:通常使用此伪操作将一个可执行文件或者任意数据包含到当前文件中。 例:INCBIN d:armfile.txt,2019/6/2,例:编写一具有完整汇编格式的程序,实现冒泡法排序功能。设无符号字数据存放在从0x400004开始的区域,字数据的数目字存放在0x400000中。 AREA SORT,CODE,READONLY ENTRY START MOV R1,#0x400000 LP SUBS R1,R1,#1 BEQ EXIT MOV R7,R1 LDR R0,=0x400004 LP1 LDR R2,R0,#4 LDR R3,R0 CMP

23、R2,R3,STRLO R3,R0, # -4 STRLO R2,R0 SUBS R7,R7,#1 BNE LP1 B LP EXIT END,2019/6/2,4.GNU下的伪操作和宏指令,GNU编译环境下的伪操作可分为以下几类: 1) 常量编译控制伪操作 2) 汇编程序代码控制伪操作 3) 宏及条件编译控制伪操作 4) 其他伪操作,2019/6/2,1)常量编译控制伪操作,2019/6/2,)汇编程序代码控制伪操作,2019/6/2,)宏及条件编译控制伪操作,2019/6/2,)其他伪操作,2019/6/2,5.ADS与GNU编译环境下的比较,2019/6/2,2019/6/2,4. AR

24、M ATPCS,1. 基本ATPCS,ATPCS就是ARM程序和Thumb程序中子程序调用的基本规则。ATPCS规定了一些子程序间调用的基本规则。 子程序调用过程中寄存器的使用规则 数据栈的使用规则 参数的传递规则。,2019/6/2,相对于其他类型的ATPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少。 它不能提供以下的支持: 1) ARM程序和Thumb程序相互调用; 2) 数据以及代码的位置无关的支持; 3)子程序的可重入性; 4) 数据栈检查的支持。,2019/6/2,1)寄存器的使用规则 寄存器的使用必须满足下面的规则: 子程序间通过寄存器 R0一R3来传递参数 在子

25、程序中,使用寄存器R4R11来保存局部变量 寄存器R12用作子程序间scratch寄存器(用于保存SP,在函数返回时使用该寄存器出栈),记作ip。在子程序间的连接代码段中常有这种使用规则。,2019/6/2,寄存器R13用作数据栈指针,记作sp。 寄存器R14称为连接寄存器,记作lr。 寄存器R15是程序计数器,记作pc。它不能用作其他用途。,2019/6/2,ATPCS中各寄存器的使用规则及其名称,2019/6/2,2)数据栈使用规则 栈指针通常可以指向不同的位置。当栈指针指向栈顶元素(即最后一个入栈的数据元素)时,称为FULL栈;当栈指针指向与栈顶元素(即最后一个入栈的数据元素)相邻的一个

26、可用数据单元时,称为EMPTY栈。 数据栈的增长方向也可以不同。当数据栈向内存地址减小的方向增长时,称为DESCENDING栈,当数据栈向内存地址增加的方向增长时,称为ASCENDING栈。,2019/6/2,综合这两种特点可以有以下4种数据栈。 FD Full Descending ED Empty Descending FA Full Ascending EA Empty Ascending ATPCS规定数据栈为FD类型,并且对数据栈的操作是8字节对齐的。,2019/6/2,3) 数传递规则 (1)参数个数可变的子程序参数传递规则: 对于参数个数可变的子程序,当参数不超过4个时,可以使用

27、寄存器R0R3来传递参数;当参数超过4个时,还可以使用数据栈来传递参数。 在参数传递时,将所有参数看作是存放在连续的内存字单元中的宇数据。然后,依次将各字数据传送到寄存器R0、Rl、R2、R3中,如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。,2019/6/2,(2)参数个数固定的子程序参数传递规则 对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同。如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递: 各个浮点参数按顺序处理。 为每个浮点参数分配FP寄存器。 分配的方法是,满足该浮点参数需要的且编号最小的一组

28、连续的FP寄存器。第一个整数参数,通过寄存器R0R3来传递。其他参数通过数据栈传递。,2019/6/2,(3)子程序结果返回规则 结果为一个32位的整数时,可以通过寄存器R0返回。 结果为一个64位整数时,可以通过寄存器R0和R1返回,依次类推。 结果为一个浮点数时,可以通过浮点运算部件的寄存器f0、d0或者s0来返回。 结果为复合型的浮点数(如复数)时,可以通过寄存铅f0fn或者d0dn来返回。 对于位数更多的结果,需要通过内存来传递。,2019/6/2,2.ARM和Thumb程序混合使用 在编译和汇编时,使用/interwork告诉编译器生成的目标代码遵守支持ARM程序和Thumb程序混合

29、使用的ATPCS。它用在以下场合: 1) 程序中存在ARM程序调用Thumb程序的情况。 2) 程序中存在Thumb程序调用ARM程序的情况。 3) 需要连接器来进行ARM状态和Thumb状态切换的情况。,2019/6/2,例如:进行状态切换的汇编程序 ARM ADR r0,ThumbProg+1 BX r0 ;跳到ThumbProg,程序切换到Thumb状志 THUMB ;THUMB指示编译器后面的为Thumb指令 ThumbProg: . ADR r0,ARMProg BX r0 ;跳转到ARMProg,程序切换到ARM状态 ARM ;ARM指示编译器后面的为ARM指令 ARMProg:

30、MOV r4, #4,2019/6/2,4. ARM程序设计,. ARM汇编语言程序设计 ARM汇编语言以段(section)为单位组织源文件。 段是相对独立的、具有特定名称的、不可分割的指令或数据序列。 段又可以分为代码段和数据段,代码段存放执行代码,数据段存放代码运行时需要用到的数据。一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段和数据段。,2019/6/2,) ARM汇编中的文件格式 ARM源程序文件(可简称为源文件)可以由任意一种文本编辑器来编写程序代码,它一般为文本格式。在ARM程序设计中,常用的源文件可简单分为以下几种.,2019/6/2,2) ARM汇编语言语句格

31、式 ARM汇编语言语句格式如下所示: symbol instruction | directive | pseudo-instruction;comment 其中: instruction为指令。 directive为伪操作。 pseudo-instrkeuction为伪指令。 symbol为符号。 comment为语句的注释。,2019/6/2,ARM汇编语言中,符号可代表地址、变量和数字常量。数字常量一般有3种表达方式: 十进制数,如79、4等。 十六进制数,以0x和&开头,如0x345、0xFB。 n进制数,用n_XXX表示,如2_01100101、8_5642。 标号:表示程序中的指令

32、或数据地址的符号,代表地址。 局部标号:主要用于局部范围代码。,2019/6/2,)ARM汇编语言程序格式 ADS环境下ARM汇编语言源程序的基本结构: AREA EXAMPLE,CODE,READONLY ENTRY start MOV r0,#10 MOV r1,#3 ADD r0,r0,r1 END 上述程序的程序体部分实现了一个简单的加法运算。,2019/6/2,GNU环境下ARM汇编语言源程序的基本结构: .equ x, 45 /* 定义变量x,并赋值为45*/ .equ y, 64 /* 定义变量y,并赋值为64*/ .equ stack_top, 0x1000 /* 定义栈顶0x

33、1000*/ .global _start .text _start: /*程序代码开始标志*/ MOV sp, #stack_top MOV r0, #x /* x的值放入R0 */ MOV r1, #y /* y的值放入R0 */ ADD r2,r1,r0 /* 求二者之和并放入R1中*/ STR r2, sp /* 将二者之和保存到堆栈中*/ stop: B stop /*程序结束,进入死循环*/ .end,2019/6/2,2. ARM汇编语言程序实例 下面的汇编语言设计的程序是针对某一开发板的LED控制器的设计程序,利用B口的710四个I/O端口做输出,控制四个LED的发光。利用AD

34、S编译生成asm.bin。,2019/6/2,;汇编指令实验 ;定义端口B寄存器预定义 rPCONB EQU 0x56000010 rPDATB EQU 0x56000014 rPUPB EQU 0x56000018 ;禁止PORT B上拉 AREA Init,CODE,READONLY ;该伪指令定义了一个代码段,段名为Init,属性只读 ENTRY ;程序的入口点标识 ResetEntry ;下面这三条语句,主要是用来设置I/O口GPB7为输出属性 ldr r0,=rPCONB ;将寄存器rPCONB的地址存放到寄存器r0中 ldr r1,=0x154000 str r1,r0 ;将r1中

35、的数据存放到寄存器rPCONB中 ;下面这三条语句,主要是禁止GPB端口的上拉电阻 ldr r0,=rPUPB ldr r1,=0xffff str r1,r0 ldr r2,=rPDATB ;将数据端口E的数据寄存器的地址附给寄存器r2,2019/6/2,ledloop ldr r1,=0x700 str r1,r2 ;使GPB7输出低电平,LED1会亮 bl delay ;调用延迟子程序 ldr r1,=0x680 ;使GPB8输出低电平,LED2会亮 str r1,r2 bl delay ldr r1,=0x580 ;使GPB9输出低电平,LED3会亮 str r1,r2 bl delay ldr r1,=0x380 ;使GPB10输出低电平,LED4会亮 str r1,r2 bl delay b ledloop ;不断的循环,2019/6/2,下面是延迟子程序 delay ldr r3,=0xffffff ;设置延迟的时间 delay1 sub r3,r3,#1 ;r3=r3-1 cmp r3,#0x0 ;将r3的值与0相比较 bne delay1 ;比较的结果不为0(r3不为0),继续调用delay1,否则执行下一条语句 mov pc,lr ;返回 END ;程序结束符,2019/6/2,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1