ARM指令系统特点
ARM指令系统属于RISC指令系统。标准的ARM指令每条都是32位长,有些ARM核还可以执行Thmub指令集,该指令集是ARM指令集的子集,每条指令只有16位。
1 数据类型
ARM处理器一般支持下列6种数据类型:
l8位有符号字节类型数据;
l8位无符号字节类型数据;
l16位有符号半字类型数据;
l16位无符号半字类型数据;
l32位有符号字类型数据;
l32位无符号字类型数据;
有些ARM处理器不支持半字和有符号字节数据类型。在ARM内部,所有指令都是32操作数据。短的数据数据类型只有在数据传送类指令中才被支持当1个字节数据取出后,被扩展到32位,在内部数据处理时,作为32位的什进行处理,并且ARM指令以字为边界。所有Thumb指令都是16位指令时,并且以2个字节为边界。
ARM协处理器可以支持另外的数据类型,包括一套浮点数据类型,ARM的核并没有明确的支持。
2 存储器组织
图3-1所示为存储器组织。
ARM这的地址的低三下四位必须为00,半字地址的最低位为0。字的内容在存储器中的存放通常有两种方式,即小端(little-endian)和大端(big-endian),这两种方式的不同在于最低位字节的地址是否在最高位字节的地址之前。小端方式每个字的低位字节在后,例如0x12345678小端方式存放如下:
地址 内容
A 78
A+1 56
A+2 34
A+3 12
大端方式的存放如下:
地址 内容
A 12
A+1 34
A+2 56
A+3 78
大多数的ARM处理器芯片都不得可以支持上面两种方式,一般缺省为小端。
23222120
19181716
word16
15141312
half-world12 half-word14
111098
word8
7654
byte6 half-word4
3210
byte3 byte2 byte1 byte0
20212223
16171819
word16
12131415
half-world12 half-word14
891011
word8
4567
Byte5 half-word6
0123
Byte0 byte1 byte2 byte3
(a)小端存储器组织 (b)大端存储器组织
图3-1 存储器组织
3 ARM指令特点
1.每条指令的多功能
ARM指令一个重要的特点是它所有的指令都带有条件,例如用户可以测试某个寄存器的什但是直到下次使用同一条件进行测试时,才能有条件的执行这些指令。ARM指令另一个重要的特点是具有灵活的第2操作数,既可以是立即数,也可以是逻辑运算数,使得ARM指令可以在读取数值的同时进行算术和移位操作。它可以在几种模式下操作,包括通过使用SWI(软件中断)指令从用户模式进入系统模式。
2. 协处理器的作用
ARM内核可以提供协处理器指令接口,通过扩展协处理器完成复杂的功能,因此,ARM指令还包含了多条协处理器接口,使用多达16个协处理器;允许将其他处理器能过协处理器接口进行耦合;还包括几种内丰管理单元的变种;包括简单的内存保护到复杂的内存保护到复杂的页面层次。例如,管理存储部件MMU就是ARM内核通过协处理器CP15实现对内存的管理。
3. Thumb指令
ARM有两种指令集:16位Thumb指令集和32位ARN指令集。使用16位的存储器可以降低成本,在这种情况下,Thumb指令集的整体执行速度比32位指令集快,而且提高了代码密度,所以一般用Thumb编译器将C语言程序编译成16位的代码。处理器一开始总在arm状态,可使用BX指令转换到Thumb状态。
4. 具有RISC指令的特点
由于ARM指令属于RISC指令,所以具有RISC指令的特点,指令少,且等长,便于充分利用流水线技术;使用多寄存器,且多为简单的Load与Store指令(从内存中读取某个值,执行完操作后再将其放回内存)。
5. 立即数和直接地址
由于指令统一为32位,无法在1条指令中存放32位立即数。一般立即数为5~12位。采用一些特殊的方法,使它能处理立即数。
同理,直接(或相对)地址一般为24位,但由于指令地址的低2位为00,故寻地范围为±226,相对地址为±225。
3.2 ARM指令系统
3.2.1 ARM指令的寻址方式
每条ARM指令都是32位指令,在大多数情况下,可以有3个操作数,其中第1个操作数或目的操作数一般为基本操作数方式。ARM指令的基本寻址方式有:
l寄存器寻址
例:
ADD R0,R1,R2 ;(R1)+(R2)→R0
l立即数寻址
例:
ADD R3,R3,#2 ;(R3)+2→R3
l寄存器间接寻址
例:
LDR R0,R0,[R3] ;((R3))→R0
l寄存器变址
例:
LDR R0,[R1,#4] ;((R1)+4)→R0
l相对寻址
例:
B rel ;(PC)+rel→PC
另外,每条ARM指令中还可以有第2条和第3条操作数,它们采用复合寻址方式,ARM的复合寻址方式有5种。
1 第2操作数的寻址方式
ARM运算指令和某些数据传送指令除了目的操作数和第1个操作数(它们为寄存器寻址)外,还具有第2操作数。该第2操作数具有以下寻址方式:
(1)立即寻址(#immediate_8*r*2)
由8位立即数和4位移位位r决定。R指定左移rⅹ2位,r=0~15,实际上可移位0,2,4,6,···,28,30。例如:实际的立即数可以为0xFF(r=0),0xFF0(r=2),0xFF000000(r=12), 0xFF000000F(r=14)等。
例:
MOV R0,#20
(2)寄存器直接(Rm)
例:
MOV R0,R1
(3)寄存器移位(Rm,移位码#immed_5)
移位码包括:LSL、LSR、ASR、ROR、RPX的任何一种,移位位数由#immed_5决定。详细请见ARM数据处理类指令的第2操作数。
例:
MOV R0,R1,LSL #1 ;(R1)*2→R0
(4)寄存器间接移位(Rm,移位码Rs)
移位码包括:LSL、LSR、ASR、ROR,移位位数由Rs的内容决定。
例:
MOV R0,R1,R2,LSL,R2 ;(R1)*(R2)→R0
2 字和无符号字节寻址方式
ARM中的取数指令的源操作数和存数指令的目的操作数采用带偏移量的变址方式,可以表示为基址+变址寻址。有效地址寄存器的内容加上偏移量的值。对于字和无符号字节,寻址方式通常可以包括3种:寄存器间接寻址,前变址偏移寻址和后变址偏移寻址。带偏移量的变址包括常数蔌寄存器值。
(1)存器间接寻址)[Rn])
例:
LDR R0,[R1] ;((R1))→R0
STR R0,[R1] ;(R0)→(R1)
(2)前变址偏移寻址([Rn,偏移量]{!})
在数据传送之前,瘵偏移量加到Rn中。其结果作为传送数据的存储器地址。若使用后缀“!”,则结果写回到Rn中,Rn不允许是R15。
该寻址方式又分为下列3种:
①立即数偏移寻址[Rn,#±《immed_12》]{!}
例:
LDR R0,[R1,#5]! ;((R1+5)→R0,(R1)+5→R1
②寄存器偏移[Rn,#±Rm{!}
例
LDR R0,[R!R1,-R2] ;((R1)-(R2))→R0
③移位寄存器偏移
[Rn, ±Rm,LSL #《immede_5》{!}
[Rn, ±Rm,LSL #《immede_5》{!}
[Rn, ±Rm,ASR #《immede_5》{!}
[Rn, ±Rm,ROR #《immede_5》{!}
[Rn, ±Rm,RPX]{!}
例:
LDR R0,[R1,R2,LSL #2] ;((R1)+(R2)*4→R0
(3)后变址偏听偏信移寻址([Rn],偏移量)
Rn的值用作传送数据的存储器地址。在数据传送后,偏移量加到Rn中,结果写回到Rn。Rn不允许是R15。
该寻址方式又分为下列3种:
①立即数偏移[Rn],#±《immde_12》
例:
LDR R0,[R1],#4 ;((R1))→R0,(R1)+4→R1
②寄存器偏移[Rn],±Rm
例:
LDR R0,[R3],-R8 ;((R3))→R0,(R3)-(R8)→R3
③移位寄存器偏移
[Rn],±Rm,LSL#《immde_5》
[Rn],±Rm,LSR#《immde_5》
[Rn],±Rm,ASR#《immde_5》
[Rn],±Rm,ROR#《immde_5》
[Rn],±Rm,RPX
例:
LDR R0,[R3],R8,LSL#2 ;((R3))→R0,(R3)+(R8)*4→R3
3 半字和有符号字节寻址方式
ARM中的半字和有符号字节取数和存数指令的寻址方式与字和无符号字节的寻址方式略有不同。
(1)寄存器间接寻址([Rn])
例:
LDR R0,[R1]
STR R0,[R1]
(2)前变址偏移寻址([Rn,偏听偏信移量]{!})
(3)在数据传送之前,将偏移量加到Rn不允许是R15。
该寻址方式又分为下列两种:
①立即数偏移[Rn,#±《immed_8》]{!}
例:
LDR R0,[R5,#22]! ;((R5+22)→R0,(R5)+22→R5
②寄存器偏移[Rn,±Rm]{!}
例:
STRB R0,[R3,-R8] ;(R0)→(R3)-(R8),(R3)-(R8)→R3
(4)后变址偏听偏信移寻址(Rn),偏移量)
Rn的值用作传送数据的存储器地址。在数据传送后,偏移量加到Rn中,结果写回到R n。Rn不允许是R15。
该寻址方式又分为下列3种:
①立即数偏移[Rn],#±immed_8》
例:
LDR R0,[R3],-R8 ;((R5))→R0,(R5)+22→R5
②寄存器偏移[Rn],±Rm
例:
STR R0,[R3],-R8 ;(R0)→(R3),(R3)-(R8)→R3
4 块寻址
ARM对堆栈的使用一般用多寄存器传送指令,是一种有效的保存处理器状态格多字节传送的有效方式。ARM硬件中的堆栈分为以下4种:]
①满向上生长型:堆栈按高地址方向生长,当前堆栈指针指向一个有效值;
②空向上生长型:堆栈按高地址方向生长,当前堆栈指针指向一个空值;
③满向下生长型:堆栈按低地址方向生长,当前堆栈指针指向一个有效值;
④空向下生长型:堆栈按低地址方向生长,当前指针指向一个空值。
图3-2说明了4条带不同变量和多字节传送前后和内存变化,以及基寄存器的变化情况。指令执行前的基寄存器是R9,指令执行后的基寄存器是R9’。
常见多字节传送指令如表3-1所示。
表3-1内FD|ED|FA|EA后缀只在堆栈时使用。F和E、分别代表指针指向为满或空。A和D分别表示堆栈是否向上或向下生长。例如:堆栈如果是向上生长,STM指令向上存放,LDM指令向下读取。IA、IB、DA、DB后缀在一般数据传送时使用。注意:LDMED与LDMIB是同一条指令(下同)。
图3-2多寄存器传送示意
表3-1常见多字节传送指令
5 协处理器寻址方式
ARM协处理器寻址方式包括以下4种方式:
(1)寄存器直接寻址([Rn]);
(2)前普址偏移寻址([Rn,#±《immed_8*4》]{!});
(3)后变址偏移寻址([Rn],#±《immed_8*4》);
(4)带参数无偏移寻址([Rn],{8-bit copro.Option}。
3.2.2 ARM指令的条件执行
每条ARM指令都是有条件执行,包括特权调用和协处理器指令,可根据执行结果来选择是否更新条件码。若要更新条件码,则指令中须包含后缀“S”。条件占32位指令的高4位。
一些指令(如CMP、CMN、TST、和TEQ不需要后缀“S”。它们唯一的功能就是更新条件标志,且始终更新条件码。更新之前保持不变。没执行的条件指令对标志没影响,一些指令只更新部分标志,不影响其他标志。
可以根据另外指令设置的标志,有条件地执行某条指令,分如下两种情况:
l在更新标志的指令后立即执行;
l在插入的几条不更新标志的指令后执行。
条件码中的N、Z、C和V位的值将决定指令如何执行。条件如表3-2所示。
表3-2 ARM条件码
表3-2中符号“*”的说明:HS、LO、HI、LS这4个条件码指的是无符号数,GE、LT、GT、LE这4个条件码指的是符号数。
3.2.3 Load/Store类指令
1. 单字和无符号字节Load/Store类指令
功能:提供ARM寄存器和内存之间单字节(8位)数据的传送。
格式:
(1)零偏移(zero offet)
LDR|STR{《条件码}}{B}{T} Rd,[Rn] ;((Rn))→Rd
零偏移指的是将Rn的内容作为传送数据的地址。
(2)前变址(pre-indexed offet)
LDR|STR{《条件码》}{B} Rd,[Rn,《offset》]{!}
;((Rn)+offset)→Rd
;有“!”,(Rn)+offset→Rn
;无“!”,Rn不变
前变址指的是在数据传送之前,将偏移量加到Rn中,其结果作为传送数据的存储地址。若使用后缀“!”,则结果写回到Rn中。Rn不允许是Rn15。
(3) 程序相对偏移(program-relative)
LDR|STR{《条件码》}Rd,Ladel ;(Label) →Rd
程序相对偏移指的是由PC计算偏移量,并将PC生成指令。不能使用后缀“!”。“LDR Rd,Label”等价为“LDR Rd,[Rn],offset”等价为“((Rn))→Rd,(Rn)+offset→Rn]”
(4) 后变址(post-indexed offset)
LDR|STR{《条件码》{B}{T} Rd,[Rn],《offset》
后变址指的是将Rn的值用作传送数据的存储器地址,数据传送后,偏移量加到Rn中,结果写回到Rn。Rn不允许是R15。“LDR Rd,[Rn],offset”等价为“((Rn))→,(Rn)+offset→Rn”。
其中:
B 可选后缀。若有B,则传送Rd的最低有效字节。若操作码是LDR,则将Rd的其他字节清零。
T 可选后缀。若有T,那么即使处理器在特权模式下,存储系统也将访问看成是处理器在用户模式下。T在用户模式下无效,不能与前变址偏移一起使用T。
Rd ARM寄存器。
Rn 存储器的基址寄存器,若指令是带写回(write back)的前变址(后缀为“!”)或后变址,或使用T后缀,则不允许Rn与Rd相同。
Offset Rn上的偏移量。
Label 程序相对偏移表达式,必须在当前指令的前指令的±4KB内。
! 可选后缀。若有“!”则将包含偏移量的地址写回到Rn。若Rn是R15,则不能使用后缀“!”。
注释:
(1) offset 说明
前变址和后变址格式中的offset可以是2种形式之一:
(2) exression
其含义是符号表达式,通常是数字整数常量,取值在-4095~+4095之间。
(3) ±Rm{.shift}
其中:
± 可选负号。若有符号“-”,则从Rn中减去偏移量。否则,将偏移量加到Rn中。
Rm 内含偏移量的寄存器。Rm不允许是R15。
Shift Rm的可选移位方法。可以是ASR、LSL、LSR、ROR、RRX的任何一种。详细说明见ARM数据处理类指令的第二操作数。
(4) 字地址对准
大多数情况下,必须保证用于32位传送的地址是32位对准的。
若系统中有协处理器(CP15),则允许对准检查,若允许对准检查,则非字对准的32位传送会引起对准异常。若系统中没有系统协处理品(CP15),或禁止对准检查,则有:
对于STR,将指定的地址取成4的倍数。
对于LDR,则
l将指定的地址取成4的倍数。
l由结果地址读取4个字节的数据。
l依据地址的位[1:0],将读取的数据循环右移1、2或3个字节。
对于小端存储系统,这使寻址的字节占用寄存器的最低有效字节。
对于大端存储系统,这使寻址的字节占用:
-位[31:24],若地址的位[0]为0;
-位[15:8],若地址的位[0]为1。
(5) 使用R15读取
使用R15(程序计数器)读取会引起处理器转移到所读取地址的指令。
对于读取值的位[1:0],有:
l对于ARM体系结构v3及以下版本,忽略位[1:0]。
l对于ARM体系结构v4及以上版本的非T变量,位[1:0]为0。
l对于ARM体系结构v5及以上版本的T变量,则有
-对于读取到R15的值,其位[1:0]不允许是ob10;
-对于读取到R15的值的位[0]置位,则处理器转到Thumb状态。
当使用R15读取时,不能使用后缀“B”或“T”。
(5) 使用R15存储
通常应尽量避免使用R15存储。
若使用R15存储,则存储的值是当前指令的地址加上实现所定义的常量。对于特写的处理器这个常量始终不变。
例 1:将R0中的内容存放进外设中。
LDR R1,UARTADD ;将UART地址放进R1中
STRB R0,[R1] ;将数据放进外设中
UARTADD & &1000000 ;UARTR的地址值
例 2:
LDR R8,[R10]! ;((R10))→R8
LDRNE R2,[R5,#960]! ;Z≠14时((R5)+960)→R2,(R5)+960→R5
STR R2,[R9,#consta-struc] ;consta-struc是常量的表达式,该常量的范围为1~4095
STRB R0,[R3,-R8,ASR#2] ;R0→(R3-R8/4),存储R0的最低有效字节,R3和R8不变
STR R%,[R7],#-8 ;读取一个字,该字位于标号loacaldata所在地址
2. 半字和有符号字节Load/store类指令
功能:提供ARM寄存器和内存之间半字(16位)和有符号字节(8位)数据的传送。
格式:
(1) 零偏移(zero offset)
LDR|STR{《条件码》}H|SH|SB Rd,[Rn]
(2) 前变址(pre-indexed offset)
LDR|STR{《条件码》}H|SH|SB Rd,[Rn,《offset》]{!}
(3) 程序相对偏移(pregram-relatve)
LDR|STR{《条件码》}H|SH|SB Rd,Label
(4) 后变址(post-indexed offset)
LDR|STR{《条件码》}H|SH|SB Rd,[Rn],《offset》
其中:
H|SH|SB 表示数据类型选择。
SH 对有符号半字(仅LDR);
H 对无符号半字;
SB 对有符号字节(仅LDR)。
Label 程序相对偏移表达式。必须是在当前指令的±255字节范围内。
Offset 加在Rn上的偏移量。含义见注释。
Rn和“!”同前面第1条(LDR和STR字和无符号字节)。
注释:
(1) offset说明
前变址和后变址格式中的offset可以是下两种形式之一:
①expression含义同前一条指令,取值在-255~+255范围之间。
②±Rm含义同前一条指令。
(2) 半字传送的地址对准
半字传送的地址必须是偶数。
若系统有系统协处理器(CP15),则可允许对准检查。若允许对准检查,则非对准的16位传送会引起对准异常。若系统没有系统协处理器(CP15)或禁止对准检查,则有
l非半字对准的16位读取将使Rd内容不可靠;
l非半字对准的16位存储将使在address和(address-1)的2个字节不可靠。
(3) 不能将半字或字节读取到R15。
例 1:
LDREQSH R11,[R6] ;(有条件地)R11←[R6],读取16位半字,有符号扩展到32位
LDH R1,[R0,#22] ;R1←[R0+22],读取16位半字,零扩展到32位
STR R4,[R0+R1] ;存储最低的有效半字到R0+R1地址开始的两个字节,地址写回到
;R0
LDRSB R6,constf ;读取位于标号constf地址中的字节,有符号扩展
例 2:
ADD R1,ARRAY1 ;ARRAY1 为半字数组
ADR R2,ARRAY2 ;ARRAY2为字数组
ADR R3 ENDARR1 ;ARRAY1+2
LOOP LDRSH R0,[R1],#2 ;取得有符号半字数,扩展为字
STRR0,[R2],#4
CMP R1,R3
BLT LOOP
3. 双字Load/Store类指令
功能:提供ARM寄存器和内存之间双字(64位)数据的传送。
格式:
(1) 零偏移(zero offset)
LDR|STR{《条件码》}D Rd,[Rn]
(2) 前变址格式(pre-indexed offset)
LDR|STR{条件码》}D Rd,[Rn,《offset》]{!}
(3) 程序相对偏移(pregram-relatve)
LDR|STR{《条件码》}D Rd,LABEL
(4) 后变地址格式(post-indexed offset)
LDR|STR{《条件码式》}D Rd,[Rn],《offset》
其中:
Rd 读取或指令寄存器其中的一个,另一个是R(d+1).Rd必须是偶数寄存器,且不是R14.
Rn 除非指令为零移,或不带写回的前索引,否则R不允许是Rd和R(d+1)相同。
Offset 加在Rn上的偏移量。含义同3.2.3节第1条指令。
Label 程序相对偏移表达式.Label必须是在当前指令的±255字节范围内。
! 可选后缀。若有”!”,则包含偏移量的最后地址写回到Rn.
注释:
对于双字节传送,地址必须是8的倍数。若系统有系统协处理器,可允许对准检查。若允许对准检查,慢非双字准的64位传送将引起对准异常。该指令适用于ARMv5TE指令系统及以上版本。
例:
LDARD R6,[R11] ;((R11)→R6,((R11)+4)→R7
STRD R4,[R9,#24] ;(R4)→(R9)+24,(R5)→(R9)+24
4. 多寄存器Load/Store类指令
功能:读取和存储多个寄存器,可以传送R0~R15的任何组合。
格式:
(1) 标准格式
LDR|STM{《条件码》}《mode》Rn{!}《寄存器》
(2) 非用户模式下,用下面可以同时把当前的SPSR写入CPSR中,转向用户模式,寄存器组饮包含PC.
LDM{《条件码》}《mode》Rn{!},《寄存器组+PC》^
(3) 非用户模式下,用下面格式可以实现访问用户模式的寄存器,但寄存器组不包含PC.
LDM|STM{《条件码》}《mode》Rn,《寄存器组-PC》^
其中:
mode IA、IB、DA、DB、FD、ED、FA、EA之一。
Rn 基址寄存器,装有传送数据的初始地址。Rn是不允许是R15。
! 可选后缀。若有“!”,则结果地址写回到Rn。
Reglist读取或存储的寄存器列表,包含在括号中,它也可包含寄存器的范围。若包含多于1个寄存器列表或包含寄存器范围,则必须用逗号分开。
^ 可选后缀,不允许用户模式或系统模式下使用。它有两个目的:
l操作码是LDM且reglist中饱包含PC(R15),那么出除了正常的多寄存器传送外,将SPSR也拷贝到CPSR中。这用于从异常处理返回,仅在异常模式下使用。
l数据传入或传出的是用户模式的寄存器,而不是当前模式的寄存器。
注意:对于LDM指令,如包含PC,位0=1时,转至Thumb状态。寄存器组中一般不应有Rn,它至少有1个寄存器。FD、ED、FA、DA用于堆栈操作;IA、IB、DA、DB用于一般的数据传送。
注释:
(1)非字对准地址
这些指令忽略地址的位[1:0]。在带有系统协处理器的系统中,若对准检查使能,则这2位的非零值将引起对准异常。
(2)读取到R15
到R15(程序计数器)的读取将引起处理器转移到读取地址处的指令。在ARM体系结构v5及以上版本的T变量中若读取的位[0]置位,则到R15的读取将导致处理器切换到执行Thumb指令。
(3)带写回的存/取基址寄存器
如果Rn包含在寄存器列表中,且用后缀“!”,指明要写回(write back),那么:
l若操作码是STM,县城Rn是寄存器列表中数字最小的寄存器,则将初值保存。
lRn的读取和储存值不可预知。
例1:若保存3个工作寄存器状态和返回地址:
STMFD R13!,{R0-R2,R14}
若恢复3个工作寄存器状态和返回地址:
LDMFD R13!,{R0-R2,R14}
例2:
LDMFD R8,{R0,R2,R9} ;((R8))→R0
;((R8)+4)→R2
;((R8)+8)→R9
STMDB R1!,{R3-R6,R11,R12} ;(R3)→R1-4
;(R4)→R1-8
;(R5)→R1-12
;(R6)→R1-16
;(R11)→R1-20
;(R12)-24→R1
STMD R13!,{R0,R4-R7,LR} ;寄存器进栈
例3:子程序调用
SUMB1 STMFD SP!,{R0-R2,R14} ;保护R0~R2和返回地址
…… ;其它指令
BL ;允许子程序嵌套
…… ;其它指令
LDMFD SP!,{R0-R2,R15} ;恢复R0~R2,返回子程序调用程序后执行
5. 预读取PLD指令
功能:cache预读取(PLD,PreLoad),使用PLD指示存储系统从后面几条指令所指定的存储器地址读取,存储系统可使用这种方法加速以后的存储器访问。
格式:
PLD[Rn,{offset}]
其中:
Rn 存储器的基址寄存器。
Offset 加在Rn上的偏移量。含义同3。2。3节第1条指令。
注释:
PLD指令适用于ARM v5TE指令及以上版本。
例:
PLD [R9,#-2481]
PLD [R0,#av*4] ;av*4必须在汇编时求值,范围为-4095~4095内的整数
PLD [R5,r8,Lsl#2]
6. 内存和寄存器交换类指令
功能:用一条指令实现在寄存器和存储器之间交换数据。
格式:
SWP{《条件码》}{B} Rd,Rm,[Rn] ;((Rn))→Rd,Rm→Rn
;n≠m,d
其中:
B 可选后缀。若有B,则交换字节;否则,交换32位字。
Rd ARM寄存器。数据从存储器读取到Rd。
Rm ARM寄存器。Rm的数据存储到存储器。Rm可以与Rd相同。Rn必须与Rd和Rm不同。
注释:
对非字对准地址的处理同LDR和STR指令。
例:
ADR R0,SEMAPHORE
SWPB R1,R1,[R0] ;交换字节
3.2.4 ARM数据处理类指令
大多数ARM通用数据处理有一个灵活的第2操作数(flexi second operand)。在每一个指令的格式中以“operand2”表示。
第2条操作数有如下2种可能的格式:
(1)#immed_8r
常量的表达式。常量必须对应于8位位图(pattern0。该位图在32位字中,被循环移位偶数位(0,2,4,8,…,26,28,30)。合法常量:0xFF、0xFF000、0xF0000000F。非法常量:0x101、0xFF04、0xFF003、0xFFFFFFFF。
(2)±Rm {,shift}
Rm 存储第2操作数ARM寄存器。可用各种方法对寄存器中的位图进行移位或循环移位。在指令操作的结果用作第2操作数,但Rm本身不变。
Shift Rm的移位方法,可以是下面的任何一种:
ASR n 算术右移n位(1≤n≤32)。
LSL n 逻辑左移n位(0≤n≤31)。
LSR n 逻辑右移n位(1≤n≤32)。
ROR n 循环右移n位(0≤n≤32)。
RRX 带进位的循环右移1位。
Type Rs 其中:Type ASR、LSR、ROP中的种;
Rs 提供移位量的ARM寄存器,仅使用于最低有效字节。
ASR、LSL、LSR、ROP和RRX的详细说明如下:
① ASR
若将Rm中的内容看作是有符号的补码整数,那么算术右移(ASR,Arithmetic Shift Right)n位,即Rm中的内容除以 。将原来的位拷贝到寄存器左边的n位中(即空出的最高补符号位),见图3-3(a)。
② LSR和LSL
若将Rm中内容看作是无符号整数,则逻辑右移(LSR,Logical Shift Right)n位,即Rm中的内容除以 ,寄存器左边的n位置0,见图3-3(b)。
若将Rm中内容看作是无符号整数,则将逻辑左移(LSR,Logical Shift Left)n位,即Rm四的内容乘以 ,可能会出现溢出且无警告,寄存器右边的n 位置0,见图3-3(b)。
③ ROR
循环右移(ROR,Rotate Right)n位,把寄存器内容循环右移,见图3-3(c)。
④ RRX
若将Rm中内容看作是无符号整数,则带进位右环移n位,寄存器左边的n位置0,见图3-3(d)。
图3-3移位操作过程
1 数据运算类指令
功能:完成数据在寄存器中的运算,这些运算包括32位数据的算术、位操作,其中某一个操作数可以经过移位或循环运算。
格式:
《操作码》{《条件码》}{S}Rd,Rn,Operand2
操作码 包括ADD、SUB、RSB、ADC、SBC、RSC、AND、ORR、EOR、BIC、MOV、MVN、CMP、CMN、TST和TEQ指令。
其中:
S 可选后缀。若指定S,则根据操作结果更新条件标志(N、Z、C和V)。
Rd ARM结果寄存器。
Rn 存储第1操作数的ARM寄存器。
Operand 第2操作数。详细说明请见3.2.4节第2操作数说明。
ARM的数据运算类指令用法如表3-3所示。
表3-3 ARM运算类指令
注释:
(1) 条件码标志
若指定S,那么ADD、SUB、RSB、ADC、SBC、RSC指令根据结果更新标志N、Z、C和V。CMP、CMN、TST和TEQ指令不需S。注意:减法(含比较)够减时,C=1。而AND、OPR、EOP、BIC、MOV和MVN指令将:①根据结果更新标志N和Z;②计算Operand2时更新标志C;③不影响V标志。
(2) R15的使用
ADD、SUB、RSB、ADC、SBC、RSC、AND、ORR、EOR、BIC、MOV和MVN指令将R15作为Rn使用,那么使用的值是指令的地址加8。
若将用R15作为Rd,则
l执行转移到结果对应的地址。
l若后缀“S”,则将当前模式的SPSR拷贝到CPSR。可以使用这点从异常返回。
在有寄存器控制移位的任何数据处理指令中,不能将R15作为Rd或任何操作数来使用。
CMP、CMN、TST和TEQ指令若将R15用作Rn,则使用的值是指令的地址加8。在有寄存器控制移位的任何数据处理指令中,不能将R15用于任何操作数。
例1:
ADD R2,R1,R3 ;(R1)+(R3)→R2
例2:
SUBS R2,R2,#1 ;(R2)-1→R2
BEQ LABEL ;如等于0,转向LABEL
例3:R0中的内容乘以5:
ADD R0,R0,R0,LSL #2 ;(R0)*5→R0
ADD R0,R0,LSL #1
例4:R0中的内容乘以10:
ADD R0,R0,R0,LSL #2 ;(R0)*10→R0
MOV R0,R0,LSL #1
例5:R0中的内容乘以10,再加R1中的内容:
ADD R0,R0,R0,LSL #2 ;(R0)*10+R1→R0
MOV R0,R1,R0,LSL #1
例6:
ADDS R2,R2,R0 ;(R3R2)+(R1R0)→R3R2
ADC R3,R3,R1
例7:
ADDNE R0,R1,#&ff ;if Z=0 then(R1)+0xff→R0
例8:R1中的内容乘7,送给R0:
RSB R0,R1,R1,LSL #3 ;(R1)*7→R0
2 前导零计数指令
功能:CLZ(Count Leading Zeros)指令对Rm中值的高位(leading zeros)个数进行计数,结果放到Rd中。若源寄存器全为0,则结果为32。若[31]为1,则结果为0。
格式:
CLZ{《条件码》}Rd,Rm
其中:
Rd ARM结果寄存器,Rd不允许是R15。
Rm 操作数寄存器。
注释:
CLZ指令适用于ARM v5指令系统以上版本。这条指令不影响条件码标志。
例:
CLZ R4,R9
CLZNE R2,R3
3 乘法指令
格式:
(1) MUL{《条件码》}{S},Rd,Rm,Rs
(2) MLA{《条件码》}Rd,Rm,Rs,Rn
其中:
Rd 结果寄存器。
Rm,Rs,Rn 操作数寄存器。
R15不能用于Rd,Rm,Rs或Rn。Rd不能与Rm相同。
(3) 《mul》{《条件码》}{S}RdHi,RdLO,Rm,Rs
mul中类型包括UMILL、UMLAL、SMULL、SMLAL。
其中:
RdLo,RdHi ARM结果寄存器。对于UMLAL和SMLAL,这两个寄存器用于保存累加值。
Rm,Rs 操作数寄存器。
R15不能于RdHi,RdLo,Rm或Rs。RdLO、RdHi和Rm必须是不同的寄存器。
(4) SUML《x》《y》{条件码}Rd,Rm,Rs
其中:
《x》 B或T。B意味着使用Rm的低端(位[15:0]),T意味着使用Rs的高端(位[31:16])。
《y》 B或T。B意味着使用Rm的低端(位[15:0]),T意味着使用Rs的高端(位[31:16])。
Rd 结果寄存器。
Rm,Rs 乘数寄存器。
R15不能用于Rd,Rm和Rs。Rd、Rm、Rs可用相同的寄存器。
(5) SMLA《x》《y》{条件码}Rd,Rm,Rs可用相同的寄存器。
其中:
《x》、《y》、Rm和Rn含义同SMUL《x》《y》指令。
R15不能用于Rd、Rm和Rs。Rd、Rm、Rs可用相同的寄存器。
(6) SMULW《y》{条件码}Rd,Rm,Rs
其中:
《y》、Rd、Rm、Rs和Rn含义同SMUL《x》《y》指令。
R15不能用于Rd、Rm和Rs。Rd、Rm、Rs可用相同的寄存器。
(7) SMULW《y》{条件码}Rd,Rm,Rs
其中:
《y》、Rd、Rm、Rs和Rn含义同SMUL《x》《y》指令。
R15不能用作Rd、Rm、Rs或Rn的任何一个。任何Rd、Rm、Rs或Rn可用相同的寄存器。
(8) SMULW《y》{条件码}Rd,Rm,Rs,Rn
其中:
《y》、Rd、Rm、Rs和Rn含义同SMUL《x》《y》指令。
R15不能用作Rd、Rm、Rs或Rn的任何一个。任何Rd、Rm、Rs或Rn可用相同的寄存器。
(9) SMULW《y》{条件码}RdLo,RdHi,Rm,Rs
其中:
《x》《y》含义同SMULxy指令。
RdHi,RdLo 结果寄存器。它们也存储累加值。
Rm,Rs 乘数寄存器。
ARM乘法类指令用法如表3-4所示。
表3-4 ARM乘法类指令
注释:
若指定S标志位,则MUL和MLA指令将:①根据结果更新标志N和Z;②不影响标志V;③在ARM v4以前版本中标志C不可靠;④在ARM v5及以后版本中不影响标志C。
若指定结果S标志位,则UMULL,UMLAL,SMULL和SMLAL指令将:①根据结果更新标志N和Z;②在ARM v4及以前版本中标志C不可靠;③在ARM v5及以后版本中不影响标志C或V。
SMULAxy指令不影响任何条件码标志。若加法出现溢出,则置位标志Q。使用MRS指令读标志Q的状态。注意:这条指令永远也不会清除Q标志。要清除Q标志,则应使用MSR指令。
SMULxy、SMULWy、SMLALxy指令不影响任何条件标志。
SMULxy、SMULWy、SMLALxy、SMLAxy和SMLAWy指令适用于ARM v5TE指令系统及以上版本。
例:
SMLALLES R8,R9,R7,R6
SMULLNE R0,R1,R9,R0
4 QADD、QSUB、QDAAA和QDSUB指令
功能:这4条指令属于DSP增强指令,完成饱和加、饱和减,饱和乘2加、饱和乘2减4种饱和运算功能。
格式:
《操作码》{条件码}Rd,Rm,Rn
《操作码》包括:QADD、QSUB、QDADD和QDSUB指令。
其中:
Rd 结果寄存器。
Rm,Rn 操作寄存器。
注释:
饱和运算是DSP指令所特有的功能,对加/减法指令的结果做了如下修改:
(1) 如果加/减法指令的结果在- ~ -1之间,饱和运算的结果取加/减法指令的结果。
(2) 如果加/减法指令的结果大于 -1,饱和运算的结果取最终结果为 -1。
(3) 如果加/减法指令结果小于- ,饱和运算的结果取最终结果为时尚- 。
QDADD和QDSUB指令计算SAT(Rm+SAT(Rn*2)),饱和可发生在加倍操作,加法上,或两咱情况下同时发生。或饱和仅发生在加倍操作上,则标志Q置位,但最后结果是不饱和的。SAT意为饱和运算。
这些指令不影响标志N、Z、C和V。若出现饱和,则置位Q标志。可使用MRS指令来读Q标志的状态。注意:即使是饱和不出现,这些指令也从不清除Q标志。使用MSR指令清除Q标志。
QADD、QSUB、QDADD和QDSUB指令适用于ARM v5TE指令系统及以上版本。
例:
QADD R0,R1,R9 ;SAT(R1+R9)→R0
QDSUBLT R9,R0,R1 ;SAT(R0-SAT((R9)*2))→R9
3.2.5 ARM转移类指令
ARM转移类指令完成循环、调用子程序和从ARM状态转向Thumb状态等功能,包括B、BL、BX和BLX指令。
1 转移/转移带链接类指令
功能:B、BL指令完成当前执行指令地址的转移,偏移地址量可以达到32M,BL指令可以把转移指令后第1条指令的地址放进链接寄存器R14中完成连接作用,通常用来完成子程序的调用。
转移地址通常由24位有符号数组成,由于指令地址的代位为00,故可进行2位的左移运算,因此总的偏移量达到±32M。
格式:
B{L}{《条件码》}《Label》
其中:
Label 程序相对偏移表达式。
注释:
BL(Branch and Link)指令将下一条指令的地址拷贝到R14(LR,链接寄存器)并引起处理器转移到Label。BL指令(L=1),等价于先把(PC)→R14,再(PC)+offset→PC.
机器级的B和BL指令限制在当前指令的± (±32M)字节范围内。但是,即使Label走超出了该范围,汇编可以使用这些指令。
例1:条件转移。
CMP R0,35 ;如果R0小于5
BLT SUB1 ;则转SUB1
BGE SUB2 ;否则转SUB2
例2:程序调用。
BL SUB ;调用子程序SUB
… ;返回点
SUB … ;子程序入口
MOV PC,R14 ;执行完返回
例3:执行循环。
MOV R0,#10 ;设置循环次数
LOOP …
SUBS R0,#1 ;循环次数减1
BNE LOOP ;如果循环次数不为0,继续循环
… ;否则结束循环
2 转移交换、转移带链接和交换指令BX,BLX
功能:BX、BLX指令用来支持者Thumb指令集,可以全处理器由ARM指令转向Thumb指令或者由于某种原因Thumb指令返回到执行ARM指令。
格式:
(1)B{L}X{《条件码》}寄存器Rm
(2)BLX《Label》
其中:
RM 含有转移地址的寄存器。Rm的位[0]不用来作为地址的一部分。若Rm的位[0]为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为Thumb代码。若Rm的位[0]为0,则位[1]就不能为1。
注释:
在指令格式中,寄存器Rm中可以存放转移地址的值,如果Rm中的第0位为1,处理器将Thumb指令;如果为0,执行ARM指令。
在指令格式2中偏移地址量的计算与B或BL指令相同。
BLX指令有如下用法:
l将下一条指令的地址拷贝到R14中(LR,链接寄存器)。
l转移到Label或Rm中的地址。
l若下面的两条中的任何一条成立,则指令集切换到Thumb,即
-Rm的位[0]为1;
-使用“BLX Label“形式。
机器级的“BLX Label“指令不能转移当前指令±32MB范围之外的地址BLX指令格式1可以是条件或者无条件执行,而指令格式2是无条件执行。
例1:无条件转移。
BX R0 ;按R0内容转移
;如果R[0]为1,转Thumb状态
例2:Thumb子程序调用。
CODE32 ;ARM代码
…
BLX TSUB ;Thumb代码执行
TSUB … ;Thumb指令TSUB子程序
BX R14 ;返回ARM代码
3.2.6 ARM协处理器类指令
ARM协处理器指令完成与协处理器有关的操作,如协处理器内部寄存器之间的数据传送、协处理器与存储器之间的数据传送、协处理器与CPU寄存器之间的数据传送。这些指令依赖于使用特写的协处理器。协处理器设计者可以自由地按需要设计处理器的功能,而且这些指令通常借助于汇编器。
1CDP和CDP2指令(CDP,Coprocessor Data operation)
功能:完成协处理器寄存器数据操作。
格式:CDP{条件码} CP#,opcodel,CRd,CRn,CRm{,opcode2}
CDP2 CP#,opcodel,CRd,CRn,CRm{,opcode2}
其中:
CP# 指令操作的协处理器名。标准名为pn,n为0~15范围内的整数。
Opcode1 协处理器的特定操作码。
CRzn,CRm,CRn 协处理器寄存器。
Opcode2 可选的协处理器特定操作码。
注释:
CDP2指令设置条件码为0b1111,为协处理器设计者提供额外的opcode空间。CDP2指的是适用于ARM v5指令系统及以上版本。
例:
CDP p1,10,C1,C2,C3 ;协处理器1中的处理器C2和C3完成操作10然后
;将结果放在C1中
CDPEQ p2,5,C1,C2,C3 ;如果Z位置1,那么协处理器2中的C2和C3完成
;操作5(子操作2),然后将结果放在C1中
2 LDC和STC指令
功能:在存储器和协处理器之间传送数据。
格式:
(1) 零偏移格式
LDC|STC{《条件码》}{L}《CP#》,CRd,[Rn]
(2) 前变址格式
LDC|STC{《条件码》}{L}《CP#》,CRd,[Rn,#offset]{!}
LDC2|STC2{《 CP#》》},CRd, [Rn,#offset]{!}
(3) 后变址格式
LDC|STC{《条件码》}{L}《CP#》,CRd,[Rn],#offset
LDC2|STC2{《 CP#》》},CRd, [Rn],#offset
其中:
L 可选后缀,指明是长整数传送。
CP# 指令操作的协处理器名。标准名为pn,其中n为0~15范围内的整数。
CPd 用于读取或存储的协处理器寄存器。
Rn 存储器基址寄存器。若指定R15,则使用的值是当前指令地址加8。
Offset 偏移量,其值必须为4的整倍数,范围在0~1020之间。
注释:
LDC2和STCC2指令设置条件码条件码为b1111,为协处理器设计者提供额外的opcode空间。LDC2和STC2指令适用于ARM v5指令系统及以上版本。注意:LDC2和STC2始终是无条件的。
例1:
LDC p6,CR1,[R4] ;将存储器中的内容取至协处理器6
;寄存器CR1中R4为所以内容地址
例2:
LDC p6,CR4,[R2,4] ;将存储器中的内容取至协处理器6
;寄存器CR4中R2+4为所以内容地址
例3:
STC p8,CR8,[R2,#4]! ;将协处理器8寄存器CR8中的内容存
;至存储器中R2+4为所存内容的地址
;然后,R2=R2+4
例4:
STC p6,CR9,[R2],#-16 ;将协处理器6寄存器CR9中的内容存
;至存储器中R2为所存内容的地址
;然后,R2=R2-16
3 MRC、MRC2、MCR和MCR2指令
功能:在协处理器与ARM寄存器之间传送数据。
格式:
(1)从协处理器传送至ARM寄存器
MRC{《条件码》}《CP#》,《Opcode1》,Rd,CRn,CRm{,《Opcode2》}
MRC2 《CP#》,《Opcode1》,Rd,CRn,CRm{,《Opcode2》}
(2)从ARM寄存器传送至协处理器
MCR{《条件码》}《CP#》,《Opcode1》,Rd,CRn,CRm{,《Opcode2》}
MRC2 《CP#》,《Opcode1》,Rd,CRn,CRm{,《Opcode2》}
本组指令格式中所有操作数的含义同(CDP和CDP2)。
注释:
MRC2和MCR2指令设置条件码为0b1111,为协处理器设计者提供额外的操作码字段。MRC2和MCR2指令适用于ARM v5指令系统及以上版本。注意:MRC2和MCR2始终是无条件的。
例1:
MRC p15,R4,C0,C2,3 ;协处理器15中的寄存器C0和C2完成
;操作5(子操作3),然后将结果传到
;CPU寄存器4中
例2:
MCR p14,1,R7,C7,C12,6 ;协处理器14在CPU寄存器7中完成
;操作1(子操作6,然后将结果传到协
;处理器14的寄存器C12中
4 MCRR和MRRC指令
功能:在2个ARM寄存器和协处理器之间进行数据传送。
格式:
MRRC{《条件码》}《CP#》,《Opcode1》,Rd,CRn,CRm
MCRR{《条件码》}《CP#》,《Opcode1》,Rd,CRn,CRm
本指令格式中所有操作数的含义同本小节第1条指令(CDP和CDP·)。MCRR和MRRC指令适用于ARM v5TE指令系统及以上版本。
3.2.7 ARM杂项指令
1 状态寄存器传送至通用寄存器类指令
功能:将状态寄存器的内容传送至通用寄存器。
格式:
MRS{《条件码》}Rd,CPSR}SPSR
其中:
Rd 目标寄存器,Rd不允许R15。
R=0 将CPSR中的内容传送目的寄存器。
R=1 将SPSR中的内容传送至目的寄存器。
注释:
MRS与MSR配合使用,作为更新PSR的读-修改-写序列的一部分。例如:改变处理器或清除标志Q。注意:当处理器在用户模式或系统模式下,一定不能试图访问SPSR
这条指令不影响条件码标志。
例:
MRS R0,CRSR ;将CPSR中的内容传送至R0
MRS R3,SPSR ;将SPSR中的内容传送至R3
2 通用寄存器传送至状态寄存器传送指令
功能:将通用寄存器的内容传送至状态寄存器。
格式:
MSR{《条件码》CPSR_f|SPSR_f,《#ommed_8r》
MSR{《条件码》CPSR_《field》|SPSR_《field》,Rm
其中:
《field》字段可以是以下之一或多种:
lC:控制域屏蔽字段(PSR中的第0位到第7位);
lX:扩展域屏蔽字段(PSR中的第8位到第15位);
lS:状态域屏蔽字段(PSR中的第16位到第32位);
lF:标志域屏蔽字段(PSR中的第24位到第31位)。
immed_8r 值数字常量的表达式。常量必须对应8位位图。该位图在32位字中循环移位偶数数位。
Rm 源寄存器。
注释:
同前一条指令(MRS)。
例1:设置N、Z、C、V标志。
MSR CPSR_f,#&f0000000 ;仅高位有效,其他必须为0
例2:
仅置位C标志,保留N、Z、V标志。
MRS R0,CPSR ;将CPSR中的内容传送至R0
ORR R0,R0,#&1f ;置位R0的第29位
MSR CPSR_c,R0 ;再将R0中的内容传送至CPSR
3 软件中断指令SWI
格式:
SWI{《条件码》immed_24
其中:
immed_24 表达式,其值范围为0~ -1的整数(24位整数)。
注释:
(1) SWI指令用来执行系统调用,处理器进入管理模式,并从地址0x08开始执行指令《24位立即数》并不影响指令的执行,由系统所解释。CPSR保存到管理模式的SPSR中执行转移到SWI向量。
(2) 条件码标志。这条指令不影响条件码标志。
例1:输出字符“A”
MOV R0,#“A” ;从R0中得到“A”
SWI SWI_WriteC ;然后显示
例2:通过SWI指令输出字符串
…
BL STROUT ;输出如下信息
= “Hello World”,&0a,&0d,0
… ;返回
STROUT LDRB R0,R[14],#1 ;得到字符
CMP R0,#0 ;检查结束标记
SWINE SWI_WriteC ;如果没有结束,则继续
BNE STROUT ;…循环
ADD R14,#3 ;字对齐
BIC R14,#3
MOV PC,R14 ;返回
例3:结束用户程序返回监控程序
SWI SWI _Exit ;返回
4 断占指令(v5T)
格式:
BKPT immmed_16
其中:
immmed_16 表达式,基值范围为0~65536内的整数(16位整数)。
注释:
支持软件调试,执行时中断正常指令,进入相应的调试子程序。BKPT指令适用于ARM v5指令系统及以上版本。
例:
BKPT
3.3 Thumb指令系统
并非所有的ARM处理器都可以执行Thumb指令,在指令集名中,含有T的均可执行Thumb指令,如ARM7TDMI。
CPSR中的T标志决定是执行Thumb指令还是ARM指令,如置位,执行Thumb指令,否则执行ARM指令。
ARM在复位以后,执行ARM指令。通常至Thumb指令的执行是由一条转移和交换指令完成的,如BX指令。但是例程处理程序中如果使用数据处理指令或者多寄存器调用指令,也会转移到Thumb指令中去。如果例程处理完毕,也将返回ARM指令中。
必须明确的是Thumb指令系统必须包括ARM代码,至少是初始化和例程入口部分。
Thumb指令集是ARM指令集的子集,Thumb只使用有限的ARM寄存器。Thumb指令一般可以完全访问通用寄存器R0~R7(称为低寄存器),R13用作堆栈指针,R14用作链接寄存器,R15用作PC。Thumb中的一些指令可以访问其余的寄存器如R8~R15(称为高寄存器),算术运算和逻辑运算指令可以访问CPS2中的标志位。
大部分的Thumb 指令与ARM指令类似,不过在寄存器、立即数、寻址等方面会有些差异,Thumb和ARM指令性计划集的区别一般有以下几点:
l转移指令;
l数据传送指令;
l单寄存器Load和Store指令;
l多寄存器Load和Store指令。
Thumb指令集没有协处理器指令、信号量(samaphore)指令以及访问CPSR或SPSR的指令。
(1) 转移指令
转移指令用于:
l向后转移形成循环;
l条件结构向前转移;
l转向子程序;
l处理器从Thumb状态切换到ARM状态。
程序相对转移,特别是条件转移与在ARM状态下相比,在范围上有更多的限制,转向子程序只能是无条件转移。
(2) 数据处理指令
这些指令对通用寄存器进行操作,在许多情况下,操作的结果必须放入其中一个操作数寄存器中,而不是第3个寄存器中。数据处理操作比ARM状态更少,访问寄存器R8~R15受到一定限制。
MOV或ADD指令可访问寄存器R8~R15,数据处理指令总是更新CPS2中的ALU状态标志。访问寄存器R8~R15的Thumb数据处理指令不能更新标志。
(3) 单寄存器Load和Store指令
这些指令从存储器读取1个寄存器值,或把1个寄存器值存储到存储器。在Thumb状态下,这些指令只能访问寄存器R0~R7。
(4) 多寄存器Load和Store指令
LDM和STM将任何范围为R0~R7的寄存器子集从存储器读取以及存储到存储中。
PUSH和POP指令使用堆栈指针(R13)作为基址实现满递减堆栈。除可传送R0~R7外,PUSH还可以用于存储连接寄存器,POP可以用于读取程序指针。
Tuhmb指令主要有以下几类指令组成:Tuhmb Load/Store类指令;Thumb数据运算类指令;Thumb转移类指令,以及软件中断指令。
3.3.1 Thumb Load/Store类指令
1 Thumb单寄存器Load/Store指令
Thumb单寄存器传送类指令是ARM单寄存器传送类指令的一个子集,和ARM有相同的指令格式。
Thumb单寄存器传送指令分以下4种:
(1) LDR和STR—立即数偏移
功能:读取寄存器和存储寄存器。寄存器的地址用一个寄存器的数偏移量指明,立即数偏移的半字和字节读取是无符号的。
格式:
<操作码>Rd,[Rn,《#immed_5*N》]
<操作码>包括:LDR,LDRB,STR,STRH和STRH指令
其中:
H 指明无符号半字传送。
B 指明无符号字节传送
RD 读取和存储寄存器。Rd必须在R0—R7范围内
RN 基址寄存器.Rn必须在R0—R7范围内
Immed_5*N 偏移量。Immed_5是一个表达式,其中值在0--31范围内,在汇编时结果是的N倍数。
对字节传送,N=1
对半字传送,N=2az
对字传送, N=4
注释:
字传送的地址必须可被4整除,半字传送的地址必须可被2整除。
若系统中有系统协处理器(CP15),则可允许对准检查。若允许对准检查,则非对准的传送会引起对准异常
若系统没有协处理系统器(CP15)或禁止对准检查,则:
非对准读取使Rd不可靠
非对准存使存储器的2个或4个字节不可靠。对半字存储,不可靠的存储器位置是address AND NOT 0x1; 于字存储器,则是address AND NOT 0x3
例:
LDR R3,[R5,#0] ;(R5)→R3
STRB R0,[R3,#3] ;(R0)→((R3)+31)
STRH R7,[R3,#16] ;(R7)→((R3)+16)
LDRH R2,[R4,#Label—{PC}]
(2) LDR和STR---寄存器偏移
功能:读取寄存器和存储寄存器。存储器的地址用一个寄存器的基于寄存器偏移指明存储器地址。
格式:
《操作码》Rd,[Rn,Rm]
《操作码》是下列情况之一:
读取寄存器,4字节字
存储寄存器,2字节字
读取寄存器,2字节无符号半字
读取寄存器,2字节字有符号半字,有符号位扩展(即高位字节与符号字节相同)
存储寄存器,2字节半字
读取寄存器,无符号半字
读取寄存器,有符号半字,有符号位扩展(即高位字节与符号位相同)
存储寄存器,字节
含偏移量的寄存器,Rm必须在R0~R7范围内
注释:
同3.3.1节第1条指令。
例:
LDR R2,[R1,R5]; ((R1)+(R5))---R2
STRH R0,[R0,R1]; (R0)---((R0)+(R1))
STRB R1,[R7,R0]; (R1)---(R7)+(R0)
(3) LDR----PC相对偏移
功能:读取寄存器和存储器。存储器中的地址用中内容的立即数偏移指明。字节码结构:
格式:
LDR Rd,[PC,#immed_8*4]
LDR Rd,Label
其中:
immed_8*4偏移量。它是一个表达式,取值(在汇编时)为4的整数倍,范围在0~1020内。
Label 程序相对偏移表达式。必须在当前指令之后且范围内。
注释:
同3.3.1节第1条指令
例:+
LDR R2,[PC,#1016]; ((PC)+1026)---R2
LDR R5,localdata
(4) LDR和STR---SP相对偏移
功能:读取寄存器和存储寄存器。存储器的地址用中内容的立即数偏移指明。
格式:LDR Rd,[SP,#immed_8*4]
STR Rd,[SP,#immed_8*4]
其中:
immed_8*4
偏移量。它是一个表达式,取值(在汇编时)为4的整数倍,范围在0~1020内。
注释:
同3.3.1节第1条指令。
例:
LDR R0,[SP,#920]; ((SP)+920)---R0
STR R1,[SP,#20]; (R1)---(SP)+20
2 Thumb多寄存器指令
功能:Load和多个Store寄存器
格式:(1)LDMIA Rn!, 《Reglist》 (2)STMIA Rn!,《Reglist》
其中:
Reglist 低寄存器或低寄存范围的,用逗号隔开的列表。列表中至少有一个寄存器。
Rn 目的寄存器,必须是低于寄存器
注释:
(1)寄存器以数字顺序取或存储。最低数字的寄存器在的初地址中。的值以中寄存器个数的4倍增加。
(2)若在Rn寄存器列表中,则
对于LDMIA指令,Rn的最终值是读取的值,不是增加后的地址。
对于STMIA指令,Rn的终值有如以下两种情况:
---若是寄存器列表中最低的寄存器,则的存储值为初值;
---其他情况则不可预知。
例:
LDMIA R3!,(R0,R4); (R0)---(R3),(R4)---(R3)+4; (R3)+8---R3
STMIA R0!,(R3,R5,R7);((R0)--R3,((R0)+4)---R5,
;((R0)+8)---R7,(R0)+12---R0
3 堆栈指令
功能:低寄存器和可选的LR进栈,低寄存器和可选的PC出栈。
格式:POP {《REglist》{,PC}}
PUSH {《Reglist》{,LR}}
其中:Reglist
低寄存器或寄存器范围的,用逗号隔开的列表。
注释:
(1)Thumb堆栈是满递减堆栈,向下增长,且SP指向堆栈的最后入口。
(2)寄存器以数字顺序存储在堆栈中。最低数字的寄存器其地址最低。
(3)POP{Reglist}这条指令引起处理器转移到从堆栈弹出给PC的地址,这通常是从子程序返回,其中LR在子程序开头压进堆栈。
(4)对于ARMv5T及以上的版本,则
若读到PC中的值的位[1:0]是b00,则处理器变换到ARM状态
位[1:0]不允许的值b10。
(5)条件码标志。这些指令不影响条件码标志。
例:
PUSH {R0,R4---R7} ;R0,R4---R7进栈-
PUSH {R0,LR}
POP {R2,R5}
POP {R0---R7,PC}
3.3.2 Thumb数据运算类指令
Thumb数据运算指令有以下8种:
1 ADD和SUM-----低寄存器
功能:2个寄存器的,内容相加或相减,结果放到第3个寄存器中。
格式:《操作码》Rd,Rn,Rm
《操作码》包括:ADD,SUB指令。
其中:
Rd 目的寄存器。必须是低寄存器
Rn 第操作寄存器。必须是低寄存器
Rm 第2操作寄存器。必须是低寄存器。
注释:这些指令更新标志N,Z,C,V。
例:ADD R3,R1,R5。
2 ADD和SUB----小整数
功能:寄存器中的值加上或减去一个小整数,结果放在另一个不同寄存器中。
格式:《操作码》 Rd,Rn,# 《3位立即数》
《操作码》包括:ADD,SUB指令。
其中:
Rd目的寄存器。必须是低寄存器(R0~R7)
Rn第1操作数寄存器。必须是低寄存器(R0~R7)
Expr3 表达式,为取值范围在—7~+7内的整数。
注释:
这些指令更新标志N,Z,C,V.
例:SUB R0,R4,#5 ; (R4)---5---R0
3 ADD,SUB,MOV,CMP----大整数
功能:寄存器中的值对于一个大事整数进行ADD,SUB,MOV,CMP运算,结果放在另一个不同的寄存器中。
格式:
《操作码》 Rd|Rn,#《8位立即数》
《操作码》包括:ADD,SUB,MOV,CMP指令。
其中:
Rd,Rn 目的寄存器。必须是低寄存器(R0~R7)
Expre8 表达式,为取值范围在—255~+255内的整数。
注释:这些指令更新标志N,Z,C,V.
例:
ADD R7,#201
ADD R1,vc+4 ; vc+4汇编时必取值范围为—255~+255的整数
4 ADD,MOV,CMP----高或低寄存器
功能:将寄存器中值进行运算,结果送回到第一操作数寄存器。
格式:
《操作码》 Rd|Rn,Rm
《操作码》包括:ADD,MOV,CMP指令。
其中:
Rd,Rn目的寄存器,也是第1操作数寄存器。
Rm第二操作数寄存器。
Rd,Rn,Rm使用高或低寄存器,当和是低寄存器,指令“ADD,Rd,Rm”汇编成“ADD Rd,Rm”。
注释:
若Rd,Rn和Rm是低寄存器,则更新条件码标志N,Z,C和V,其他情况下这些标志不受影响。
例:ADD R0,R8
ADD R2,R4 ; 等价于“ADD R2,R2,R4”,不影响标志。
5 ADD和SUB----SP
功能:SP加上或减去立即数常量。
格式:
《操作码》SP,#《expr》
《操作码》包括:ADD,SUB指令。
其中:
expr表达式,取值范围在—508~+508内的4倍数的整数。expr为负值的ADD指令汇编成相应的带正数常量的指令。expr为负值的指令汇编相应的带正数常量的ADD指令。
注释:
这条指令指示不影响条件码标志。
例:
ADD SP,#312
SUB SP,#96
SUB SP,#abc+8; abc+8汇编时必须取值为范围在---508~+508内4的整数倍。
6 ADD---PC或SP相对偏移
功能:SP或PC值加上一立即相对数常量,结果放入低寄存器。
格式:
ADD Rd,Rp,#《expr》
其中:
Rd 目的寄存器。Rd必须在R0~R7范围内。
Rp SP|PC.RP是PC,则使用值是(当前指令地址+4)AND&FFFFFFC。
Expr 表达式,取值为范围在0~1020的4整倍数。
注释:
这条指令不影响条件码标志。
例:
ADD R2,SP,#64
ADD R6,PC,#980
ADD R0,PC,#lit—{PC}; lit—{PC}必须取值成范围在0~1020的4的
;整数倍
7 ASR,LSL,LSR和ROR运算
功能:移位和循环移位操作。这些指令可使用寄存器中的值或立即数移位。
格式1:
《操作码》Rd,Rn,《#immed_5》
其中:
《操作码》是下列的任何一种:
ASR算术右移。将寄存器中的内容看作补码形式的有符号整数。将符号位移拷贝到空位。
LSL逻辑左移,移入为0。
LSR逻辑右移,移入为0。
ROR循环右移。将寄存器右移出的位循环移回到左端。ROR仅能与寄存器控制的移位一起使用。
Rd立即数移位的目的寄存器。必须在R0~R7范围内。
Rn立即数移位的源寄存器。Rn必须在R0~R7范围内。
Immed_5 立即数移位量。它是一个取值为整数的表达式。整数的范围如下:
《操作码》若是LSL,ROR,则为0~31;
其余则为1~32。
格式2:
《操作码》 Rd|Rn,Rs|Rm
其中:
《操作码》同格式1。
Rd 寄存器控制移位的源寄存器。Rd必须在R0~R7范围内。
Rs 在控制移位中包含移位量的寄存器。Rs必须在R0~R7范围内。
注释:
(1)立即数移位(格式1)。
指令从Rn取值,并对其进行移位,结果放回Rd中。
(2)寄存器控制移位(格式2)
这些指令从Rd中取值,并对其进行移位,结果放回Rd.只有Rs的最低的效数字节可用作移位量。
对于除ROR以外的所有指令,则有
若移位量为32,则Rd清零。最后移出的位保留在标志C中。
若移位量大于32,则Rd和标志C均被清零。
(3)条件码标志
这些指令根据结果更新标志N与Z,且不影响标志V。对于标志C,若移位量是零,则它不受影响,其他情况下,它包含源寄存器的最后移出位。
例:ASR R3,R5
LSR R0,R2,#6
LSR R%,R5,av; av的值必须在汇编时取成在1~32范围内的整数
LSL R0,R4,#0 ;除了不影响标志C和V外,同“MOV R0,R4”
8 其他运算类指令
格式1:
《操作码》 Rd|Rn,Rm|Rs
《操作码》 包括:MOV,MVN,CMN,TST,ADC,SBC,NEG,MUL,AND,EOR,ORR,BIC指令。
《操作码》Rd|Rn,#expr
《操作码》包括:MOV,CMP指令。
Rd Rn 目的寄存器,它也是包含第1条指令操作数。
Rm Rs 第二操作数寄存器。
Expr 表达式,其值范围为在1~255内的整数。
表3~5 Thumb数据处理指令
助记符含义动作
ADC Rd,RmADD Rd,Rn,RmADD Rd,Rn,#0to7ADD Rd,#0to255AND Rd,RmASR Rd,Rm#1to32ASR Rd,RaBIC Rd,RaCMN Rn,RmCMP Rn,#0to255CMP Rn,RmEOR Rd,RmLSL Rd,Rm,#0to31LSL Rd,Rm,#1to32LSR Rd,Rm,#1to32LSR Rd,RsMOV Rd,#0to255MOV Rd,RnMUL Rd,RmMVN Rd,RmNEG Rd,RmORR Rd,RmRORRd,RsSBC Rd,RmSUBRd,Rn,RmSUB Rd,Rn,RmSUB Rd,#0to255TST Rn,Rm带进位加法加法加法加法逻辑与算术右移算术右移位清除比较非值比较比较逻辑异或逻辑左移逻辑左移逻辑右移逻辑右移传送传送乘法传送非取负逻辑或循环右移带进位减法减法减法减法测试Rd---Rd+Rm+进位标志Rd---Rn+RmRd---Rn+3位立即数Rd---Rd+8位立即数Rd---Rd AND RmRd---Rm ASR5位立即数Rd---Rd ASR RsRd---Rd AND NOT RmRn+Rm更新标志Rn—8后立即更新标志Rn—RmRd---Rd EOR RmRd---Rm LSL 5位立即数Rd---Rm LSL RsRd---Rd LSR 5位立即数Rd---Rd LSR RsRd---8位立即数Rd---RnRd---Rm*RdRd---NOT RmRd---0--RmRd---Rd OR RmRd---Rd ROR RsRd--Rd-Rm-NOT(进位标志)Rd---Rn--RmRd---Rn—3位立即数Rd---Rn—8立即数Rn AND Rm后更新标志
注释:
(1)除了“CMP RN,Rm”和“MOV Rd,Rm”指令中的和可以是中的Rn,Rm任何寄存器外,其余指令只能使用低寄存器(R0~R7)
(2)条件码标志:
ADC,SBC,CMP,CMN和NEG指令更新标志N,Z,C和V.
AND,EOR,ORR,BIC指令根据结果更新标志N和Z
MVN,TST,“MOV Rd,#expr”和指令更新标志N和Z,对标志C和V影响。
“MOV Rd,Rm”指令表现如下:
若Rd或Rm是高寄存器(R8~R15),则标志不受影响。
若Rd或Rm都是低寄存器(R0~R7),则更新标志N和Z,且清除清除标志C和V。
MUL更新标志N和Z。在ARM v4及前版本中,MUL会使标志C和V不可靠。在ARM v5及以后的版本中,MUL不影响标志C和V。
注意:可用移位为0来使用LSL,实现在低寄存器之间传送而不清除标志C,V。
例:
ADC R2,R4
CMP R7,R12 ; 指令“CMP Rn,Rm”允许高寄存器
MOV R3,#0
TST R2,R4
3.3.3 Thumb转移指令
Thumb 转移指令主要分以下几类:
1 B指令
格式1:
B 《条件码》 《Label》
格式2:
B 《Label》
其中:
Label 程序相对偏移表达式。通常是在同一代码块内标号。
若使用条件码,则必须在当前指令的—254~+254字节范围内;
若指令是无条件,则Label必须中正负2KB范围内。
Thumb B指令的条件码如表3--6所示。
表3—6 Thumb B指令
条件代码含义标志位状态显示
EQNECS/HSCC/LOMIPLVSVCHILSGELTGTLE相等/是否为0不等进位置/大于进位清零/小于结果为负结果为正溢出无溢出大于小于大于等于小于等于大于小于等于 Z置位Z清零C置位C清零N置位N清零V置位V清零C置位且Z清零C清零或Z置位N等于VN不等于VZ清零或N等于VZ置位或N不等于V
注释:
若条件码满足或不使用条件码,则B指令引起处理器转移到Label.
例:
B dloop
BEQ sectB
2 BL,BLX指令
格式:
BL{X} 《Label》
其中:
Label 程序相对转移表达式。
注释:
BL指令将下一条指令的地址拷贝到R14(LR链接寄存器),并引起处理器转移到Label。机器级指令不能转移到当前正负4MB指令以外的地址。必要时,ARM链接器插入代码(veneer)以允许更长的转移。
BL指令实际上分为2条指令,1条指令H=0,它把11位偏移量左移12位,加上现行PC,写入中R14(LR),另一条指令H=1,它把LR加上11位偏移量乘2写入PC,同时把下一条指令写入R14中。
BLX指令可用于:
拷贝下一条指令的地址到R14(LR链接寄存器)。
引起处理器转移到Label或Rm存储的地址
如果Rm的位[0]清零,或使用“BLX Label”形式,则指令集切换到ARM状态。BLX指令适用于ARM v5T指令系统及以上版本。
例:
B extract
3 BX,BLX指令
格式:
B{L}X Rm
其中:
Rm 装有目的地址的ARM寄存器,m=0~15。Rm的位[0]I不用于地址部分。若Rm位清零。则
位[1]也必须清零;
指令清零CPSR中的标志T,目的地址的代码被解释为ARM代码。
注释:
BX指令引起处理器转移到Rm存储的地址。若Rm的位[0]置位,则指令集切换到Hhnmb状态。
BLX指令用来在Thumb程序中调用ARM或者子程序,地址由Rm指定。从子程序返回,用BX R14指令。
例:
BX R5
BLX R6
3.3.4 Thumb软件中断和断点指令
1 Thumb软件中断指令
功能:Thumb的SWI指令类似于ARM SWI指令。该指令执行后的操作是:
(1)将下一条Thumb指令地址保存进R14_svc。
(2)PSR的内容保存进SPSR_svc;
(3)禁止IRQ中断,清除Thumb位,进入SVC模式;
(4)PC指向0x08。
返回指令恢复Thumb执行的状态。
格式:SWI 《immed_8》
其中:
immed_8 符号表达式,其取值范围为的整数。
SWI指令引起SWI异常。这意味着处理器状态切换到ARM态,处理器模式切换到管理模式的,CPSR保存到管理模式中,执行转移SWI到向量地址。
处理器忽略immed_8,但immed_8出现在指令操作码的位[7:0]中。而异常处理程序用它来确定正在请求何种服务。
注释:
这条指令不影响条件码标志。
例:
SWI 12
2 Thumb断点指令
格式:
BRKT immed_8
其中:
immed_8 符号表达式,取值范围为0~255的整数。
注释:
BKPT(BreakPoinT)指令引起处理器进入调试模式。调试工具利用这一特点调查到达特定地址的指令时的系统状态。
尽管immed_8出现在指令操作码的位[7:8]中,处理器忽略immed_8。调试器用它来存储有关断点的附加消息。
BKPT指令适用于ARM v5T指令系统及以上版本。
例:
BKPT 67
BKPT 2_10110
3.3.5 Thumb指令示例
1 从Thumb状态到ARM状态
ADR R1,oct of Thumb
MOV R11,R1
BX R11
……
ALIGN
CODE32
Out of Thumb ……
2 ARM和Thumb指令编写的比较
本节最后通过比较ARM和Thumb指令编写“Hello Word”程序,示例Thumb指令的编写。从下面的例子中可以看到,指令Thumb的执行必须由ARM状态转向Thumb状态,通常BX指令完成。另外在Thumb指令前必须有CODE16伪指令指示汇编器以下指令为Thumb指令。
(1) ARM指令编写的“Hello Word”程序
AREA HelloW,CODE,READONLY
SWI_WriteC EQU &0; SWI中断入口
SWI_Exit EQU &11
ENTRY
START ADR R1,TEXT
LOOP LDRB R0,[R1],#1
CMP R0,#0
SWINE SWI_WriteC;参数&0完成显示成输出
BNE LOOP
SWI SWI_Exit;参数&11返回
TEXT = “Hello Word”;&0a,&0d,0
END
(2) Thumb指令编写的“Hello Word”程序
AREA HelloW_Thumb,CODE,READONLY
SWI_WriteC EQU&0
SWI_Exit EQU&11
ENTRY
CODE32 ;指示以下为ARM指令
ADR R0,START+1
BX R0 ;转向Thumb程序
CODE16 ;指示以下指令为Thumb指令
START ADR R1,TEXT
LOOP LDRB R0,[R1]
ADD R1,R1,#1
CMP R0,#0
BEQ DONE ;转向Thumb子程序DONE
SWINE SWI_WriteC
B LOOP
DONE SWI SWI_Exit
ALIGN
TEXT DATA
= “Hello World”,&0d,0
END
3.4 ARM宏汇编
本节将详尽地介绍汇编器所提供的特征,包括伪指令,宏汇编以及指示标志。
3.4.1 预定义变量
1 预定义变量的寄存器的协处理器名
ARM汇编器对ARM的寄存器进行了预定义,所有的寄存器和协处理器都是大小写敏感的。预定义的寄存器如表3—7所示。
(1) 定义的寄存器名
R0~R15
R0~r15
a1~a4
v1~v8
sp和SP
Ir和LR
Pc和PC
Sl和SL
表3---7为ARM寄存器列表及含义
寄存器特殊定义其它定义含义
R15R14R13R12R11R10R9R8R7R6R5R4R3R2R1R0V8V7V6V5V4V3V2V1a4a3a2a1PCLRSPIPFPSLSBWR程序计数器链接寄存器堆栈指针程序调用暂存寄存器变量寄存器8/帧指针(ARM状态)变量寄存器7/堆栈上限指针(ARM)变量寄存器6/基址寄存器(进程ID/重入/共享库中)变量寄存器5变量寄存器4(Thumb状态工作寄存器)变量寄存器3变量寄存器2变量寄存器1参数/结果/暂寄存器4参数/结果/暂寄存器3参数/结果/暂寄存器2参数/结果/暂寄存器1
R0~R3通常用来传递参数和保存结果,也可以保存子程序调用的中间结果,在ARM状态下,R12(也称为IP)通常也保存子程序调用的中间结果。R14~R11通常保存程序的局部变量,也可以用V1~V8表示,但是V1~V4只能在Thumb状态下使用。
R12~R15一般有特殊用途,也通常称为IP,SP,LR,PC。
(1)定义的程序状态寄存器名
cpsr和CPSR
spsr和SPSR
(2)定义的浮点数寄存器名
f0~f7
F0~F7
(3)定义的协处理器名
p0~p15
c0~c15
2 内置变量
表3—8列出了ARM汇编器所定义的内置变量,值得注意的是内置变量的设置不能用SETA,SETL,或SETS等表示词来设置,只能用字符或条件表达式来设置。例如:
IF {ARCHITECTURE}=“4T”
表3—8 变量含义
(PC )或者(VAR)或者@(TRUE)(FALSE)(OPT)(CONFIG)(ENDIAN)(CODESIZE)(CPU)(ARCHITECTURE)(PCSTOREOFFSET)当前指令的地址存储区计数器的当前值逻辑常量为真逻辑常量为假当前设置列表选项,OPT用来保存当前列表选项,改变选项值,恢复设置它的原始值如果汇编器在ARM模式下值为32,如果汇编在Thumb 模式下值为16如果汇编器在big—endian模式下为big,如果汇编器在某些方面little—endian模式下值为little如果汇编Thumb代码值为16,否则为32选定的CPU符号,如果没有说明,则为genericARM选定的ARM架构的值,3,3M,4,4T,4TxMSTRpc,[…]或STM Rb,(…PC)的地址和PC的存储值之间的偏移量
3.4.2 伪指令
ARM汇编器采用两类伪指令,一类是为ARM伪指令,另一类是Thumb伪指令。在ARM状态下可以使用的伪指令如下:
1 ADR伪指令
功能:把程序相关的或寄存器相关的地址调进寄存器中。
格式:ADR{condition} register,expression
其中:
register 读取的寄存器。
Expression 程序相关的或寄存器相关的表达式,必须是:
255字节以内的非字对准地址;
1020字节以内的字对准地址。
寄存器相关的表达式由1个寄存器加或减1个数字常数组成(见“ⅴ”或者MPA介绍。)程序相关的表达式由PC加或减1个数字组成,一般它可为标号或加减数字表达式。
注释:
ADR伪指令通常汇编成一条指令,汇编器产生一条ADD或SUB指令以读入地址。如果表达式是关于程序相关的,读取地址只能是ADR伪指令所在代码所在的地址。
例:
start MOV R0,#10
ADR R4,start ; 等同于SUB,R4,PC,#0xc
2 ADRL伪指令
功能:与ADR功能类似,但是可以调进范围更广的地址。
格式:
ADR{condition} register,expression
其中:
register 读取的寄存器。
Expression 程序相关的或相关的表达式,必须是:
64KB以内的非对准地址;
256KB以内的字对准地址。
注释:
ADRL伪指令通常汇编成2条指令,即使地址在第1条指令已经产生,也会产生1条冗余指令。如果表达式是关于程序表达式相关的,读取地址只能是ADRL伪指令所在的代码段所在的地址。注意:该指令只能在ARM状态下使用,在Thumb状态下不能使用。
例:
start MOV R0,#10
ADRL R4,start+60000;等同于ADD R4,PC,#0xE800
等同于ADD R4,R4,#0x254
3 LDFD伪指令
功能:将一个双精度的浮点常量放进
格式:
LDFD{condition} fp-register,=expression
其中:
condition 可选的条件代码。
fp-register 读取的浮点寄存器。
Expression 浮点常量。汇编器通常把放在一个库中,用LDFD伪指令读进浮点寄存器中,该浮点常量用2个字存放。PC与该常量的偏移量不得超过4KB。
注释:
浮点数常量的范围是:
最大值 1.79769313486231571e+308
最小值2.22507385850720138e—308ADR
注意;只有系统中有浮点加速器FPA(Floating Point Accelerator)时,才能使用该指令。
例:
LDFD f1,=3.12E106
4 LDFS 伪指令
功能:将一个单精度的浮点数常量放进一个浮点数寄存器。
格式:
LDFS{condition} fp-register,=expression
其中:
condition 可选的条件代码。
fp-register 读取的浮点寄存器。
Expression 浮点常量。汇编器通常把该常量放在一个库中,用LDFD伪指令读进浮点寄存器中,该浮点常量用2个字存放。PC与该常量的偏移量不得超过4KB。
注释:
浮点数常理的范围是:
最大值:3.40282347e+38F
最小值:1.17549435e—38F
注意:只有系统中有一个浮点加速器时,才能使用该指令。
例:
LDFS f1,=3.12E---6
5 LDR 伪指令
功能:将一个32位常量或地址读取至寄存器。
格式:
LDR{condition} register,=[expression|Label-expression]
其中:
condition 可选的条件代码。
register 读取的寄存器。
expression 数字常量:
如果该数字常量在MOV或MVN指令的范围中,汇编器会产生合适的指令;
如果该数字量不在MOV或MVN指令的范围中,汇编器把该常量于程序后,用程序相关的LDR伪指令读取,PC与该常量的偏移量不得超过4KB。
Label-expression 程序相关的或外部的表达式。汇编器将其存放在程序后的常量库(称为文字池(literal pool))中,用程序相关的LDR伪指令读取,PC与与该常量的偏移量不得超过4KB。
注释:
LDR伪指令的使用有两个目的:
对于不能被MOV和MVN指令所读取的立即数,将其变成常量,进行读取:
将一个程序相关的或外部的表达式读取进寄存器中。
例:
LDR R1, =0xfff
LDR R2, =place
6 NOP伪指令
功能: 产生空操作代码。即:MOV R0,R0.
格式:
NOP
注释:
该指令不能带条件使用,也不能改变条件码.
评论
查看更多