ARM汇编语言.docx

上传人:b****5 文档编号:6991012 上传时间:2023-01-15 格式:DOCX 页数:21 大小:30.82KB
下载 相关 举报
ARM汇编语言.docx_第1页
第1页 / 共21页
ARM汇编语言.docx_第2页
第2页 / 共21页
ARM汇编语言.docx_第3页
第3页 / 共21页
ARM汇编语言.docx_第4页
第4页 / 共21页
ARM汇编语言.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

ARM汇编语言.docx

《ARM汇编语言.docx》由会员分享,可在线阅读,更多相关《ARM汇编语言.docx(21页珍藏版)》请在冰豆网上搜索。

ARM汇编语言.docx

ARM汇编语言

ARM汇编语言

伪操作:

伪操作又称为伪指令,它不像机器指令那样是在程序运行期间由计算机来执行的,它是在汇编程序对源程序汇编期间由汇编程序处理的操作,它们可以完成如数据定义、分配存储区、指示程序结束等功能。

宏指令是一段独立的程序代码,它通过伪操作来定义。

宏通过宏名来调用,并可以设置相应的参数。

宏定义本身不会产生代码,只是在调用它时把宏体插入到源程序中。

a、符号定义伪操作

伪操作

作用

GBLA

声明全局算术变量

GBLL

声明全局逻辑变量

GBLS

声明全局字符串变量

LCLA

声明局部算术变量

LCLL

声明局部逻辑变量

LCLS

声明局部字符串变量

SETA

给全局或局部算术变量赋值

SETL

给全局或局部逻辑变量赋值

SETS

给全局或局部字符串变量赋值

RLIST

为通用寄存器列表定义名称

CN

为协处理器的寄存器定义名称

CP

为协处理器定义名称

DN/SN

为双精度/单精度VFP的寄存器定义名称

FN

为FPA浮点寄存器定义名称

①GBLA、GBLL、GBLS用于声明一个ARM程序中的全局变量,并将其初始化。

GBLA声明一个全局的算术变量,并将其初始化为0;

GBLL声明一个全局的逻辑变量,并将其初始化为{FALSE};

GBLS声明一个全局的字符串变量,并将其初始化为空字符串””。

句法:

variable

GBLX是三种伪操作之一,variable是所说明的全局变量的名称,在其作用范围唯一。

用法:

如果用这些伪操作重新声明已经声明过的变量,则变量的值将被初始化成后一次声明语句中的值。

全局变量的作用范围为包含该变量的源程序。

例子:

GLBAarithmetic;声明全局算术变量arithmetic

arithmeticSETA0xff;向该变量赋值

SPACEarithmetic;引用该变量

GBLLlogical;声明全局逻辑变量logical

logicalSETL{TRUE};向该变量赋值

②LCLA、LCLL、LCLS用于声明一个ARM程序中的局部变量,并将其初始化。

LCLA声明一个局部的算术变量,并将其初始化为0;

LCLL声明一个局部的逻辑变量,并将其初始化为{FALSE};

LCLS声明一个局部的字符串变量,并将其初始化为空字符串””。

句法:

variable

用法:

如果用这些伪操作重新声明已经声明过的变量,则变量的值将被初始化成后一次声明语句中的值。

局部变量的作用范围为包含该局部变量的宏代码的一个实例。

例子:

MACRO;声明一个宏

$labelmessage$a;宏的原型

LCLSerr;声明一个局部字符串变量err

errSETS“errorno:

”;向该变量赋值

$label

INFO0,“err”:

CC:

:

STR:

$a;使用该字符串变量

MEND;宏定义结束

③SETA、SETL、SETS用于给一个ARM程序中的变量赋值

SETA给一个算术变量赋值;

SETL给一个逻辑变量赋值;

SETS给一个字符串变量赋值。

句法:

variableexpr

variable是已定义变量的名称,在其作用范围内唯一。

是三种伪操作之一,expr是要赋的值。

在向变量赋值前必须先声明该变量。

④RLIST为一个通用寄存器列表定义名称。

句法:

nameRLIST{list-of-register}

name为寄存器列表名称,list-of-register为通用寄存器列表。

用法:

定义的名称可以在LDM/STM指令中使用。

