第六章 基于ARM的嵌入式程序设计.

Slides:



Advertisements
Similar presentations
ARM 编程技巧.
Advertisements

第9章 ARM汇编语言程序设计基础.
Oracle数据库 Oracle 子程序.
在PHP和MYSQL中实现完美的中文显示
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
嵌入式系统讲义 第3章 ARM指令系统 周国运
EBNF 请用扩展的 BNF 描述 C语言里语句的结构; 请用扩展的 BNF 描述 C++语言里类声明的结构;
College of Computer Science & Technology
管理信息结构SMI.
第4章 汇编语言程序设计 汇编语言源程序格式 汇编语言上机过程 汇编语言与C语言混合编程技术.
走进编程 程序的顺序结构(二).
网络常用常用命令 课件制作人:谢希仁.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
Zhao4zhong1 (赵中) C语言指针与汇编语言地址.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第十章 IDL访问数据库 10.1 数据库与数据库访问 1、数据库 数据库中数据的组织由低到高分为四级:字段、记录、表、数据库四种。
College of Computer Science & Technology
第二章 Java语言基础.
逆向工程-汇编语言
第五章 C/C++及汇编语言的混合编程 5.1 ARM C/C++编译器 5.2 在C/C++程序中内嵌汇编指令
(第2版).
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
(第2版).
第一章 函数与极限.
第4章 PHP流程控制语句.
第7章 在C/C++中使用汇编 罗文坚 中国科大 计算机学院
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
1.3 C语言的语句和关键字 一、C语言的语句 与其它高级语言一样,C语言也是利用函数体中的可执行 语句,向计算机系统发出操作命令。按照语句功能或构成的不 同,可将C语言的语句分为五类。 goto, return.
C语言程序设计 主讲教师:陆幼利.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
学习目标 1、什么是字符集 2、字符集四个级别 3、如何选择字符集.
$9 泛型基础.
ARM及Thumb指令集 (练习).
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
第3章 ARM微處理器的指令集.
ARM指令集 Author : Steve Furber Advisor: Mei-Ling Chiang Speaker: 徐翔宇
VB与Access数据库的连接.
姚金宇 MIT SCHEME 使用说明 姚金宇
微机原理与接口技术 微机原理与接口技术 朱华贵 2015年11月13日.
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
项目二:HTML语言基础.
Web安全基础教程
第六章 Excel的应用 一、Excel的单元格与区域 1、单元格:H8, D7, IV26等 2、区域:H2..D8, HS98:IT77
第4章 Excel电子表格制作软件 4.4 函数(一).
本节内容 内存复制指令 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第九节 赋值运算符和赋值表达式.
iSIGHT 基本培训 使用 Excel的栅栏问题
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 结构体 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
数据报分片.
Chapter 18 使用GRASP的对象设计示例.
College of Computer Science & Technology
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
临界区问题的硬件指令解决方案 (Synchronization Hardware)
本节内容 C语言的汇编表示 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
Python 环境搭建 基于Anaconda和VSCode.
3. 逻辑运算指令 A、简单逻辑操作指令 CLR A. (不影响CY、AC、 OV标志) CPL A
本节内容 结构体.
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第四节 向量的乘积 一、两向量的数量积 二、两向量的向量积.
本节内容 进程 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
顺序结构程序设计 ——关于“字符串”和数值.
<编程达人入门课程> 本节内容 有符号数与无符号数 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
实验六、COM类型病毒分析实验 实验开发教师: 刘乃琦 谌黔燕.
编译原理实践 6.程序设计语言PL/0.
学习目标 1、什么是列类型 2、列类型之数值类型.
Presentation transcript:

第六章 基于ARM的嵌入式程序设计

6.1 ARM汇编语言的伪操作、宏指令与伪指令 6.1.1 两种常见的ARM编译开发环境 6.1.2 ADS编译环境下的伪操作和宏指令 6.1.3 GNU编译环境下的伪操作和宏指令 6.1.4 ARM汇编语言的伪指令

ARM汇编语言的伪操作、宏指令与伪指令 伪操作——为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编过程起作用,不参与程序运行。 宏指令——通过伪操作定义的一段独立的代码。在调用它时将宏体插入到源程序中。 伪指令——是汇编语言程序里的特殊指令助记符,在汇编时被合适的机器指令替代。

