您的位置 首页 观点

ARM学习手札之汇编伪指令

ARM汇编程序由机器指令,伪指令和宏指令组成。伪指令不像机器指令那样在处理器运行期间由机器执行,而是汇编程序对源程序汇编期间由汇编

ARM 汇编程序由机器指令,伪指令和宏指令组成。伪指令不像机器指令那样在处理器运转期间由机器履行,而是汇编程序对源程序汇编期间由汇编程序处理。在前面的指令集章节中,咱们现已触摸了几条常用到的伪指令,如ADR 、ADRL、LDR、NOP 等,把它们和指令集一同介绍是因为它们在汇编时会被适宜的机器指令替代,完成真实机器指令操作。宏是一段独立的程序代码,它是经过伪指令界说的,在程序中运用宏指令即可调用宏。

当程序被汇编时,汇编程序将对每个调用进行打开,用宏界说替代源程序中的宏指令。

符号界说伪指令
符号界说伪指令用于界说ARM 汇编程序的变量,对变量进行赋值以及界说寄存器称号,该类伪指令如下:
大局变量声明:GBLA、GBLL 和GBLS。
部分变量声明:LCLA、LCLL 和LCLS。
变量赋值: SETA、SETL 和SETS。
为一个通用寄存器列表界说称号:RLIST。
为一个协处理器的寄存器界说称号:CN。
为一个协处理界说称号: CP。
为一个VFP 寄存器界说称号:DN 和SN。
为一个FPA 浮点寄存器界说称号:FN。

GBLA、GBLL、GBLS
大局变量声明伪指令。
GBLA 伪指令用于声明一个大局的算术变量,并将其初始化为0。
GBLL 伪指令用于声明一个大局的逻辑变量,并将其初始化为{FALSE}。
GBLS 伪指令用于声明一个大局的字符串变量,并将其初始化为空字符串“”。
伪指令格局:
GBLA variable
GBLL variable
GBLS variable
其间:variable 界说的大局变量名,在其效果规模内有必要专一。大局变量的效果规模为包括该变量的源程序。
伪指令运用举例如下:
GBLL codedbg ;声明一个大局逻辑变量
codebg SETL {TRUE} ;设置变量为{TRUE}

LCLA、LCLL、LCLS
部分变量声明伪指令,用于宏界说的体中。
LCLA 伪指令用于声明一个部分的算术变量,并将其初始化为0。
LCLL 伪指令用于声明一个部分的逻辑变量,并将其初始化为{FALSE}。
LCLS 伪指令用于声明一个部分的字符串变量,并将其初始化为空字符串“”。
伪指令格局:
LCLA variable
LCLL variable
LCLS variable
其间:variable 界说的部分变量名。在其效果规模内有必要专一。部分变量的效果规模为包括该部分变量只能在宏中进行声明及运用。
伪指令运用举例如下:
MACRO ;声明一个宏
SENDDAT $dat ;宏的原型
LCLA bitno ;声明一个部分算术变量

bitno SETA 8 ;设置变量值为8

MEND

SETA、SETL、SETS
变量赋值伪指令。用于对已界说的大局变量,部分变量赋值。
SETA 伪指令用于给一个大局/部分的算术变量赋值。
SETL 伪指令用于给一个大局/部分的逻辑变量赋值。
SETS 伪指令用于给一个大局/部分的字符串变量赋值。
伪指令格局:
variable_a SETA expr_a
variable_l SETL expr_l
variable_s SETS expr_s
其间:variable_a 算术变量。用GBLA、LCLA 伪指令界说的变量。
expr_a 赋值的常数。
variable_l 逻辑变量。用GBLL、LCLL 伪指令界说的变量。
expr_l 逻辑值,即{TRUE}或{FALSE}。
variable_s 字符串变量。用GBLS、LCLS 伪指令界说的变量。
expr_s 赋值的字符串。
伪指令运用举例如下:
GBLS ErrStr

ErrStr SETS “No,semaphone”

RLIST
RLIST 为一个通用寄存器列表界说称号。伪指令格局如下:
name RLIST {reglist}
其间:name 要界说的寄存器列表的称号。
reglist 通用寄存器列表。
伪指令运用举例如下:
LoReg RLIST {R0-R7} ;界说寄存器列表LoReg

