ARM教材第5章ARM汇编程序设计.docx

上传人:b****3 文档编号:5443849 上传时间:2022-12-16 格式:DOCX 页数:21 大小:27.37KB
下载 相关 举报
ARM教材第5章ARM汇编程序设计.docx_第1页
第1页 / 共21页
ARM教材第5章ARM汇编程序设计.docx_第2页
第2页 / 共21页
ARM教材第5章ARM汇编程序设计.docx_第3页
第3页 / 共21页
ARM教材第5章ARM汇编程序设计.docx_第4页
第4页 / 共21页
ARM教材第5章ARM汇编程序设计.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

ARM教材第5章ARM汇编程序设计.docx

《ARM教材第5章ARM汇编程序设计.docx》由会员分享,可在线阅读,更多相关《ARM教材第5章ARM汇编程序设计.docx(21页珍藏版)》请在冰豆网上搜索。

ARM教材第5章ARM汇编程序设计.docx

ARM教材第5章ARM汇编程序设计

第5章ARM汇编程序设计

ARM编译器,如ADS集成开发环境,一般都支持汇编语言的程序设计。

本章介绍ARM程序设计的一些基本概念,如ARM汇编语言的伪指令、汇编语言的语句格式和汇编语言的程序结构等到,并在些基础上介绍一些常用的ARM汇编子程序的设计。

4.1ARM伪指令

ARM汇编程序由汇编指令、伪指令和宏指令组成,伪指令不介汇编指令那样在处理器的运行期间执行,而是在汇编器对汇编程序进行汇编时处理。

宏是一段独立的汇编程序代码,它是通过伪指令定义的,在程序中宏指令即调用宏指令。

当程序被汇编时,汇编程序对每个宏调用进行展开,用宏定义代汇编程序中的宏指令。

由于指令也发球汇编伪指令的一部分,因此本书将宏指令放在汇编伪一起介绍。

与单片机汇编程序设计一样,在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,它们没有相对应的操作友码,通常称这些特殊指令助记符为伪指令,它们所完成的操作称为伪操作。

伪指令在源程序中的作用是为完成汇编程序做各种准备工作,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成了。

在ARM的光荣称号程序中,有如下几种伪指令:

符号定义伪指令、数据定义伪指令、汇编控制伪指令以及其他伪指令。

4.1.1符号定义(SymbolDefinition)伪指令

符号定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等。

常见的符号定义伪指令有以下几种:

●用于宝玉局变量的GBLA、GBLL和GBLS;

●用于定义局部变量的LCLA、SETL、LCLS;

●用于对变量赋值的SETA、SETL、SETS;

●为通用寄存器列表定义名称的RLIST;

●为一个协处理器的寄存器定义名称的伪指令CN;

●为一个协处理器定义名称的伪指令CP;

●为一个CFP寄存器定义名称的伪指令DN和SN;

●为一个FPA浮点寄存器定义名称的伪指令FN。

1.GBLA、GBLL和GBLS

语法格式:

GBLA(GBLL或GBLS)全局变量名

GBLA、GBLL和GBLS伪指令用于定义一个ARM程序中的全局变量,并半其初始化。

其中:

GBLA伪指令用于定义一个全局的数字变量,并初始化为0;

GBLL伪指令用于定义一个全局的逻辑变量,并初始化为F(假);

GBLS伪指令用于定义一个全局的字符串变量,并初始化为空。

由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。

使用示例:

GBLANumber1;定义一个全局的数字变量,变量名为Number1

Number1SETA0xaa;将Number1变量赋值为0xaa

GBLLTrue1;定义一个全局的逻辑变量,变量名为True1

True1SETL{TRUE};将True1变量赋值为真

GBLSString1;定义一个全局的字符串变量,变量名为String1

String1SETS“Testing”;将String1变量赋值为“Testing”

2.LCLA、LCLL和LCLS

语法格式:

LCLA(LCLL或LCLS)局部变量名

LCLA、LCLL和LCLS伪指令用于定义一个ARM程序中的局部变量,并将其初始化,其中:

●LCLA伪指令用于定义一个局部的数字变量,并初始化为0;

●LCLL伪指令用于定义一个局部的逻辑变量,并初始化为F(假);

●LCLS伪指令用于定义一个局部的字符串变量,并初始化为空。

以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。

使用示例:

LCLANumber2;声明一个局部的数字变量,变量名为Number2

Number2SETA0xaa;将Number2变量赋值为0xaa

LCLLLogic2;声明一个局部的逻辑变量,变量名为Logic2

Logic2SETL{TRUE};将Logic2变量赋值为真

LCLSString2;定义一个局部的字符串变量,变量名为String2