6.1.1两种常见的ARM编译开发环境 ADS/SDT IDE开发环境:它由ARM公司开发,使用了CodeWarrior公司的编译器; EmbestIDE开发环境:集成了GNU开发工具的IDE开发环境,由GNU的汇编器as、交叉编译器gcc、和链接器ld等组成。 这两种开发环境的编译器都完全支持ARM指令集,但伪指令不同,代码风格不同。

ADS编译环境下的伪操作可分为以下几类: 符号定义(Symbol Definition)伪操作 数据定义(Data Definition)伪操作 汇编控制(Assembly Control)伪操作 信息报告(Reporting)伪操作 其他(Miscellaneous)伪操作

符号定义伪操作 GBLA,GBLL,GBLS:声明全局变量。 LCLA,LCLL,LCLS:声明局部变量。 SETA,SETL,SETS:给变量赋值。 RLIST:为通用寄存器列表定义名称。

用于声明一个ARM程序中的全局变量,并将其初始化。 1、GBLA,GBLL,GBLS 用于声明一个ARM程序中的全局变量,并将其初始化。 GBLA:声明一个全局算术变量,并初始化成0。 GBLL:声明一个全局逻辑变量,并初始化成{FALSE}。 GBLS:声明一个全局串变量,并初始化成空串“”。 语法格式: <gblx> variable 全局变量的作用范围为:包含该变量的源程序,全局变量名称在作用范围内必须唯一。

用于声明一个ARM程序中的局部变量,并将其初始化。 2、LCLA,LCLL,LCLS 用于声明一个ARM程序中的局部变量,并将其初始化。 LCLA:声明一个局部算术变量,并初始化成0。 LCLL:声明一个局部逻辑变量,并初始化成{FALSE}。 LCLS:声明一个局部串变量,并初始化成空串“”。 语法格式: <lclx> variable 局部变量的作用范围为:包含该局部变量的宏代码的一个实例

variable <setx> expression expression:赋给变量的值。 3、 SETA,SETL,SETS 用于给ARM程序中的变量赋值。 SETA:给一个算术变量赋值。 SETL:给一个逻辑变量赋值。 SETS:给一个串变量赋值。 语法格式: variable <setx> expression expression:赋给变量的值。 在向变量赋值前,必须先声明该变量。

例: GBLS s1 GBLS s2 LCLS s3 S1 SETS “strings1” S2 SETS “strings2” S3 SETS s1:CC:S2 GBLL logic logic SETL {TRUE} LCLA arithmetic arithmetic SETA 0xff ;声明一个全局串变量s1 ;声明一个全局串变量s2 ;声明一个局部串变量s3 ; 串变量s1赋值为“strings1” ; 串变量s2赋值为” strings2” ; 串变量s3赋值 ;声明一个全局逻辑变量logic ; 变量logic赋初值为{TRUE} ;声明一个局部算术变量 ; 变量arithmetic赋初值为oxff

为一个通用寄存器列表定义名称。定义的名称可以在LDM/STM指令中使用。 语法格式: 4、RLIST 为一个通用寄存器列表定义名称。定义的名称可以在LDM/STM指令中使用。 语法格式: name RLIST {list-of-registers} name:寄存器列表名称。 {list-of-registers}:通用寄存器列表。 例: context RLIST {R0-R6} ;将寄存器列表名称定义为context LDMDF SP! ,context ;加载寄存器列表

数据定义伪操作 LTORG:声明一个数据缓冲池的开始。 SPACE:分配一块内存单元,并用0初始化。 MAP:定义一个结构化的内存表的首地址。 FIELD:定义结构化内存表中的一个数据域。 DCB:分配一段字节内存单元,并初始化。 DCD、DCDU:分配一段字内存单元,并初始化。

用于声明一个数据缓冲池(文字池)的开始。 语法格式: LTORG 例:start BL func …… func LDR R1,=0x8000 ;子程序 MOV PC,LR ;子程序返回 LTORG ;定义数据缓冲池&0x8000 Data SPACE 4200 ;从当前位置开始分配4200字节的内 存单元,并初始化为0。 END 默认数据缓冲池为空

