ARM指令详解

ARM 206浏览

详细介绍ARM指令集1- - 首先详细介绍ARM指令集,ARM指令集包括标准ARM指令集和Thumb指令集,并介绍ARM的宏汇编以及ARM汇编语言编程 1 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,#±]{!} 例: LDR R0,[R1,#5]! ;((R1+5)→R0,(R1)+5→R1 ②寄存器偏移[Rn,#±Rm{!} 例 LDR R0,[R!R1,-R2] ;((R1)-(R2))→R0 ③移位寄存器偏移 [Rn, ±Rm,LSL #{!} [Rn, ±Rm,LSL #{!} [Rn, ±Rm,ASR #{!} [Rn, ±Rm,ROR #{!} [Rn, ±Rm,RPX]{!} 例: LDR R0,[R1,R2,LSL #2] ;((R1)+(R2)*4→R0 (3)后变址偏听偏信移寻址([Rn],偏移量) Rn的值用作传送数据的存储器地址。在数据传送后,偏移量加到Rn中,结果写回到Rn。Rn不允许是R15。该寻址方式又分为下列3种: ①立即数偏移[Rn],#± 例: LDR R0,[R1],#4 ;((R1))→R0,(R1)+4→R1 ②寄存器偏移[Rn],±Rm 例: LDR R0,[R3],-R8 ;((R3))→R0,(R3)-(R8)→R3 ③移位寄存器偏移 [Rn],±Rm,LSL# [Rn],±Rm,LSR# [Rn],±Rm,ASR# [Rn],±Rm,ROR# [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,#±]{!} 例: 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,#±]{!}); (3)后变址偏移寻址([Rn],#±); (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,]{!} ;((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], 后变址指的是将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,]{!} (3) 程序相对偏移(pregram-relatve) LDR|STR{<条件码>}H|SH|SB Rd,Label (4) 后变址(post-indexed offset) LDR|STR{<条件码>}H|SH|SB Rd,[Rn], 其中: 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,]{!} (3) 程序相对偏移(pregram-relatve) LDR|STR{<条件码>}D Rd,LABEL (4) 后变地址格式(post-indexed offset) LDR|STR{<条件码式>}D Rd,[Rn], 其中: 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{<条件码>}Rn{!}<寄存器> (2) 非用户模式下,用下面可以同时把当前的SPSR写入CPSR中,转向用户模式,寄存器组饮包含PC. LDM{<条件码>}Rn{!},<寄存器组+PC>^ (3) 非用户模式下,用下面格式可以实现访问用户模式的寄存器,但寄存器组不包含PC. LDM|STM{<条件码>}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) {<条件码>}{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{条件码}Rd,Rm,Rs 其中: B或T。B意味着使用Rm的低端(位[15:0]),T意味着使用Rs的高端(位[31:16])。 B或T。B意味着使用Rm的低端(位[15:0]),T意味着使用Rs的高端(位[31:16])。 Rd 结果寄存器。 Rm,Rs 乘数寄存器。 R15不能用于Rd,Rm和Rs。Rd、Rm、Rs可用相同的寄存器。 (5) SMLA{条件码}Rd,Rm,Rs可用相同的寄存器。其中: 、、Rm和Rn含义同SMUL指令。 R15不能用于Rd、Rm和Rs。Rd、Rm、Rs可用相同的寄存器。 (6) SMULW{条件码}Rd,Rm,Rs 其中: 、Rd、Rm、Rs和Rn含义同SMUL指令。 R15不能用于Rd、Rm和Rs。Rd、Rm、Rs可用相同的寄存器。 (7) SMULW{条件码}Rd,Rm,Rs 其中: 、Rd、Rm、Rs和Rn含义同SMUL指令。 R15不能用作Rd、Rm、Rs或Rn的任何一个。任何Rd、Rm、Rs或Rn可用相同的寄存器。 (8) SMULW{条件码}Rd,Rm,Rs,Rn 其中: 、Rd、Rm、Rs和Rn含义同SMUL指令。 R15不能用作Rd、Rm、Rs或Rn的任何一个。任何Rd、Rm、Rs或Rn可用相同的寄存器。 (9) SMULW{条件码}RdLo,RdHi,Rm,Rs 其中: 含义同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}{<条件码>}