String2SETS“Testing”;将String2变量赋值为“Testing”

3.SETA、SETL和SETS

语法格式:

变量名SETA(SETL或SETS)表达式

伪指令SETA、SETL、SETS用于给一个已经定义的全局变量或局部变量赋值。

●SETA伪指令用于给一个数学变量赋值;

●SETL伪指令用于给一个逻辑变量赋值;

●SETS伪指令用于给一个字符串变量赋值。

其中,变量名是已经定义地的全局变量或局部变量,表达式是将要赋给变量的值。

使用示例:

LCLANumber3;声明一个局部的数字变量,变量名为Number3

Number3SETA0xaa;将Number3变量赋值为0xaa

LCLLLogic3;声明一个局部的逻辑变量,变量名为Logic3

Logic3SETL{TRUE}了;将Logic3变量赋值为真

4.RLIST

语法格式:

名称RLIST{寄存器列表}

RLIST伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在ARM指令LDM/STM中使用。

在LDM/STM指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。

使用示例:

RegListRLIST{R0-R5,R8,R10};将寄存器列表名称定义为RegList,可在ARM

;指令LDM/STM中通过该名称访问寄存器列表

STMDSP!

RegList;保存寄存器列表RegList到堆栈

由于在编程过程中,协处理器汇编伪指令使用的情况比较少,因此本书不对CP、DN和SN以及FN等协处理器伪指令进行介绍。

4.1.2数据定义(DATADefinition)伪指令

数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成对已分配存储单元的初始化。

常见的数据定义伪指令有如下几种:

●DCB用于分配一片连续的字节存储单元并用指定的数据初始化;

●DCW(DCWU)用于分配一片连续的半字节存储单元并用指定的数据初始化;

●DCD(DCDU)用于分配一片连续的字存储单元并用指定的数据初始化;

●DCFS(DCFSU)用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始化;

●DCQ(DCQU)用于分配一片以8字节个为单位的连续的存储单元并用指定的数据初始化;

●DCDO用于分配一段字的内存单元,将每个单元的内容初始化为该单元相对于基址寄存器的偏移量;

●DCI用于分配一段字的内丰单元,并用单精度的浮点数据初始化,指定内存单元存放的是代码,而不是数据;

●SPACE用于分配一片连续的存储单元;

●MAP用于定义一个结构化的内存表首地址;

●FIELD用于定义一个结构化的内在表的数据域;

●LTORG用于声明一个文字池。

1.语法格式:

标号DCB表达式

DCB伪指令用于分配一片连续的字节存储单元并用伪指令中的表达式初始化。

其中,表达式可以为0—255的数字或字符吕,DC也可用“=”代替。

使用示例:

标号DCB表达式

DCB伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。

其中,表达式可以为0—255的数字或字符串,DCB也可用“=”代替。

使用示例:

StringDCB“Thisisatest!

”;分配一片连续的字节存储单元并初始化

ParameterDCB0x33,0x44,0x55

DCB-1,-2,0,1,2,;分配一片连续的字节存储单元并初始化

2.DCW(或DCWU)

语法格式:

标号DCW(或DCWU)表达式

DCW(或DCWU)伪指令用于为双精度的浮点数分配一片连续的字节存储单元,并用伪指令中指定的表达式初始化。

每个双精度的浮点数占据两个字单元,用DCFD分配的字存储单元是字对齐的,而用DCFDU分配的字存储单元并不严格字对齐。

使用示例:

FdataDCFD0,2E115。

-5E7;分配一片连续的字存储单元并初始化为指定的双精度数

5.DCFS(或DCFSU)

语法格式:

标号DCFS(或DCFSU)表达式

DCFS(或DCFSU)伪指令用于为单精度的浮点数分配一片连续的字存储单元,并用伪指令中指定的表达式初始化。

每个单精度的浮点数占据一个字单元,用DCFS分配的字存储单元是字对齐的,而用DCFSU分配的字存储单元并不严格对齐。

使用示例:

SdataDCFS1,2E5,-5E7;分配一片连续的字存储单元并初始化为指定的单精度数

6.DCQ(或DCQU)

语法格式:

标号DCQ(或DCQU)表达式

DCQ(或DCQU)伪指令用于分配一片以8个字节为单位的连续存储区域,并用伪指令中指定的表达式初始化。

用DCQ分配的存储单元是字对齐的,而用DCQU分配的存储单元并不严格对齐。

使用示例:

DataDCQ100,1000;分配一片连续的存储单元并初始化为指定的值

7.DCDO

语法格式:

标号DCDO表达式