注意: LTORG伪操作通常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器不会错误地将数据缓冲池中的数据当作指令来执行。 通常ARM汇编编译器把数据缓冲池放在代码段的最后面,即下一个代码段开始之前,或者END伪操作之前。

2、SPACE——也可以用符号“%”表示 用于分配一块连续的内存单元供程序使用,并且将这个内存单元的内容初始化为0。 语法格式: {label} SPACE expr 或 {label} % expr 其中: {label} :是一个标号,可选项。 expr:数值表达式,用来规定内存单元的字节数。 例: AREA DataSpace,Data,READWRITE data1 SPACE 256 ;定义大小为256字节的数据区

3、MAP、FIELD 使用MAP和FIELD伪操作描述数据结构。 MAP用于定义数据结构的起始地址; FIELD用于定义结构中的字段(各数据域的字节长度),并可为每一个数据域指定一个标号,其它指令可引用此标号。 注: MAP和FIELD伪操作只是定义数据结构并不实际分配内存单元。

MAP expr {,base-register} 或 ^ expr {,base-register} 其中: 语法格式: MAP expr {,base-register} 或 ^ expr {,base-register} 其中: expr:数据表达式或程序中的标号(使用MAP之 前已定义)。 base-register:基址寄存器 若指令中没有此项时,expr为结构的首地址。(基于绝对地址的数据结构) 若指令中包含此项时,expr+base-register的和为结构首地址。(基于相对地址的数据结构)

例: MAP 0xC0008 ^ datalabel+64 MAP 0x10,R9 ;数据结构存放的起始地址是0xC0008

(2)FIELD ——也可以用符号”#”表示 用户定义数据结构中的字段。 语法格式: {label} FIELD expr 或 {label} # expr 其中: {label}:字段的名称(地址标号)。 expr: 此字段在数据结构中所占的字节数。

由MAP和FIELD伪操作配合定义的数据结构有3种: 基于绝对地址的数据结构 基于寄存器相对偏移的数据结构 基于程序相对偏移的数据结构(基于PC)。 例1:基于绝对地址—首地址固定 MAP 0x200 ;内存的首地址为0x200 a FIELD 4 ;字段a长度为4,相对位置为0 b FIELD 4 ;字段b长度为4,相对位置为4 x FIELD 8 ;字段x长度为8,相对位置为8 y FIELD 8 ;字段y长度为8,相对位置为16 s FIELD 16 ;字段s长度为16,相对位置为24 引用结构中的数据: LDR R0,b