在LDM/STM指令中,寄存器列表中的寄存器访问次序总是先访问编号较低的寄存器,再访问编号较高的寄存器,不管寄存器列表中各寄存器的排列顺序。

例子:

ContextRLIST{R0-R6,R8,R10,R15};

⑤CN为一个协处理器的寄存器定义名称

句法:

nameCNexpr

name为该寄存器的名称,expr为协处理器编号,数值为0~15。

用法:

CN用于给一个协处理器的寄存器定义名称,方便程序员记忆该寄存器的功能。

例子:

PowerCN6;将协处理器的寄存器6的名称定义为Power

⑥CP为一个协处理器定义名称

句法:

nameCPexpr

name为该协处理器的名称,expr为协处理器的编号,数值为0~15。

用法:

CP用于给一个协处理器定义名称,方便程序员记忆该协处理器的功能。

例子:

DmuCN6;将协处理器6的名称定义为Dmu

⑦DN/SN

DN为一个双精度的VFP寄存器定义名称

SN为一个单精度的VFP寄存器定义名称

句法:

nameDNexpr/nameSNexpr

name为该VFP寄存器的名称。

expr为VFP双精度寄存器编号(0~15)或者单精度寄存器编号(0~15)。

用法:

便于程序员记忆该寄存器的功能。

例子:

heightDN6

widthSN15

⑧FN为一个FPA浮点寄存器定义名称。

句法:

nameFNexpr

name为该浮点寄存器的名称。

expr为该浮点寄存器的编号,数值为0~7。

用法:

FN用于给一个浮点寄存器定义名称,方便程序员记忆该寄存器的功能。

例子:

heightFN6;将浮点寄存器6的名称定义为height

程序中的变量代换

①程序中的变量可通过代换操作取得一个常量。

代换操作符为“$”。

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

③如果在逻辑变量前面有一个代换操作符“$”,编译器会将该逻辑变量代换为它的取值(真或假)。

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

b、数据定义(内存分配)伪操作

伪操作

作用

LTORG

声明一个数据缓冲池的开始

MAP

定义一个结构化的内存表的首地址

FIELD

定义一个结构化内存表中的一个数据域

SPACE

分配一块内存单元,并用0初始化

DCB

分配一段字节的内存单元,并用指定数据初始化

DCD/DCDU

分配一段字的内存单元

DCDO

分配一段字的内存单元,并将单元的内容初始化成该单元相对于静态基值寄存器的偏移量

DCFD/DCFDU

分配一段双字的内存单元,并用双精度的浮点数据初始化

DCFS/DCFSU

分配一段字的内存单元,并用单精度的浮点数据初始化

DCI

分配一段字节的内存单元,用指定的数据初始化,指定内存单元中存放的是代码,而不是数据

DCQ/DCQU

分配一段双字的内存单元,并用64位的整数数据初始化

DCW/DCWU

分配一段半字的内存单元,并用指定的数据初始化

①LTORG用于声明一个数据缓冲池的开始

句法:

LTORG

用法:

通常ARM汇编编译器把数据缓冲池放在代码段的最下面,即下一个代码段开始之前,或在END之前。

该指令通常放在无条件分支指令之后,或者子程序返回指令之后,这样处理器就不会错误地将数据缓冲池中的数据当作指令来执行了。

当程序中使用LDFD之类的指令时,数据缓冲池的使用可能越界。

这时可以使用LTORG定义数据缓冲池。

通常大的代码段可以使用多个数据缓冲池。

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

此时,内存表的位置计数器设置成该地址。

句法:

MAPexpr{,base-register}

其中:

expr为数字表达式或者程序中的标号。

当指令中没用base-register时,expr即为结构化内存表的首地址。

base-register为一寄存器。

当指令包括这一项时,结构化内存表的首地址为expr和base-register寄存器值的和。

用法:

MAP和FIELD伪操作配合使用来定义结构化的内存表。

例子:

MAP0x80,R9;内存表的首地址为0x80+R9

③FIELD用于定义一个结构化的内存表的数据域。

句法:

{label}FIELDexpr

其中{label}是可选的,当包括这一项时,label的值为当前内存表的位置计数器{VAR}的值。