DCDO用于分配一段字内存单元,并将每个单元的内容初始化为该单元相对于表态基址寄存器的偏移量。

DCDO伪指令作为表态基址寄存器R9的偏移量分配内在单元,该指令需要内在字对齐。

使用示例:

IMPORTexternsys

DataDCDOexternnsys;分配32位的字单元,其值勤为标号externnsys基于R9的偏移量

8.DCI

语法格式:

标号DCI表达式

DCI用于分配一段字节的内在单元,并用伪指令中指定的表达式初始化。

指定内在单元存放的是代码而不是数据,在Thumb代码中,DCI分配的是半字节的内存代码单元。

使用示例:

MACRO;这个宏指令将指令newinstrRd,Rm定义为相应的机器指令

Newinstr$Rd,$Rm

DCI0Xe15f0f10:

CR:

(8$Rd:

SHL:

12):

OR;$Rm;这是存放的是指令MEND

9.SPACE

语法格式:

标号SPACE表达式

SPACE伪指令用于分配一片连续的存储区域并初始化为0。

其中,表达式是要分配的字节数,SPACE也可用“%”代替。

使用示例:

DataSpaceSPACE1000;分配连续1000B的存储单元并初始化为0

10.MAP

语法格式:

MAP表达式{,基址寄存器}

MAP伪指令用于定义一个结构化的内存表的首地址,MAP也可用“^”代替。

表达式可以是程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。

MAP伪指令通常与FIELD伪指令配合使用来定义结构化的内存表。

使用示例:

MAP0x10,R0;定义结构化内存表首地址的值为0x10+R0

11.FIELD

语法格式:

标号FIELD表达式

FIELD伪指令用于定义一个结构化内存表中的数据域。

FIELD也可用“#”代替,表达式的值是当前数据域在内存表中所占的字节数。

FIELD伪指令常与MAP伪指令配合使用来定义结构化的内存表,MAP伪指令定义内存表的首地址,FIELD伪指令定义内存表中的各个数据域,并可以为每个数据域指定一个标号供其他的指令引用。

注意MAP和FIELD伪指令仅用于定义数据结构,并不实际分配存储单元。

使用示例:

MAP0x100;定义结构化内存表首地址的值为为0x100

AFIELD16;定义A的长度为16B,位置为0x100

BFIELD32;定义B的长度为32B,位置为0x110(0x100的存放了

;16个字节)

SFIELD256;定义S的长度为256B,位置为0x130(0x100后存放了

;32个字节)

12.LTORG

语法格式:

LTORG

LTORG用于声明一个文字池。

在使用LDR伪指令时,要在适当的地址加入LTORG声明文字池,这样就会把要加载的数据保存在文字池中,再用ARM的加载指令读出数据。

如果没有使用LTORG声明文字池,则汇编器会在程序末尾自动声明,使用LTORG声明文字池的目的可以在程序代码的任何位置存储加载的数据。

使用示例:

LDRR0,=0x12345

ADDR1,R1,R0

MOVPC,LR

LTORG;声明文字池,此处存放0x12345

…;其他代码

4.1.3汇编控制(AssemblyControl)伪指令

汇编控制伪指令用于控制汇编程序的执行流程,包括以下常用的汇编控制伪指令:

●IF、ELSE、ENDIF

●WHILE、WEND

●MACRO、MEND

●MEXIT

1.IF、ELSE、ENDIF

语法格式:

IF逻辑表达式

指令序列1

ELSE

指令序列2

ENDIF

IF、ELSE、ENDIF伪指令能够根据条件的成立与否决定是否执行某个指令序列。

若IF后面的逻辑表达式为真,则执行指令序列1,否则执行指令序列2。

其中,ELSE及指令序列2可以没有,此时,若IF后面的逻辑表达式为真,则执行指令序列1,否则继续执行后面的指令。

IF、ELSE、ENDIF伪指令可以嵌套使用。

使用示例:

GBLSVersion;定义一个全局的字符串变量,变量名为Version

IFVersion=“V1”

指令序列1

ELSE

指令序列2

ENDIF

2.WHILE、WEND

语法格式:

WHILE逻辑表达式

指令序列

WEND

WHILE、WEND伪指令能够根据条件的成立与否决定是否循环执行某个指令序列。

若WHILE后面的逻辑表达式为真,则执行指令序列,该指令序列执行完毕后,再判断逻辑表达式的值,若为真则继续执行,一直到逻辑表达式的值为假。

WHILE、WEND伪指令可以嵌套使用。

使用示例如下:

GBLACounter;声明一个全局的的数字变量,变量名为Counter,作为循环计数器

WHILECounter<10

指令序列

WEND

3.MACRO、MEND

语法格式:

$标号宏名$参数1,$参数2,…

指令序列

MEND

MACRO、MEND伪指令可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码。

其中,$标号在宏指令被展开时,标号会被替换为用户定义的符号,宏指令可以使用一个或多个参数,当宏指令被展开时,这些参数被相应的值替换。

宏指令的使用方式和功能与子程序相似,子程序可以提供模块化的程序设计,节省存储空间并提高运行速度。

包含在MAMEND之间的指令序列称为宏定义体,在宏定义的第一行应声明宏的原型(包含宏名、所需的参数),然后就可以在汇编程序中通过宏名来调用该指令序列。

MACRO、MEND可以嵌套使用。

使用示例如下:

MACRO

CODE_1;宏名为CODE_1,无参数

LDRR0,=rPDATG;读取PG0口的值

LDRR1,[R0]

ORRR1,R1,#0X01;CSI置位

SRTR1,[R0]

MEND

4.MEXIT

语法格式:

MEXIT

MEXIT用于从宏定义中跳转出去

4.1.4其他常用的伪指令

还有一些其他的伪指令,在汇编程序中经常会被使用,下面是一些使用比较频繁的伪指令:

●AREA

●ALIGN

●CODE16、CODE32

●ENTRY

●END

●EQU

●EXPORT(GLOBAL)

●IMPORT

●EXTERN

●GET(INCLUDE)

●INCBIN

●RN

●ROUT

4.2汇编语法

4.2.1汇编程序源文件

ARM汇编源程序文件是文本文件格式,可以使用任意一种文本编辑器编写程序代码。

通常情况下,ARM项目中的源程序文件具有如表4.1所示的扩展名。

表4.1ARM项目中的源程序文件及扩展名

源程序

文件扩展名

汇编源程序

.s

包含文件

.inc

C文件

.c

头文件

.h

在一个项目设计中,至少需要有一个汇编源文件或C程序文件,可以有多个汇编文件、多个C程序文件或者C语言和汇编语言混合编程的文件。

4.2.2汇编语句语法

1.汇编语句格式

ARM(Thumb)汇编语言的语句格式为:

{标号}{指令或伪指令}{;注释}

在汇编语言程序设计中,每一条指令的助记符可以全部用大写或全部用小写,但不允许一条指令中大、小写混用。

同时,如果一条语句太长,可半该长语句分为若干行来书写,在行的末尾用“\”表示下一行与本行为同一条语句。

汇编语句的注释用“;”,注释内容由“;”开始到此行结束,注释可以在一行的顶头书写。

对于变量的设置、常量的定义,其标识符必须在一行的顶头书写。

源程序中允许有空行,适当的插入空行可以提高程序的可读性。

汇编语句正确的例子和错误的例子如下:

String1SETS"Mystring1"

CountRNR0

USR_STRACKEQU64

STARTLDRR0,=0x12345

MOVR1,#0

LOOP

MOVR2,#3

错误的例子:

STARTMOVR0,#1;标号START没有顶头写(START前有空格)

ABC:

MOVR1,#2;标号ABC后不能带“:

MOVR2,#3;MOV指令不允许顶头写(MOV前要有空格)

LoopMOVR2,#3;指令中有大、小写混合

Bloop;无法跳转到loop去(loop与Loop有区别)

2.标号

在ARM汇编中,标号代表一个地址,段内标号的地址在汇编时确定,而段外标号的地址在连接时确定,根据标号的生成方式,可以有以下3种方式:

1)基于PC的标号

基于PC的标号是位于目标指令前的标号或程序中的数据定义伪指令前的标号,这种标号在汇编时被处理成PC值加上或减去一个数字常量,它常用于跳转指令的目标地址,或代码段中所嵌入的少量数据。

2)基于寄存器的标号

基于寄存器的标号通常由MAP和FIELD伪指令定义,也可以用EQU伪指令定义。

这种标号在汇编时被处理成寄存器的值加上或减去一个数字常量。

它通常用于访问位于数据段中的数据。

3)绝对地址

绝对地址是一个32位的数字,它可以寻址的范围是0~232-1,可以直接寻址整个内存空间。

3.常用符号

在汇编语言程序设计中,经常使用各种符号代替地址、变量和常量等,以增加程序的可读性。

尽管符号的命名由编程者决定,但并不是任意的,必须遵循以下的决定:

●符号由大、小写字母、数字以及下划线组成;

●除局部标号以数字开头外,其他的符号不能以数字开头;

●符号区分大、小写,同名的大、小写符号会被编译器认为是两个不同的符号;

●符号在其作用范围内必须唯一;

●自定义的符号不能与系统的保留子相同;