STMFD SP!,LoReg ;保存寄存器列表LoReg

CN
CN 为一个协处理器的寄存器界说称号。
伪指令格局:
name CN expr
其间:name 要界说的协处理器的寄存器称号。
expr 协处理器的寄存器编号,数值规模为0~15。
伪指令运用举例如下:
MemSet CN l ;将协处理的寄存器l 称号界说为MemSet

CP
CP 为一个协处理器界说的称号。
伪指令格局:
name CP expr
其间:name 要界说的协处理器称号。
expr 协处理器的编号,数值规模为0~15。
伪指令运用举例如下:
DivRun CN 5 ;将协处理器5 称号界说为DivRun

DN、SN
DN 和SN 为VFP 的寄存器的称号界说的伪指令。
DN 为一个双精度原VFP 寄存器界说称号。
SN 为一个单精度的VFP 寄存器界说称号。
伪指令格局:
name DN expr
name SN expr
其间:name 要界说的VFP 寄存器称号。
expr 双精度的VFP 寄存器编号为0~15,单精度的VFP 寄存器编号为0~31。
伪指令运用举例如下:
cdn DN 1 ;将VFP 双精度寄存器1 称号界说为cdn
rex SN 3 ;将VFP 单精度寄存器3 称号界说为rex

FN
FN 为一个FPA 浮点寄存器界说称号
伪指令格局:
name FN expr
其间:name 要界说的浮点寄存器称号。
expr 浮点寄存器的编号,值为0~7。
伪指令运用举例如下:
ibq FN l ;将浮点寄存器l 称号界说为ibq

A.4.2 数据界说伪指令
数据界说伪指令用于数据表界说,文字池界说,数据空间分配等。该类伪指令如下:
声明一个文字池:LTORG。
界说一个结构化的内存表的首地址:MAP。
界说结构化内存表中的一个数据域:FIELD。
分配一块内存空间,并用0 初始化:SPACE。
分配一段字节的内存单元,并用指定的数据初始化:DCB。
分配一段字的内存单元,并用指令的数据初始化:DCD 和DCDU。
分配一段字的内存单元,将每个单元的内容初始化为该单元相关于静态基址寄存器的偏移量:DCDO。
分配一段双字的内存单元,并用双精度的浮点数据初始化:DCFD 和DCFDU。
分配一段字的内存单元,并用单精度的浮点数据初始化:DCFS 和DCFSU。
分配一段字的内存单元,并用单精度的浮点数据初始化,指定内存单元寄存的是代码,而不是数据:DCI。
分配一段双字的内存单元,并用64 位整数数据初始化:DCQ 和DCQU。
分配一段半字的内存单元,并用指定的数据初始化:DCW 和DCWU。

LTORG
LTORG 用于声明一个文字池,在运用LDR 伪指令时,要在恰当的地址参加LTORG 声明文字池,这样就会把要加载的数据保存在文字池内,再用ARM 的加载指令读出数据。(若没有运用LTORG 声明文字池,则汇编器会在程序结尾主动声明。)
伪指令格局:
LTORG
伪指令运用举例如下:

LDR R0,=0x12345678
ADD R1,R1,R0
MOV PC,LR
LTORG ;声明文字池,此地址存储0x12345678
… ;其它代码
LTORG 伪指令常放在无条件跳转指令之后,或许子程序回来指令之后,这样处理器就不会过错地将文字池中的数据当作指令来履行。

MAP
MAP 用于界说一个结构化的内存表的首地址。此刻,内存表的方位计数器{VAR}设置为该地址值{VAR}为汇编器的内置变量。^与MAP 同义。
伪指令格局:
MAP expr,{base_register}
其间:expr 数字表达式或程序中的标号。当指令中没有
base_register 时,expr 即为结构化内存表的首地址。
base_register 一个寄存器。当指令中包括这一项时,结构化内存表的首地址为expr 与base_register 寄存器值的和。
伪指令运用举例如下:
MAP 0x00,R9 ;界说内存表的首地址为R9
Timer FIELD 4 ;界说数据域Timer,长度为4 字节
Attrib FIELD 4 ;界说数据域Attrib,长度为4 字节
String FIELD 100 ;界说数据域String,长度为100 字节