处理了这条FIELD伪操作后,VAR的值将加上expr。

expr表示本数据域在内存表中所占的字节数。

用法:

MAP和FIELD伪操作配合使用来定义结构化的内存表结构,MAP定义了首地址,FIELD定义了各数据域的字节长度,并为每个数据域定义了一个标号。

MAP和FIELD仅仅是定义数据结构,它们并不实际分配内存单元。

例子:

定义一个内存表,其首地址为固定地址4096(0x1000),该内存表中包含5个数据域:

consta和constb长度分别为4个字节;x和y长度分别为8个字节;string长度为256字节。

这种内存表称为基于绝对地址的内存表。

MAP4096

constaFIELD4

constbFIELD4

xFIELD8

yFIELD8

stringFIELD256

在指令中,可以这样引用内存表的数据域:

LDRR6,consta

④SPACE用于分配一块内存单元,并用0初始化。

句法:

{label}SPACEexpr

其中{label}是可选的。

expr表示本伪操作分配的内存字节数。

例子:

DatastructSPACE280;分配280字节的内存,并将单元内容初始化为0

⑤DCB用于分配一段字节内存单元,并用伪操作中的expr初始化它。

句法:

{label}DCBexpr{,expr}…

其中{label}是可选的。

expr可以为-128~255的数值或字符串。

例子:

NullstringDCB“Nullstring”,0;构造一个以NULL结尾的字符串。

⑥DCD和DCDU。

DCD用于分配一段字内存单元(分配的内存都是字对齐),并用伪操作中的expr初始化它。

DCDU的不同之处在于分配的内存并不严格对齐。

句法:

{label}DCD{U}expr{,expr}…

其中{label}是可选的。

expr可以为数字表达式或程序中的编号。

用法:

DCD可能在分配的第一个内存单元前插入填补字节来保证分配的内存是字对齐的。

例子:

data1DCD1,5,20;其值分别为1、5、20

data2DCDmemaddr+4;分配一个字单元,其值为程序中的标号memaddr加上4

⑦DCDO用于分配一段字内存单元(分配的内存都是字对齐),并将这个字单元的内容初始化成expr标号基于基址寄存器R9的偏移量。

句法:

{label}DCDOexpr{,expr}…

其中{label}是可选的。

expr可以为数字表达式或程序中的编号。

用法:

为基于静态基址寄存器R9的偏移量分配内存单元。

例子:

IMPORTexternsym

DCDOexternsym;分配一个字单元,其值为标号;externsym基于R9的偏移量。

⑧DCFD和DCFDU。

DCFD用于双精度的浮点数分配字对齐的内存单元,并用伪操作中的fpliteral初始化它。

每个双精度数占据两个字单元。

DCFDU的分配的内存并不严格对齐。

句法:

{label}DCFD{U}fpliteral{,fpliteral}…

其中{label}是可选的。

fpliteral为双精度浮点数。

用法:

DCFD可能在分配的第一个内存单元前插入填补字节来保证分配的内存是字对齐的。

例子:

DCFD1E208,-4E-100

DCFDU10000,-.1,3.1E26

⑨DCFS和DCFSU。

DCFD用于单精度的浮点数分配字对齐的内存单元,并用伪操作中的fpliteral初始化它。

每个单精度数占据1个字单元。

DCFSU的分配的内存并不严格对齐。

句法:

{label}DCFS{U}fpliteral{,fpliteral}…

其中{label}是可选的。

fpliteral为双精度浮点数。

用法:

DCFS可能在分配的第一个内存单元前插入填补字节来保证分配的内存是字对齐的。

例子:

DCFS1E3,-4E-9

DCFSU1.0,-.1,3.1E6

⑩DCI。

在ARM代码中,用于分配一段字对齐的内存单元,并用伪操作中的expr初始化它。

在Thumb代码中,用于分配一段半字对齐的内存单元。

句法:

{label}DCIexpr{,expr}…

用法:

DCI和DCD非常类似,不同之处在于DCI分配的内存中数据被标识为指令,可用于通过宏指令来定义处理指令系统不支持的指令。

例子:

MACRO

Newinst$Rd,$Rm

DCI0xe16f0f10:

OR:

($Rd:

SHL:

12):

OR:

$Rm;这个宏指令将指令newinst定义为相应的机器指令。

DCQ和DCQU。

DCQ用于分配一段8个字节为单位的内存(分配的内存都是字对齐),并用伪操作中的literal初始化它。

DCQU的不同之处在于分配的内存并不严格对齐

句法:

{label}DCQ{U}literal{,literal}…

其中{label}是可选的。

literal为64位数字表达式,取值范围为-263~264-1。

用法:

DCD可能在分配的第一个内存单元前插入多达3个字节的填补字节来保证分配的内存是字对齐的。

例子:

dataDCQ-225,2_101;2_101表示为二进制的101

DCQUnumber+4

DCW和DCWU。

DCW用于分配一段半字内存单元(分配的内存都是半字对齐),并用伪操作中的expr初始化它。

DCWU的不同之处在于分配的内存并不严格半字对齐

句法:

{label}DCW{U}expr{,expr}…

其中{label}是可选的。

expr为数字表达式,取值范围为-32768~65535。

用法:

DCW可能在分配的第一个内存单元前插入1个字节的填补字节来保证分配的内存是半字对齐的。

例子:

Data1DCW-235,num1+8

c、汇编控制定义伪操作

伪操作

作业

IF

ELSE

ENDIF

能够根据条件把一段源代码包括在汇编语言程序内或者将其排除在程序之外。

WHILE

WEND

能够根据条件重复汇编相同的一段源代码。

MACRO

MEND

MEXIT

MACRO标识宏定义的开始,MEND标识宏定义的结束。

MEXIT用于从宏中跳转出去。

用MACRO和MEND定义的一段代码,称为宏定义体。

通过宏名称来调用宏。

①IF、ELSE和ENDIF。

能够根据条件把一段源代码包括在汇编语言内或者将其排除在外。

其中ELSE伪操作是可选的。

例子:

IFVersion=“1.0”

;指令

;伪指令

ELSE

;指令

;伪指令

ENDIF

②WHILE和WEND。

能够根据条件重复汇编相同的或者几乎相同的一段源代码。

例子:

countSETA1

WHILEcount<=4

countSETAcount+1

;代码

WEND

③MACRO及MEND。

MACRO标识宏定义的开始,MEND标识宏定义的结束。

用它们定义一段代码,称为宏定义体。

语法格式:

MACRO

{$label}macromane{$parameter{,parameter}…}

;code

;code

MEND

其中,$label在宏指令被展开时,label可被替换成相应的符号,通常是一个标号。

$parameter为宏指令的参数。

macroname为所定义的宏名字。

例子:

MACRO

$labelxmac$p1,$p2

;code

$label.loop1;code;label.loop1为宏定义体的内部标号。

;code

BGE$label.loop1

$label.loop2;code

BL$p1;参数p1为一子程序的名称

BGT$lqabel.loop2

;code

ADR$p2

;code

MEND

;在程序中调用时

abcxmacsubr1,de;通过宏的名称调用宏,宏的标号为abc

④MEXIT用于从宏中跳转出去。

例子:

MACRO

$abcmacroabc$param1,$param2

;code

WHILEcondition1

;code

IFcondition2

;code

MEXIT;从宏中跳转出去

ELSE

;code

ENDIF

WEND

;code

MEND

d、信息报告伪操作

伪操作

作用

ASSERT

报告错误信息

INFO

报告诊断信息

OPT

在源程序中设置列表选项

TTL和SUBT

在列表文件中的每一页开头插入标题和子标题

e、其它伪操作

伪操作

作用

ALIGN

通过添加补丁字节使当前位置满足一定的对齐方式

AREA

定义一个代码段或者数据段

CODE16

CODE32

CODE16告诉编译器后面的指令序列为16位的Thumb指令;CODE32告诉编译器后面的指令序列为32位的ARM指令

END

告诉编译器已经到了源程序结尾

ENTRY

指定程序的入口点

EQU

为数字常量、基于寄存器的值和程序中的标号(基于PC的值)定义一个字符名称

EXPORT/GLOBAL

声明一个符号可以被其他文件引用,相当于声明了一个全局变量

EXTERN

告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号

GET/INCLUDE