●符号名不应与指令或伪指令同名。

1)程序中的变量

程序中的变量是指其值在程序的运行过程中可以改变的量。

ARM汇编程序所支持的变量有数字变量、逻辑变量和字符串变量。

2)程序中的常量

程序中的常量是指其值在程序的运行过程中不能被改变的量。

ARM汇编程序所支持的常量有数字常量、逻辑常量和字符串常量。

数字常量一般为32位的整数,其取值范围为-231~231-1。

数字常量有3种表示方式:

●十进制数,如12,4,2,-4等;

●十六进制数,如0x32,0xFF,0x0等;

●n进制数,用n-XXX表示,其中n为为~9,XXX为具体的数,如2-0100101,8-43213等。

逻辑常量(又叫布尔常量)只有两种取值情况:

真{TRUE}或假{FALSE}。

比如:

IsrightSETS{FALSE}

字符串常量为一个固定的字符串,一般用于程序运行时的信息提示,比如:

HelloSETS"HelloWorld!

"

ErrorSETS"Theparameteriserror"

4.程序中的变量代换

程序中的变量可通过代换操作取得一个常量,代换操作符为“$”。

如果在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并将“$”后的数字变量用该十六进制的字符串代换。

如果在逻辑变量前面有一个代换操作符“$”,编译器会将“$”后的字符串变量用该字符串变量的值代换。

使用示例:

GBLSSTR1

GBLSSTR2

STR1SETS“test”

STR2SETS“Thisisa$STR1”;汇编后,STR2的值为Thisisatest

5.表达式和运算符

在汇编语言程序设计中,也经常使用各种表达式,表达式一般由变量、常量、运算符和括号构成。

常用的表达式有数字表达式、逻辑表达式和字符串表达式,其运算次序遵循如下的优先级:

●优先级相同的双目运算符的运算顺序为从左到右;

●相邻的单目运算符的运算顺序为从右到左,且单目运算符的优先级高于其他运算符;

●括号运算符的优先级最高

1)数字表达式及运算符

数字表达式一般由数字常量、数字变量、数字运算符和括号构成。

与数字表达式相关的运算符如下:

●“+”、“-”、“×”、“/”及“MOD”算术运算符

以上的算术运算任分别代表加、减、乘、除和取余运算。

例如,以X和Y表示两个数字表达式,则:

X+Y表示X与Y的和

X-Y表示X与Y的差

X×Y表示X与Y的乘积

X/Y表示X与Y的商

X:

MOD:

Y表示X除以Y的余数

●“ROL”、“ROR”“SHL”及“SHR”移位运算符

以X和Y表示两个数字表达式,则:

X:

ROL:

Y表示将X循环左移Y位

X:

ROR:

Y表示将X循环右移Y位

X:

SHL:

Y表示将X左移Y位

X:

SHR:

Y表示将X右移Y位

●“AND”、“OR”、“NOT”及“EOR”按位逻辑运算符

以X和Y表示两个数字表达式,则:

X:

AND:

Y表示将X和Y作逻辑与的操作

X:

OR:

Y表示将X和Y作逻辑或的操作

NOT:

Y表示将将Y作逻辑非的操作

X:

EOR:

Y表示将X和Y按位作逻辑异或的操作

2)逻辑表达式及运算符

逻辑表达式一般由逻辑量、逻辑运算符和括号构成,其表达式的运算结果为真或假。

与逻辑表达式相关的运算符如下:

●“=”、“>”、“<”、“>=”、“/=”“<>”运算符

以X和Y表示两个逻辑表达式,以上的运算符代表运算如下:

X=Y表示X等于Y

X>Y表示X大于Y

X

X>=Y表示X大于等于Y

X<=Y表示X小于等于Y

X/=Y表示X不等于Y

X<>Y表示X不等于Y

●“LAND”、“LOR”、“LNOT”及“LEOR”运算符

以X和Y表示两个逻辑表达式,以上的逻辑运算符代表运算如下:

X:

LAND:

Y表示将X和Y作逻辑与的操作

X:

LOR:

Y表示将X和Y作逻辑或的操作

LNOT:

Y表示将将Y作逻辑非的操作

X:

LEOR:

Y表示将X和Y按位作逻辑异或的操作

3)字符串表达式及运算符

字符串表达式一般由字符串常量、字符串变量、运算符和括号构成,编译器所支持的字符串最大长度为512B。

常用的字符串表达式相关的运算符如下:

●LEN运算符

LEN运算符返回字的长度(字符数),以X表示字符串表达式,其语法格式如下:

LEN:

X

●CHR运算符

CHR运算符将0——255之间的整数转换为一个

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

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1