ADR R9,DataStart ;设置R9 的值,即设置结构化的内存表地址
LDR R0,Atrrib ;相当于LDR,R0,[R9,#4]

MAP 伪指令和FIELD 伪指令合作运用,用于界说结构化的内存表结构。MAP 伪指令中的base-register 寄存器的值关于这以后一切的FIELD 伪指令界说的数据域是默许运用的,直到遇到新的包括base-register 项的MAP 伪指令。

FIELD
FIELD 用于界说一个结构化内存表中的数据域。#与FIELD 同义。
伪指令格局:
{tabel} FIELD expr
其间:label 当指令中包括这一项时,label 的值为当时内存表的方位计数器{VAR}的值,汇编编译器处理了这条FIELD 伪指令后,内存表计数器的值将加上expr。
expr 表明本数据域在内存表中所占用的字节数。
伪指令运用举例如下:
MAP 0x40003000 ;内存表的首地址为0x40003000
count1 FIELD 4 ;界说数据域count1,长度为4 字节
count2 FIELD 4 ;界说数据域count2,长度为4 字节
count3 FIELD 4 ;界说数据域count3,长度为4 字节
LDR R1,count1 ;R1=[0x40003000+0x00]
STR R1,count2 ;[0x40003000+0x00]=R1
MAP、FIELD 伪指令仅仅是界说数据结构,它们并不实践分配内存单元。

SPACE
SPACE 用于分配一块内存单元,并用0 初始化。%与SPACE 同义。
伪指令格局:
{label} SPACE expr
其间:label 内存块开端地址标号。
expr 所要分配的内存字节数。
伪指令运用举例如下:
AREA DataRA,DATA,READWROTE ;声明一数据段,名为DataRAM
DataBuf SPACE 1000 ;分配1000 字节空间

DCB
DCB 用于分配一段字节内存单元,并用伪指令中的expr 初始化。一般可用来界说数据表格,或文字符串。=与DCB 同义。
伪指令格局:
{label} DCB expr{,expr}{,expr}…
其间:label 内存块开端地址标号。
expr 能够为-128~255 的数值或字符串。内存分配的字节数由expr 个数决议。
伪指令运用举例如下
DISPTAB DCB 0x33,0x43,0x76,0x12
DCB -120,20,36,55
ERRSTR DCB “Send,data is error!”,0

DCD 和DCDU
DCD 用于分配一段字内存单元,并用伪指令中的expr 初始化。DCD 伪指令分配的内存需求字对齐,一般可用来界说数据表格或其它常数。&与DCD 同义。
DCDU 用于分配一段字内存单元,并用伪指令中的expr 初始化。DCD 伪指令分配的内存不需求字对齐,一般可用来界说数据表格或其它常数。
伪指令格局:
{label} DCD expr{,expr}{,expr}…
{label} DCDU expr{,expr}{,expr}…
其间:label 内存块开端地址标号。
expr 常数表达式或程序中的标号。内存分配字节数由expr 个数决议。
伪指令运用举例如下:
Vectors
LDR PC,ReserAddr
LDR PC,UndefinedAddr

ResetAddr DCD Reset
UndefinedAddr DCD Undefined

Reset

Undefined

DCDO
DCDO 用于分配一段字内存单元。并将每个单元的内容初始化为该单元相关于静态基址寄存器的偏移量。DCDO 伪指令作为依据静态基址寄存器R9 的偏移量分配内存单元。DCDO 伪指令分配的内存需求字对齐。
伪指令格局:
{label} DCDO expr{,expr}{,expr}…
其间:label 内存块开端地址标号。
expr 地址偏移表达式或程序中的标号。内存分配的字数由expr 个数决议。
伪指令运用举例如下:
IMPORT externsym
DCDO externsym ;分配32 位的字单元,其值为标号externsym 依据R9 的偏移

DCFD 和DCFDU
DCFD 用于分配一段双字的内存单元,并用双精度的浮点数据fpliteral 初始化。每个双精度的浮点数占有两个字单元。DCFD 伪指令分配的内存需求字对齐。
DCFDU 具有DCFD 相同的功用,但分配的内存不需求字对齐。
伪指令格局:
{label} DCFD fpliteral{,fpliteral}{,fpliteral}…
{label} DCFDU fpliteral{,fpliteral}{,fpliteral}…
其间:label 内存块开端地址标号。
fpliteral 双精度的浮点数。
伪指令运用举例如下:
DCFD 2E30,-3E-20
DCFDU -.1,1000,2.1E18

DCFS 和DCFSU
DCFS 用于分配一段字的内存单元,并用单精度的浮点数据fpliteral 初始化。每个单精度的浮点数占有一个字单元。DCFD 伪指令分配的内存需求字对齐。
DCFSU 具有DCFS 相同的功用,但分配的内存不需求字对齐。
伪指令格局:
{label} DCFS fpliteral{,fpliteral}{,fpliteral}…
{label} DCFSU fpliteral{,fpliteral}{,fpliteral}…
其间:label 内存块开端地址标号
fpliteral 单精度的浮点数。
伪指令运用举例如下:
DCFS 1.1E2,-1.3E10,0.0999

DCI
在ARM 代码中,DCI 用于分配一段字节的内存单元,用指定的数据expr 初始化。指定内存单元寄存的是代码,而不是数据。
在Thumb 代码中,DCI 用于分配一段半字节的内存单元,用指定的数据expr 初始化。指定内存单元寄存的是代码,而不是数据。
伪指令格局:
{label} DCI expr
其间:label 内存块开端地址标号。
expr 可为数字表达式。
DCI 伪指令和DCD 伪指令十分相似,不同之处在于DCI 分配的内存中的数据被标识为指令。可用于经过宏指令业界说处理器不支持的指令。
伪指令运用举例如下:
MACRO ;宏界说(界说NEWCMN Rd,Rn 指令)
NEWCMN $Rd,$Rm ;宏名为NEWCMN,参数为Rd 和Rm
DCI 0xe16a0e20:OR:($Rd:SHL:12):OR:$Rm
MEND

DCQ 和DCQU
DCQ 用于分配一段双字的内存单元,并用64 位的整数数据literal 初始化。DCQ 伪指令分配的内存需求字对齐。
DCQU 具有DCQ 相同的功用,但分配的内存不需求字对齐。
伪指令格局:
{label} DCQ {-}literal{,{-}{literal}}…
{label} DCQU {-}literal{,{-}{literal}}…
其间:label 内存块开端地址标号。
literal 64 位的数字表达式。取值规模为0~264-1 当literal前有“.”号时,取值规模为-263~-1 之间。
伪指令运用举例如下:
DCQU 1234,-76568798776

DCW 和DCWU
DCW 用于分配一段字的内存单元,并用指定的数据expr 初始化。DCW 伪指令分配的内存需求字对齐。
DCWU 具有DCW 相同的功用,但分配的内存不需求字对齐。
伪指令格局:
{label} DCW expr{,expr}{,expr}…
{label} DCWU expr{,expr}{,expr}…
其间:label 内存块开端地址标号。
expr 数字表达式,取值规模为-32768~65535。
伪指令运用举例如下:
DCW -592,123,6756
陈述伪指令
陈述伪指令用于汇编陈述指示。该类伪指令如下:
断语过错:ASSERT。
汇编确诊信息显现:INFO。
设置列表选项:OPT。
刺进标题:TTL 和SUBT。

ASSERT
ASSERT 为断语过错伪指令。在汇编编译器对汇编程序的第二遍扫描中,假如其间
ASSERT 条件不建立,ASSERT 伪指令将陈述该过错信息。
伪指令格局:
ASSERT Logical_expr
其间:Logical_expr 用于断语的逻辑表达式
伪指令运用举例如下:
ASSERT Top<>Temp ;断语Top 不等于Temp

INFO
汇编确诊信息显现伪指令,在汇编器处理过程中的榜首遍扫描或榜首遍扫描时陈述确诊信息。
伪指令格局:
INFO numeric_expr,string_expr
其间:numeric_expr 数据表达式。若值为0,则在榜首遍扫描时陈述确诊信息。否则在榜首遍扫描时陈述确诊信息。
strint_expr 要显现的字串
伪指令运用举例如下:
INFO 0,”Version 0。1” ;在第二遍扫描时,陈述版别信息
if cont1 > cont2 ;假如cont1 > cont2
INFO 1,”cont1 > cont2” ;则在榜首遍扫描时陈述”cont1 > cont2”

OPT
设置列表选项伪指令。经过OPT 伪指令能够在源程序中设置列表选项。
伪指令格局:
OPI n
其间n 所设置的选项的编码如下:
1 设置惯例列表选项
2 封闭惯例列表选项
4 设置分页符,在新的一页开端显现
8 将行号从头设置为0
16 设置选项,显现SET、GBL、LCL 伪指令
32 设置选项,不显现SET、GBL、LCL 伪指令
64 设置选项,显现宏打开
128 设置选项,不显现宏打开
256 设置选顶,显现宏调用
512 设置先项,不显现宏调用
1024 设置选顶,显现榜首遍扫描列表
2048 设置选项,不显现榜首遍扫描列表
4096 设置选项目,显现条件汇编伪指令
8192 设置选项,不显现条件汇编伪指令
16384 设置选项,显现MEND 伪指令
32768 设置选项,不显现MEND 伪
默许状况下,-list 选项生成惯例的列表文件,包括变量声明,宏打开,条件汇编伪指令及MEND 伪指令,并且列表文件仅仅在第二遍扫描时给出,经过OPT 伪指令,能够在源程序中改动默许的选项。
伪指令运用举例如下:
… ;代码
OPT 512 ;不显现宏调用
… ;代码

TTL 和SUBT
TTL 和SUBT 为刺进标题伪指令。
TTL 伪指令在列表文件的每一页的最初刺进一个标题。该TTL 伪指令的效果在这以后的每一页,直到遇到新的TTL 伪指令。
SUBT 伪指令在列表文件的每页的最初榜首个子标题。该SUBT 伪指令的效果在这以后的每一页,直到遇到新的SUBT 伪指令。
伪指令格局:
TTL title
SUBT subtitle
其间:title 标落款。
subtitle 子标落款。
伪指令运用举例如下:

TTL mainc

SUBT subc con

A.4.3 汇编操控伪指令
汇编操控伪指令用于条件汇编、宏界说、重复汇编操控等。该类伪指令如下:
条件汇编操控: IF、ELSE 和ENDIF
宏界说: MACRO 和MEND
重复汇编: WHILE 及WEND

IF、ELSE 和ENDIF
IF 、ELSE 和ENDIF 伪指令能够依据条件把一段代码包括在汇编程序内或将其扫除在程序之外。
[与IF 同义,|与ELSE 同义,]与ENDIF 同义。
伪指令格局:
IF logical_expr
;指令或伪指令代码段1
ELSE
;指令或伪指令代码段2
ENDIF
其间:logical_expr 用于操控的逻辑表达式。若条件建立,则代码段落在汇编源程序中有用。若条件不建立,代码段1 无效,一起若运用ELSE 伪指令,代码段有用。
伪指令运用举例如下:

IF {CONFIG}=16
BNE __rt_udiv_1
LDR R0,=__rt_div0
BX R0
ELSE
BEQ __rt_div0
ENDIF
IF、ELSE 和ENDIF 伪指令是能够嵌套运用的。

MACRO 和MEND
MACRO 和MEND 伪指令用于宏界说。MACRO 标识宏界说的开端,MEND 标识宏界说久的完毕。用MACRO 及MEND 界说的一段代码,称为宏界说体。这样在程序中就能够经过宏指令屡次调用该代码段。
伪指令格局:
MACRO
{$label} macroname {$parameter} {$parameter}…
;宏界说体。
MEND
其间:$label 宏指令被打开时,label 可被替换成相应的符号,一般为一个标号在一个符号前运用$表明被汇编时将运用相应的值替代$后的符号。
macroname 所界说的宏的称号。
$parameter 宏指令的参数。当宏指令被打开时将被替换成相应的值,相似于函数中的方法参数。
关于子程序代码比较短,而需求传递的参数比较多的状况下能够运用汇编技能。首要要用MACR 和MEND 伪指令界说宏,包括宏界说体代码。在MACRO 伪指令之后的榜首行声明宏的原型,其间包括该宏界说的称号,及需求的参数。在汇编程序中能够经过该宏界说的称号来调用它。当源程序被汇编时,汇编编译器将打开每个宏调用,用宏界说体替代源程序中的宏界说的称号,并用实践的参数值替代宏界说时的方法参数。
伪指令运用举例如下:
MACRO
CSI_SETB ;宏名为CSI_SETB,无参数
LDR R0,=rPDATG ;读取GPG0 口的值
LDR R1,[R0]
ORR R1,R1#0x01 ;CSI 置位操作
STR R1,[R0] ;输出操控
MEND
带参数的宏界说如程序清单:
MACRO
$IRQ_Label HANDLER $IRQ_Exception
EXPORT $IRQ_Label
IMPORT $IRQ_Exception
$IRQ_Label
SUB LR,LR,#4
STMFD SP!,{R0-R3,R12,LR}
MRS R3,STSR
STMFD SP!,{R3}

MEND

WHIL 和WEND
WHILE 和WEND 伪指令用于依据条件重复汇编相同的或简直相同的一段源程序。
伪指令格局:
WHILE logical_expr
;指令或伪指令代码段
WEND
其间:logical_expr 用于操控的逻辑表达式。若条件建立,则代码段在汇编源程序中有用,并不断重复这段代码直到条件不建立。
伪指令运用举例如下:
WHILE no<5
no SETA no+1

WEND
WHILE 和WEND 伪指令是能够嵌套运用的。

A.4.5 杂项伪指令
杂项伪指令在汇编编程规划较为常用,如段界说伪指令,进口点设置伪指令,包括文件伪指令,标号导出或引进声明等,该类伪指令如下:
鸿沟对齐: ALIGN。
段界说: AREA。
指令集界说: CODE16 和CODE32。
汇编完毕: END。
程序进口: ENTRY。
常量界说: EQU。
声明一个符号能够被其它文件引证:EXPORT 和GLORBAL。
声明一个外部符号:IMPORT 和EXTERN。
包括文件:GET 和INCLUDE。
包括不被汇编的文件:INCBIN。
保存符号表中的部分符号:KEEP。
制止浮点指令:NOFP。
指示两段之间的依靠联系:REQUIRE。
仓库8 字节对准:PEQUIRE8 和PRESERVE8。
给特定的寄存器命名:RN。
符号部分标号运用规模的边界:ROUT。

ALIGN
ALIGN 伪指令经过增加补丁字节使当时方位满意必定的对齐方法。
伪指令格局:
ALIGN {expr{,offset}}
其间:expr 数字表达式,用于指定对齐的方法。取值为2 的n 次幂,如1、2、4、8等,不能为0 其没有expr,则默许为字对齐方法。
offset 数字表达式,当时方位对齐到下面方法的地址处:offset+n*expr
鄙人面的状况中,需求特定的地址对齐方法:
(A)Thumb 伪指令ADR 要求地址是字对齐的。而Thumb 代码中地址标号或许不是字对齐的。这时就要运用伪指令ALIGN4 使Thumb 代码中地址标号为字对齐。
(B)因为有些ARM 处理器的Cache 选用了其他对齐方法。如16 字节对齐方法,这时运用ALIGN 伪指令指定适宜的对齐方法能够充分发挥Cache 的功能优势。
(C)LDRD 和STRD 指令要求存储单元为8 字节对齐。这样在为LDRD/STRD 指令分配的存储单元前要运用伪指令ALIGN8 完成8 字节对齐方法。
(D)地址标号一般自身没有对齐要求,而在ARM 代码中要求地起标号对齐是字对齐的,Thumb 代码中要求半字对齐。这样能够运用ALIGN4 和ALIGN2 伪指令来调整对齐方法。
伪指令运用举例如下。
经过ALIGN 伪指令使程序中的地址标号字对齐:
AREA Example,CODE,READONLY ;声明代码段Example
START LDR R0,=Sdfjk

MOV PC,LR
Sdfjk DCB 0x58 ;界说一字节存储空间,字对齐方法被损坏
ALIGN ;声明字对齐
SUBI MOV R1,R3 ;其它代码

MOV PC,LR
在段界说AREA 中,也可运用ALIGN 伪指令对齐,但表达式的数字意义是同的
AREA MyStack,DATA,NOINIT,ALIGN=2 ;声明数据段
;MyStack,并从头字对齐
IrqStackSpace SPACE IRQ_STACK_LEGTH*4 ;间断形式仓库空间
FiqStackSpace SPACE FIQ_STACK_LEGTH*4 ;快速间断形式仓库空间
AbtStackSpace SPACE ABT_STACK_LEGTH*4 ;间断义形式仓库空间
UndtStackSpace SPACE UND_STACK_LEGTH*4 ;未界说形式仓库

将两个字节的数据放在同一个字的榜首个字节和第四个字节中,带offset 的ALIGN对齐:
AREA offsetFxample, CODE
DCB 0x31 ;榜首个字节保存0x31
ALIGN 4,3 ;字对齐
DCB 0x32 ;第四个字节保存0x32

AREA
AREA 伪指令用于界说一个代码段或数据段。ARM 汇编程序规划选用分段式规划,一个ARM 源程序至少需求一个代码段,大的程序能够包括多少个代码段及数据段。
伪指令格局:
AREA sectionname{,attr}{,attr}…
其间:sectionname 所界说的代码段或数据段的称号。假如该称号是以数据最初的,则该称号有必要用“|”括起来,如|1_datasec|。还有一些代码段具有的约好的称号。如|text|表明C 言语编译器发生的代码段或许与C 言语库相关的代码段。
attr 该代码段或数据段的特点。
在AREA 伪指令中,各特点之间用逗号离隔。以下为段特点及相关阐明:
ALIGN = expr。默许的状况下,ELF 的代码段和数据段是4 字节对齐的,expr 能够取0~31 的数值,相应的对齐方为2expr 字节对齐。如expr=3 时为字节对齐。关于代码段,expr 不能为0 或1。
ASSOC = section。指定与本段相关的ELF 段。任何时候衔接section 段也有必要包括sectionname 段。
DODE 为界说代码段。默许特点为READONLY。
COMDEF 界说一个通用的段。该段能够包括代码或许数据。在其它源文件中,同名的COMDEF 段有必要相同。
COMMON 界说一个通用的段。该段不包括任何用户代码和数据,衔接器将其初始化为此。各源文件中同名的COMMON 段共用相同的内存单元,衔接器为其分配适宜的尺度。
DATA 为界说段。默许特点为READWRITE。
NOINIT 指定本数据段仅仅保存了内存单元,而没有将各初始写入内存单元,或许将内存单元值初始化为0。
READONLY 指定本段为只读,代码段的默许特点为READONLY。
READWRITE 指定本段为可读可写。数据段的默许特点为READWRITE。
运用AREA 伪指令将程序分为多个ELF 格局的段,段称号能够相同, 这时同名的段被放在同一个ELF 段中。
伪指令运用举例如下:
AREA Example ,CODE,READNOLY ;声明一个代码,名为Example

CODE16 和CODE32
CODE16 伪指令指示汇编编译器后边的指令为16 位的Thumb 指令。
CODE32 伪指令指示汇编编译器后边的指令为32 位的ARM 指令。
伪指令格局:
CODE16
CODE32
CODE16 和CODE32 伪指令仅仅指示汇编编译器后边的指令的类型,伪指令自身并不进行程序状况的切换。要进行状况切换,能够运用BX 指令操作。
伪指令运用举例如下:
AREA Example CODE,READONLY
CODE32

运用CODE16 和CODE32 界说Thumb 指令及ARM 指令并用BX 指令进行切换。
CODE16 和CODE32 的运用:
AREA ArmThumC,CODE,READONLY
CODE32
ADR R0,ThumbStart+1
BX R0
CODE16
ThumbStart
MOV R0,#10

END

END
END 伪指令用于指示汇编编译器源文件已完毕。每一个汇编源文件均要运用一个END 伪指令,指示根源程序完毕。
伪指令格局:
END

ENTRY
ENTRY 伪指令用于指定程序的进口点。
伪指令格局:
ENTRY
一个程序(能够包括多个源文件)中至少要有一个ENTRY,能够有多个ENTRY。但一个源文件中最多只有一个ENTRY。
伪指令运用举例如下。
AREA, Example, CODE,READNOLY
ENTRY
CODE32
START MOV R1,#0x5F

EQU
EQU 伪指令为数字常量,依据寄存器的值和程序中的标号界说一个称号。*与EQU同义。
指令格局:
name EQU expr{,type}
其间:name 要界说的常量的称号。
expr 依据寄存器的地址值,程序中的标号,32 位地址常量或32 位常量。
type 当expr 为32 位常量时,可用type 指示expr 表明的数据类型。如下示例:
CODE16
CODE32
DATA
EQU 伪指令的效果相似于C 言语中的#define。用于为一个常量界说称号。
伪指令运用举例如下:
T_bit EQU 0x20 ;界说常量T_bit,其值为0x20
PLLCON EQU 0xE01FC080 ;界说寄存器PLLCON,地址为0Xe01F080
ABCD EQU label+8 ;界说ABCD 为label+8

EXPORT 和GLOBAL
EXPORT 声明一个符号能够被其它文件引证。相当于声明晰一个大局变量。
GLOBAL 与EXPORT 相同
指令格局:
EXPORT symbol{[WEAK]}
GLOBAL symbol{[WEAK]}
其间:symbol 要声明的符号称号
[WEAK] 声明其它的同名符优先于本符号被引证。
伪指令运用举例如下:
EXPORT InitStack
GLOBAL Vectors

IMPORT 和EXTERN
IMJPORT 伪指令指示编译器当时的符号不是在根源文件中界说的,而是在其他源文件中界说的,在根源文件中或许引证该符号。
EXTERN 与IMPORT 相同
指令格局:
IMPORT symbol{[WEAK]}
EXTERN symbol{[WEAK]}
其间:symbol 要声明的符号称号。
[WEAK] 指定该选项后,假如symbol 在一切的源程序中都没有被界说,编译器也不会生任何过错信息,一起编译器也不会到当时没有被INCLUDE 进来库中去查找该标号。
运用IMPORT 或EXTERN 声明外部标号时,若衔接器在衔接处理时不能解说该符号,而伪指令中没有[WEAK]选项,则衔接器会陈述过错,若伪指令中有[WEAK]选项,则衔接器不会陈述过错,而是进行下面的操作:
(A)假如该符号被B 或许BL 指令引证,则该符号被设置成下一条指令的地址,该B 或许BL 指令相当于一条NOP 指令。
(B)其它状况下该符号被设置0。
伪指令运用举例如下:
IMPORT InitStack
EXTERN Vectors

GET 和INCLUDE
GET 伪指令将一个源文件包括到当时源文件中,并将被包括的文件在当时方位进行汇编处理。INCLUDE 与GFT 同义。
指令格局:
GET filename
INCLUDE filename
其间:filename 要包括的源文件名,能够运用途径信息。
GET 伪指令一般用于包括一些宏界说或常量界说的源文件。如用EQU 界说的常量,用MAP 和FIELD 界说的结构化的数据类型,这样的源文件相似于C 言语中的头文件,GET、INCLUDE 伪指令不能用来包括方针文件,而INCBIN 伪指令能够包括方针文件。
伪指令运用举例如下:
INCLUDE LPC2106.inc

INCBIN
INCBIN 伪指令将一个文件包括到当时源文件中,而被包括的文件不进行汇编处理。
指令格局:
INCBIN filename
其间:filename 要包括的源文件名,能够运用途径信息。
一般能够运用INCBIN 将一个履行文件或许恣意数据包括到当时文件中,被包括的履行文件或数据将被原封不动地放下当时文件中,编译器从INCBIN 伪指令后边开端持续处理。
伪指令运用举例如下:
NCBIN charlib。bin

KEEP
KEEP 伪指令指示编译器保存符号表中的部分符号。
伪指令格局:
KEEP {symbol}
其间:symbol 要保存的部分标号。若没有此项,则除了依据寄存器处的一切符号将包括在方针文件的符号表中。

NOFP
NOFP 伪指令用于制止源程序中包括浮点运算指令。
伪指令格局:
NOFP

REQUIRE
REQUIRE 伪指令指定段之间的依靠联系。
伪指令格局:
REQUIRE label
其间:label 所需求的标号的称号。
当进行链接处理时,包括了REQUIRE label 伪指令的源文件,则界说label 的源文件也被包括。

PEQUIRE8 和PRESERVE8
PEQUIRE8 伪指令指示当时文件恳求仓库为8 字节对齐。
PRESERVE8 伪指令指示当时文件坚持仓库为8 字节对齐。
伪指令格局:
PEQUIRE8
PRESERVE8
链接器确保要求8 字节对齐的仓库只能被仓库为8 字的对齐的代码调用

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/261956.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部