将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理

IMPORT

告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号

INCBIN

将一个文件包含到当前源文件中,被包含的文件不进行汇编处理

KEEP

告诉编译器将局部符号包含在目标文件的符号表中

NOFP

禁止源程序中包含浮点运算指令

REQUIRE

指定段之间的相互依赖关系

RN

为一个特定的寄存器定义名称

ROUT

定义局部变量的有效范围

①ALIGN通过添加补丁字节使当前位置满足一定的对齐方式。

句法:

ALIGN{expr{,offset}}

其中,expr为数据表达式,用于指定对齐方式。

可能的取值是2的次幂,如1、2、4、8等。

如果没有指定expr,则当前位置对齐到下一个字边界处。

Offset为数字表达式。

当前位置对齐到下面形式的地址处:

offset+n*expr。

用法:

在下列情况中,需要特殊的地址对齐方式:

Thumb的宏指令ADR要求地址是字对齐的,而Thumb代码中的地址标号可能不是字对齐的。

这时就要使用伪操作ALIGN4使Thumb代码中的地址标号字对齐

由于有些ARM处理器的CACHE采用了其他对齐方式,如16字节的对齐方式,这时使用ALIGN指定合适的对齐方式可以充分发挥CACHE的性能优势。

LDRD和STRD指令要求内存单元是8字节对齐的。

这样在为LDRD/STRD指令分配的内存单元前要使用ALIGN8实现8字节对齐方式。

地址标号通常自身没有对齐要求。

而在ARM代码中要求地址标号是字对齐的,在Thumb代码中要求半字对齐。

需要使用合适的ALIGN伪操作来调整对齐方式。

例子1:

在AREA伪操作中的ALIGN和ALIGN伪操作中的expr含义是不同的

AREAcacheable,CODE,ALIGN=3;下面的指令时8字节对齐

rout1;code

;code

MOVPC,LR;程序跳转后变成4字节对齐的

ALIGN8;指定下面的指令只8字节对齐

rout2;code

例子2:

将两个字节数据放在同一个字的第一个和第四个字节

AREAoffsetExample,CODE

DCB1

ALIGN4,3

DCB1

例子3:

通过ALIGN伪操作使程序中地址标号字对齐

AREAExample,CODE,READONLY

StartLDRR6,=label11

;code

MOVPC,LR

Label11DCB1

ALIGN

Subroutine1

MOVR5,#0x5

②AREA用于定义一个代码段或者数据段。

句法:

AREAsectionname{,attr}{,attr}…

其中,sectionname为所定义的代码段或者数据段的名称。

如果是数据打头的,则该名称必须用“|”括起来,如|1_datasec|。

还有一些代码段具有约定的名称,如|.text|表示C语言编译器产生的代码或者与C语言库相关的代码段。

attr是该代码段的属性。

在AREA中,各属性间用逗号隔开。

可能的属性有:

ALIGN=expression。

默认的情况下,ELF代码段和数据段是4字节对齐。

Expression可以取0-31的数值,相应的对齐方式是(2expression)字节对齐,如expression=3时为8字节对齐。

ASSOC=section。

指定与本段相关的ELF段。

CODE定义代码段,默认属性为READONLY。

COMDEF定义一个通用段。

该段可以包含代码或者数据。

在各源文件中,同名的COMMON段必须相同。

COMMON定义一个通用段。

该段不包含任何代码和数据,连接器将其初始化为0。

各源文件中同名的COMMON段公用同样的内存单元。

DATA定义数据段。

默认属性为READWRITE。

NOINIT指定本数据段仅仅保留内存单元,而没有将各初值写入内存单元,或者将内存单元值初始化为0。

READONLY指定本段为只读,代码段的默认属性为READONLY。

READWRITE指定本段为可读可写,数据段的默认属性为READWRITE。

用法:

一个大的程序可以包含多个代码段和数据段,一个汇编程序至少包含一个段。

例子:

AREAExample,CODE,READONLY

;code

③CODE16和CODE32。

CODE16告诉编译器后面的指令序列是16位的Thumb指令;CODE32指示32位的ARM指令。

句法:

CODE16

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

当前位置:首页 > 初中教育 > 语文

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

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