ADR R9,datastart ; datastart是数据起始地址 例2:基于寄存器相对偏移—首地址基于基址寄存器 MAP 0,R9 ;内存的首地址为R9寄存器的值 a FIELD 4 ;字段a长度为4,相对位置为0 b FIELD 4 ;字段b长度为4,相对位置为4 x FIELD 8 ;字段x长度为8,相对位置为8 y FIELD 8 ;字段y长度为8,相对位置为16 s FIELD 16 ;字段s长度为16,相对位置为24 可通过下面的指令访问数据结构中的信息: ADR R9,datastart ; datastart是数据起始地址 LDR R0, b ;LDR R0,[R9,#4] 通过在ADR指令中指定不同的基址寄存器的值,定义的数据结构可在程序中有多个实例。

LDR R0, b ;LDR R0, Datastruc+4 例3:基于程序相对偏移—首地址基于PC Datastruc SPACE 280 ;分配280字节的内存单元 MAP Datastruc ;内存的首地址为Datastruc内存单元 a FIELD 4 ;字段a长度为4,相对位置为0 b FIELD 4 ;字段b长度为4,相对位置为4 x FIELD 8 ;字段x长度为8,相对位置为8 y FIELD 8 ;字段y长度为8,相对位置为16 s FIELD 256 ;字段s长度为16,相对位置为24 可通过下面的 指令访问数据结构中的信息: LDR R0, b ;LDR R0, Datastruc+4

例:判断当前内存的使用情况是否超过程序分配的可用内存的方法。 startofmem EQU 1000 ;分配内存首地址 endofmem EQU 2000 ;分配内存末地址 MAP startofmem ;内部首地址为startofmem a FIELD 4 ;字段a长度为4,相对位置为0 b FIELD 4 ;字段b长度为4,相对位置为4 x FIELD 8 ;字段x长度为8,相对位置为8 y FIELD 8 ;字段y长度为8,相对位置为16 s FIELD max ;字段s长度为max,相对位置为24 endofstru FIELD 0 ;endofstru用于检查内存是否越界 ASSERT endofstru<=endofmem

用于定义并且初始化一个或者多个字节的内存区域。 语法格式: 4、DCB——也可以用符号”=”表示 用于定义并且初始化一个或者多个字节的内存区域。 语法格式: {label} DCB expr{,expr}…… 或 {label} = expr{,expr} 其中: expr表示: -128到255之间的一个数值常量或者表达式。 一个字符串。 当DCB后面紧跟一个指令时,可能需要使用ALIGN确保指令是字对齐的。

short DCB 1 ;为short分配了一个字节,并初始 string DCB “string”,0 ;构造一个以0结尾的字 例: short DCB 1 ;为short分配了一个字节,并初始 化为1。 string DCB “string”,0 ;构造一个以0结尾的字 符串

用于分配一段字内存单元(分配的内存单元都是字对齐的)并初始化。 语法格式: 5、DCD、DCDU (1)DCD ——也可以用符号”&”表示 用于分配一段字内存单元(分配的内存单元都是字对齐的)并初始化。 语法格式: {label} DCD expr{,expr}…… 或 {label} & expr{,expr}…… 其中: expr:数字表达式或程序中的标号。 DCD伪操作可能在分配的第一个内存单元前插入填补字节以保证分配的内存是字对齐的。

例: data1 DCD 2,4,6 ;为data1分配三个字,内容初始化为2,4,6 data2 DCD label+4 ;初始化data2为label+4对应的地址 (2)DCDU DCDU与DCD的不同之处在于DCDU分配的内存单元并不严格字对齐。

汇编控制伪操作 IF,ELSE及ENDIF WHILE及WEND MACRO,MEND及MEXIT

IF,ELSE及ENDIF伪操作能够根据条件把一段源代码包括在汇编语言程序内或者将其排除在程序之外。 语法格式: IF logic expression; logic expression控制选择逻辑表达式 …… ;指令或伪指令代码段1 {ELSE ;可选 …… ;指令或伪指令代码段2 } ENDIF IF、ELSE及ENDIF伪操作可以嵌套使用

例: IF Variable=16 ;如果Variable=16成立,则编译下面代码 BNE SUB1 LDR R0,=SUB0 BX R0 ELSE ;否则编译下面代码 BNE SUB0 BX R1 ENDIF

WHILE及WEND伪操作能够根据条件重复汇编相同的一段源代码。 语法格式: WHILE logic expression instructions or derectives WEND WHILE和WEND伪操作可以嵌套使用

例: count SETA 1 ;设置循环计数变量count初始值为1 WHILE count<=4 ;由count控制循环执行的次数 …… ;代码 WEND ;结束

3、MACRO、MEND及MEXIT MACRO:标识宏定义的开始。 MEND:标识宏定义的结束。 MEXIT:用于从宏中跳转出去。 宏体代表了一个预定义的汇编语言指令序列。在汇编程序中通过宏的名称调用宏,编译时,宏语句被展开。

{$label} macroname {$parameter{, $parameter}..} 语法格式: MACRO {$label} macroname {$parameter{, $parameter}..} ;code …… MEND 其中: {$label}:在宏被展开时,label可被替换成相应的符号。 macroname:多定义的宏的名称。 $parameter:宏指令的参数。

在程序中调用此宏: exam jump sub,det 例:(示例26) MACRO $label jump $a1,$a2 …… $label.loop1 BGE $label.loop1 $label.loop2 BL $a1 BGT $label.loop2 ADR $a2 MEND …… examloop1 …… BGE examloop1 examloop2 BL sub BGT examloop2 …… ADR det

例: MACRO $abc macroabc $param1,$param2 ;code IF condition1 MEXIT ;从宏中跳出 ELSE ENDIF MEND 子程序比较短,而需要传递的参数比较多是可以使用宏汇编技术。

其他伪操作 1、CODE16和CODE32 CODE16告诉汇编编译器后面的指令序列为16位的Thumb指令。 CODE32告诉汇编编译器后面的指令序列为32位的ARM指令。 语法格式: CODE16 CODE32 CODE16和CODE32只是告诉编译器后面指令的类型,该伪操作本身不进行程序状态的切换。

AREA ChangeState, CODE, READONLY ENTRY CODE32 ;下面为32位ARM指令 例: AREA ChangeState, CODE, READONLY ENTRY CODE32 ;下面为32位ARM指令 LDR R0,=start+1 BX R0 …… CODE16 ;下面为16位Thumb指令 start MOV R1,#10 ……. END ;切换到Thumb状态,并跳转到start处执行

EQU伪操作为数字常量、基于寄存器的值和程序中的标号定义一个字符名称。 语法格式: name EQU expr{,type} 其中: name:为expr定义的字符名称。 type:当expr为32位常量时,可以使用type指示expr的数据的类型。取值为: CODE32 CODE16 DATA

;定义abcd符号的值为(label+16) abcd EQU 0x1c,CODE32 例: abcd EQU 2 ;定义abcd符号的值为2 abcd EQU label+16 ;定义abcd符号的值为(label+16) abcd EQU 0x1c,CODE32 ;定义abcd符号的值为绝对地址 ;值0x1c,而且此处为ARM指令

AREA sectionname{,attr} {,attr}… 其中: 用于定义一个代码段或是数据段。 语法格式: AREA sectionname{,attr} {,attr}… 其中: sectionname:为所定义的段的名称。 attr:该段的属性。具有的属性为: CODE:定义代码段。 DATA:定义数据段。 READONLY:指定本段为只读,代码段的默认属性。 READWRITE:指定本段为可读可写,数据段的默认属性。

ALIGN=expression:指定段的对齐方式为2expression。expression的取值为0~31。 ASSOC=section:指定与本段相关的ELF段。 COMDEF:定义一个通用的段。该段可以包含代码和数据。在某个源文件中,同名的COMDEF段必须相同。 COMMON:定一个通用段。该段不包含任何用户代码和数据。 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0。 一个大的程序可包含多个代码段和数据段。一个汇编程序至少包含一个代码段。

4、ENTRY 指定程序的入口点。 语法格式: ENTRY 注意: 一个程序(可包含多个源文件)中至少要有一个ENTRY(可以有多个ENTRY),但一个源文件中最多只能有一个ENTRY(可以没有ENTRY)

5、END END伪操作告诉编译器已经到了源程序结尾。 语法格式: END 注意:   每一个汇编源程序都必须包含END伪操作,以表明本源程序的结束。

ALIGN伪操作通过填充0将当前的位置以某种形式对齐。 语法格式: ALIGN {expr{,offset}} 其中: expr:一个数字,表示对齐的单位。这个数字是2的整数次幂,范围在20~231之间。(如果没有指定expr,则当前位置对齐到下一个字边界处。) offset:偏移量,可以为常数或数值表达式。 不指定offset表示将当前位置对齐到以expr为单位的起始位置。

例1: short DCB 1 ;本位操作使字对齐被破坏 ALIGN ;重新使其为字对齐 MOV R0,1 例2: ALIGN 8 ;当前位置以2个字的方式对齐

声明一个源文件中的符号,使得此符号可以被其他源文件引用。 语法格式: EXPORT/GLOBAL symbol {[weak]} 其中: 例: AREA example,CODE,READONLY EXPORT DoAdd DoAdd ADD R0,R0,R1

IMPORT symbol{[weak]} EXTERN symbol{[weak]} 其中: 8、IMPORT及EXTERN 声明一个符号是在其他源文件中定义的。 语法格式: IMPORT symbol{[weak]} EXTERN symbol{[weak]} 其中: symbol:声明的符号的名称。

[weak]: 当没有指定此项时,如果symbol在所有的源文件中都没有被定义,则连接器会报告错误。 1、如果该符号被B或者BL指令引用,则该符号被设置成下一条指令的地址,该B或BL指令相当于一条NOP指令。 2、其他情况下此符号被设置成0。

将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 指令格式: GET filename 9、GET及INCLUDE 将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 指令格式: GET filename INCLUDE filename 其中: filename:包含的源文件名,可以使用路径信息(可包含空格)。 例:GET d:\arm\file.s

将一个文件包含到当前源文件中,而被包含的文件不进行汇编处理 指令格式: INCBIN filename 其中: 通常使用此伪操作将一个可执行文件或者任意数据包含到当前文件中。 例:INCBIN d:\arm\file.txt

6.1.3 GNU编译环境下的伪操作和宏指令 GNU编译环境下的伪操作可分为以下几类: 常量编译控制伪操作 汇编程序代码控制伪操作 宏及条件编译控制伪操作 其他伪操作

常量编译控制伪操作 伪操作 语法格式 作 用 .byte .byte expr {,expr} … .hword/.short .hword expr {,expr} … 分配一段半字内存单元,并用expr初始化。 .ascii .ascii expr {,expr} … 定义字符串expr(非零结束符)。 .asciz /.string .asciz expr {,expr} … 定义字符串expr(以/0为结束符)。 .float/.single .float expr {,expr} … 定义一个32bit IEEE 浮点数expr。 .double .double expr {,expr} … 定义64bit IEEE浮点数expr。 .word/.long /.int .word expr {,expr} … 分配一段字内存单元,并用expr初始化。 .fill .fill repeat {,size}{,value} 分配一段字节内存单元( repeat个size长度的内存单元),用value初始化每个内存单元。 .zero .zero size 分配一段字节内存单元,并用0填充内存。 .space/.skip .space size {, value} 分配一段内存单元,用value将内存单元初始化。

字符编译控制伪操作 伪操作 语法格式 .equ/.set .equ symbol, expr .set symbol, expr 作用 .equ/.set .equ symbol, expr .set symbol, expr 为一个常量、标号等定义一个字符名称 例:.equ rPLLCON, 0x01d80000 .equ zhen, “student” .global/.globl .global symbol 定义本模块中一个可被其它文件引用的全局变量 例: .global Func .extern .extern symbol 声明本文件中要使用的其它文件中的全局变量(亦可不声明) 例: .extern Func

汇编程序代码控制伪操作 伪操作 语法格式 作 用 .section .section expr 定义域中包含的段。 .text .text {subsection} 将操作符开始的代码编译到代码段或代码段子段。 .data .data {subsection} 将操作符开始的数据编译到数据段或数据段子段。 .bss .bss {subsection} 将变量存放到.bss段或.bss段的子段。 .code 16/.thumb .code 16 .thumb 表明当前汇编指令的指令集选择Thumb指令集。 .code 32/.arm .code 32 .arm 表明当前汇编指令的指令集选择ARM指令集。 .end 标记汇编文件的结束行,即标号后的代码不作处理。 .include .include “filename” 将一个源文件包含到当前源文件中。 .align/.balign .align {alignment} {,fill} {,max} 通过添加填充字节使当前位置满足一定的对齐方式。

宏及条件编译控制伪操作 伪操作 语法格式 作 用 .macro、.exitm及.endm .macro acroname{parameter{, parameter}…} … .endm .macro伪操作标识宏定义的开始,.endm标识宏定义的结束。用.macro及.endm定义一段代码,称为宏定义体。.exitm伪操作用于提前退出宏。 .ifdef,.else及.endif .ifdef condition .else .endif 当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。其中else可以缺省。

例:req count, 7 ;定义R7 为count 其他伪操作 .ltorg 在当前段(一般为代码段)的当前地址(字对齐)产生一个文字池。一般放在一段程序的后面。  例: mov pc, lr src: .long 1,2,3,4,5 dst: .long 0,0,0,0 .req name,expr 为一个特定的寄存器定义名称。 例:req count, 7 ;定义R7 为count

6.1.4 ARM汇编语言的伪指令 ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替。ARM伪指令有四条,分别是: ADR:小范围的地址读取伪指令。 ADRL:中等范围的地址读取伪指令。 LDR:大范围的地址读取伪指令。 NOP:空操作伪指令。

1、ADR——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现此ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 语法格式: ADR{cond} register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围是参考P212

…… 例1: …… ADD R1,PC,#0x3C (0x20) ADR R1,Delay Delay MOV R0,R14 编译后的反汇编代码: …… ADD R1,PC,#0x3C MOV R0,R14 例1: …… (0x20) ADR R1,Delay Delay (0x64) MOV R0,R14 PC+0x3C =0x20+0x08+0x3C =0x64 使用ADR将程序标号Delay所表示的地址存入R1。

例2:查表 ADR R0,D_TAB ;加载转换表地址 LDRB R1,[R0,R2] ;使用R2作为参数,进行查表 …… D_TAB DCB 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92

2、ADRL——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。在汇编编译器编译源程序时,ADRL被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 语法格式: ADRL{cond} register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围参考P212

…… 例: …… ADD R1,PC,#0x3C (0x20) ADRL R1,Delay ADD R1,R1,#0 Delay 编译后的反汇编代码: …… ADD R1,PC,#0x3C ADD R1,R1,#0 MOV R0,R14 例: …… (0x20) ADRL R1,Delay Delay (0x64) MOV R0,R14 使用ADRL将程序标号Delay所表示的地址存入R1。 ADRL伪指令被汇编成两条指令,尽管第2条指令并没有意义。

3、LDR ——大范围的地址读取 LDR伪指令用于加载32位立即数或一个地址值到指定的寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超过MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 语法格式: LDR{cond} register,=expr 其中: Register:加载的目标寄存器。 expr:32位常量或地址表达式。

编译后的反汇编代码: …… 例: …… LDR R1,stack (0x060) LDR R1,=Delay Delay MOV R0,R14 LTORG stack DCD 0x102 例: …… (0x060) LDR R1,=Delay Delay (0x102) MOV R0,R14 使用LDR将程序标号Delay所表示的地址存入R1。 LDR伪指令被汇编成一条LDR指令,并在文字池中定义一个常量,该常量为标号Delay的地址。

注意: 从指令位置到文字池的偏移量必须小于4KB。 与ARM指令的LDR相比,伪指令LDR的参数有“=”号。

NOP伪指令在汇编时将被替代成ARM中的空操作,比如可能是“MOV R0,R0”指令等。 NOP可用于延时操作。 语法格式: NOP 例: Delay NOP ;空操作 NOP SUBS R1,R1,#1 ;循环次数减1 BNE Delay MOV PC,LR

6.2 ARM汇编语言程序设计 一、ARM汇编中的文件格式 源程序文件 文件名 说 明 汇编程序文件 *.S 用ARM汇编语言编写的ARM程序或Thumb程序。 C程序文件 *.C 用C语言编写的程序代码。 头文件 *.H 为了简化源程序,把程序中常用到的常量命名、宏定义、数据结构定义等等单独放在一个文件中,一般称为头文件。

二、ARM汇编语言语句格式 ARM汇编语言语句格式为: 其中: symbol:标号 instruction:指令 directive:伪操作 {symbol}{instruction|direction|pseudo-instruction} {;comment} 其中: symbol:标号 instruction:指令 directive:伪操作 pseudo-instruction:伪指令 comment:语句的注释

书写规则: 指令、伪操作和伪指令的助记符可全部用大写字母,也可全部用小写字母,但不能在一个助记符中即用大写字母又用小写字母。 标号严格区分大小写。 标号必须在一行的顶格书写,而所有指令均不能顶格书写。 如果一条语句很长,可使用“\”将长语句分成若干行来写。

例:符合规则的例子

例:不符合规则的例子 start MOV R0,#1 ABC: MOV R1,#2 MOV R2,#3 Loop MOV R2,#3 B loop

ARM汇编语言是以段(section)为单位来组织源文件的。 段是相对独立的、具有特定名称的、不可分割的指令或者数据序列。 段又可以分为代码段和数据段,代码段存放执行代码,数据段存放代码运行时需要用到的数据。 一个ARM源程序至少需要一个代码段,大的程序可以包含多个代码段和数据段。

举例说明ARM汇编语言源程序的基本结构 .global _start .text _start MOV r0,#10 MOV r1,#3 ADD r0,r0,r1 .end 本程序的程序体部分实现了一个简单的加法运算。