3.1 ARM指令集

ARM指令集可以分为6类,即跳转指令、数据处理指令、程序状态寄存器(PSR)传输 指令、Load/Store指令、协处理器指令和异常中断产生指令。
为了更清楚地描述这些指令,有些大类的指令进一步分为几小类分别讲述。

3.1.1跳转指令

在ARM中有两种方式可以实现程序的跳转;一种是跳转指令;另一种是直接向PC 寄存器(R15)中写入目标地址值。
通过直接向PC寄存器中写入目标地址值可以实现在4 GB的地址空间中任意跳转. 这种跳转指令又称为长跳转。如果在长跳转指令之前使用MOV 、LR、PC等指令.可以保存将来返回的地址值,就实现了在4GB的地址空间中的子程序调用。
在ARM版本5及以上的体系中,实现了 ARM指令集和Thumb指令集的混合使用。 指令使用目标地址值的bit[0]来确定目标程序的类型。
 bit[0]值为1时,目标程序为Thumb 指令;
 bit[0]值为0时,目标程序为ARM指令。

在ARM版本5以前的体系中,传送到PC寄存器中的目标地址值的低两位bits[1:0] 被忽略,跳转指令只能在ARM指令集中执行,即程序不能从ARM状态切换到Thumb状态。
非T系列版本5的ARM体系不含Thumb指令,当程序试图切换到Thumb状态时,将产生未定义指令异常中断。
ARM的跳转指令可以从当前指令向前或向后的32 MB的地址空间跳转。这类跳转指令有以下4种:
 B跳转指令
 BL带返回的跳转指令。
 BLX带返回和状态切换的跳转指令。
 BX带状态切换的跳转指令。

1. B(跳转指令)及BL(带返回的跳转指令}

B指令和BL指令均可以跳转到指令中的目标地址,这两个指令和目标地址处的指令都属于ARM指令集。二者也都可以根据CPSR中条件标志位的值与指令中的执行条件决 定是否执行跳转操作。二者的不同之处在于,B指令仪仅执行跳转操作;BL指令同时还 将PC寄存器的值保存到LR寄存器中。
指令的编码格式
31 28 27 26 25 24 23 0<br />cond | 1 0 1 | L | signed_immed_24
指令的语法格式
B{L} {} <target_address>
其中:
 L决定是否保存返回地址。
 当有L时,当前PC寄存器的值将保存到LR寄存器中;
 当无L时,指令仅执行跳转,当前pc寄存器的值将不会保存到LR寄存器 中。
 为指令执行的条件码。
指令操作的伪代码
if ConditionPassed(cond) then<br />if L == 1 then<br />LR = address of the instruction after the branch instruction<br />PC = PC + (SignExtend(^igned_immed_24) << 2)
指令的使用
BL指令用于实现子程序调用。子程序的返回可以通过将LR寄存器的值复制到PC寄存器中来实现。通常有下面3种方法实现这种复制;
• BX R14
• MOV PC, R14
• 当子程序入口中使用了 STMFD R13!,{〈registers〉,R14}时,可以用指令LDMFD R13!, {〈registers〉,PC}
ARM汇编器通过以下步骤计算指令编码中的Signed_immed_24:
(1) 将PC寄存器的值作为本跳转指令的基地址值。
(2) 从跳转的目标地址中减去上面所说的跳转的基地址值,生成字节偏移量。由于ARM指令是字对齐的,该字节偏移量为4的倍数。
(3) 当上面生成的字节偏移覺超过范围33554432〜3355443。时,程序需要作相应 的处理。
(4) 否则,将指令编码字中的Signed_immed_24设置成上述字节偏移量的bits[25 :2],
当指令跳转越过地址0或32位地址空间最高地址时,将产生不可预知的结果。
示例
BCC Lable ;当CPSR寄存器中的C条件标志位为1时,程序跳转到标LabM处执行
BL func_l ;程序跳转到子程序func_l处执行,同时将当前PC值保有到LR中

2.BLX ⑴

第1种格式的BLX指令记作BLX(1)。BLX⑴指令从ARM指令集跳转到指令中指定的目标地址,并将程序状态切换为Thumb状态,该指令同时将PC寄存器的内容复制到 LR寄存器中。
本指令属于无条件执行的指令(即条件码为AL)。
指令的编码格式
31 28 27 26 25 24 23 0<br />1111 | 101 |H |signed_immed_24
指令的语法格式
BLX <target_add.ress>
其中,的用法与B及BL指令中的用法相同。
操作的伪代码
LR = address of the instruction after the BLX instruction<br />T Flag = 1<br />PC = PC + (SignExtend(signed_immed_24) << 2) + (H << 1)
指令的使用
当子程序为Thumb指令集,而调用者为ARM指令集时,可以通过BLX指令实现子程序调用和程序状态的切换。子程序的返回可以通过将LR寄存器(R14)的值复制到PC寄 存器中来实现。通常有下面两种方法:
• BXR14。
• 当子程序入口中使用了 PUSH{vregisters>,R14}时,可以用指令 POP {〈registers〉,PC} °
ARM汇编器通过以下步骤计算指令编码中的Signed^immed_24:
(1) 将PC寄存器的值作为本跳转指令的基地址值。
(2) 从跳转的目标地址中减去上面所说的跳转的基地址值,生成字节偏移量。由于 ARM指令是字对齐的,Thumb指令是半字对齐的,该字节偏移量为偶数。
(3) 当上面生成的字节偏移量超过范围33554432〜33554430时,程序需要作相应 的处理。
(4) 否则,将指令编码字中的Signed_immed_24设置成上述字节偏移量的 bits[25:2],同时将指令编码字中的H位设置成上述字节偏移量的bit[l]o
本指令是无条件执行的。
指令中的bit[24)被作为目标地址的bit[l].

3. BLX(2)

第2种格式的BLX指令记作BLX(2)。BLX(2)指令从ARM指令集跳转到指令中指定
的目标地址,目标地址的指令可以是ARM指令,也可以是Thumb指令。目标地址放在 指令中的寄存器<Rm>中,该地址的bil[O]值为0,日标地址处的指令类型由CPSR中的T 位决定。该指令同时将PC寄存器的内容复制到LR寄存器中。
指令的编码格式
31 282726 2C 19 8 7 6 5 4 3 0<br />cond 丨 0001 0010 | 应为 0 | 0 0 11| Rm
指令的语法格式
BLX{<ccnd>} <Rm>
其中:
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。
<Rm>该寄存器中为跳转的目标地址。当<Rm>寄存器的bit[O]值为0时,目标地 址处的指令为ARM指令;当寄存器的bit[O]值为1时,目标地址处的指令 为Thumb指令。当寄存器为R15时,会产生不可预知的结果。
指令操作的伪代码
if ConditioriPassec (cond) then<br />LR = address of instruction after the BLX instruction<br />T Flag = Rm[0]<br />PC - Rm AND OXFFFFFFFM
指令的使用
当Rm[l:0]=0bl0时,由于ARM指令是字对齐的,这时会产生不可预料的结果。

4. BX指令

BX指令跳转到指令中指定的目标地址,日标地址处的指令可以是ARM指令,也可 以是Thumb指令。冃标地址值为指令的值和OxFFFFFFFE做与操作的结果,目标地址处 的指令类型由寄存器vRm>的bit[O]决定。
指令的编码格式
31 28 27 26 20 19 8 7 6 5 4 3 0<br />cond |0001 0010 |应为 0 |0 0 0 1|Rm
指令的语法格式
BX{<cond>} <Rm>
其中:
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。
<Rm>该寄存器中为跳转的目标地址。当<Rm>W存器的bit[O]为0时,目标地址 处的指令为ARM指令;当〈日昨寄存器的bit(O]为1时,目标地址处的指令为 Thumb指令。
指令操作的伪代码
if ConditionPassed(cond) then<br />T Flag = Rm[0j<br />PC = Rm AND OxFFFFFFFE
指令的使用
当Rm[l:0]=0bl0时,由于ARM指令是字对齐的,这时会产生不可预料的结果。
当<Rm>为PC寄存器时,即指令BX PC将程序跳转到当前指令下面第2条指令处执 行。虽然可以这样使用,但推荐使用更简单的指令实现与这条指令相同的功能。如指令 MOV PC, PC 及指令 ADD PC, PC, #0。

3.1.2数据处理指令

数据处理指令又可大致分为3类:数据传送指令,如MOV算术逻辑运算指令,如 ADD、SUB和AND等;比较指令,如1ST。
数据传送指令用于向寄存器中传入-个常数。该指令包括一个目标寄存器和一个源操 作数,源操作数的计算方法在2.2节己详细描述。
算术逻辑运算指令通常包括…个目标寄存器和两个源操作数。其中•一个源操作数为寄 存器的值;另外一个源操作数的计算方法在2.2节己详细描述。算术逻辑运算指令将运算 结果存入目标寄存器,同时更新CPSR中相应的条件标志位。
比较指令不保存运算结果,只更新CPSR中相应的条件标志位。
数据处理指令包括以下指令:
• MOV数据传送指令。
• MVN数据求反传送指令。
• CMP比较指令。
• CMN基于相反数的比较指令。
• TST位测试指令。
• TEQ相等测试指令。
• ADD加法指令。
• SUB减法指令。
• RSB逆向减法指令。
• ADC带位加法指令。
• SBC带位减法指令。
• RSC带位逆向减法指令。
• AND逻辑与操作指令。
• BIC位清除指令。
• EOR逻辑异或操作指令。
• ORR逻辑或操作指令。

1. MOV传送指令

MOV指令将<shifter_operand>表示的数据传送到目标寄存器<Rd>中,并根据操作的 结果更新CPSR中相应的条件标志位。
指令的编码格式
31 28 2726 25 24 21 20 19 16 15 12 11 0<br />cond |0 0 |1 |1101 | S | 应为 0| Rd |shifter_operand
指令的语法格式
M0V{:{S} , <shifter_operand>
其中:
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。
S决定指令的操作是否影响CPSR中条件标志位的值。当有S时指令更新CPSR 中条件标志位的值;当没有S时指令不更新CPSR中条件标志位的值。当有S时 有两种情况;若指令中的日标寄存器<Rd>为R15,则当前处理器模式对应的 SPSR的值被复制到CPSR寄存器中,对于用户模式和系统模式,由于没有相应 的SPSR,指令执行的结果将不可预料;若指令中的目标寄存器<Rd>不是R15, 指令根据传送的数值设置CPSR中的N位和Z位,并根据移位器的进位值carry* out设置CPSR的C位,CPSR中的其他位不受影响。
<Rd>寄存器为目标寄存器。
<Shifter_operand>为向目标寄存器传送的数据,其计算方法在2.2节有详细介 绍。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = shifteroperand<br />if S == 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S == 1 then<br />N Flag = Rd[31]<br />Z Flag = it Rd == 0 then 1 else 0<br />C Flag = shifter_carry_out<br />V Flag = unaffected
指令的使用
MOV指令可以完成以下功能:
• 将数据从一个寄存器传送到另■•个寄存器中。
• 将一个常数传送到一个寄存器中。
• 实现单纯的移位操作。左移操作可以实现将操作数乘以2L
• 当PC寄存器作为目标寄存器时可以实现程序跳转。这种跳转可以实现子程序调 用以及从于程序中返回。
• 当PC寄存器作为目标寄存器且指令中S位被设置时,指令在执行跳转操作的同 时,将当前处理器模式的SPSR寄存器内容复制到CPSR中。这样指令MOVS PC, LR可以实现从某些异常中断中返回。

2. MVN传送指令

MVN指令将表示的数据的反码传送到目标寄存器vRd>中,并根据 操作的结果更新CPSR中相应的条件标志位。
指令的编码格式
31 28 2726 25 2421 20 19 _1615 12 11_ 0 <br />cond | 00 |1|1111| S |应为 0| Rd | shifter_operand
指令的语法格式
MVN{<cond>}{S}<Rd> , < shifter_operand>
其中,各参数的用法与MOV传送指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = NOT shifter_operand<br />if S == 1 and Rd == R15 then<br />CPSR = S?SR<br />else if S — 1 then<br />N Flag = Rd[31]<br />Z Flag = if Rd == 0 then 1 else 0<br />C Flag = ter_carry_out<br />V Flag = unaffected
指令的使用
MVN指令有以下用途;
• 向寄存器中传送一个负数。
• 生成位掩码。
• 求一个数的反码。

3. ADD加法指令

ADD指令将表示的数据与寄存器中的值相加,并把结果保存到 目标寄存器中,同时根据操作的结果更新CPSR中相应的条件标志位。
指令的编码格式
31 28 27 26 25 24 21 20 19 16 15 12 11 0<br />cond |0 0 | 1 | 0100 | S |Rn |Rd |shifter_operand
指令的语法格式
ADD{<cond>}{$)〈Rd〉,<Rn>, <shifter_opecand>
其中:
、S和Rd的用法与MOV传送指令相同。
寄存器为第1个源操作数所在的寄存器。
为第2个操作数,其计算方法在2.2节有详细介绍。 
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd a Rn + shifter_operand<br />if S == 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S == 1 then<br />N Flag = Rd[31]<br />Z Flag = if Rd -= 0 then 1 else 0<br />C Flag = CarryFrom(Rn + shifter_operand)<br />V Flag = OverflowFrom(Rn + shifter_operand)
指令的使用
ADD指令实现两个操作数相加。
示例
典型用法如下所示:

  1. ADD Rx, Rx, #1 ; Rx=Rx+1
  2. ADD Rd, Rx, Rx,LSL #n ; Rx=Rx+Rx* (2*n)=RX* (2*n+11
  3. ADD Rs,PC,#offset ;生成基于PC的跳转指针

4. ADC带位加法指令

ADC指令将〈shifteroperand>表示的数据与寄存器vRn>中的值相加,再加上CPSR中 的C条件标志位的值,并把结果保存到目标寄存器<Rd>中,同时根据操作的结果更新 CPSR中相应的条件标志位。
指令的编码格式
image.png
指令的语法格式
`ADC{ } {S} , , <shifter
operand><br />其中,各参数用法与ADD传送指令相同。 指初作的伪代码<br />if ConditicnPassedtcond) then
Rd = Rn + shifter_operanci + C Flag
if S “ 1 and Rd =- R15 Chen
CPSR - SPSR
else if S == 1 then
N Flag = Rd[31]
Z Flag = if Rd 0 then 1 else 0
C Flag = CarryFrom(Rn + shifteroperand + C Flag)
V Flag = OverflowFrom(Rn + shifter_operand + C Flag)<br />指令的使用<br />ADC指令和ADD指令联合使用可以实现两个64位的操作数相加。如果寄存器R0和R1中放置一个64位的源操作数,其中RO中放置低32位数值;寄存器R2和R3中放 置另…个64位的源操作数,其屮R2屮放置低32位数值。下面的指令序列实现了两个64 位操作数的加法操作。<br />ADDS R4,R0,R2
ADC R5,R1,R3`
若将上述的ADC R5,R1,R3指令改为ADCS R5,R1,R3,操作结果将影响到CPSR寄存 器中相应的条件标志位的值。

5. SUB减法指令

SUB指令从寄存器中减去表示的数值,并把结果保存到目标寄 存器中,同时根据操作的结果更新CPSR中相应的条件标志位。
指令的縮码格式
image.png
指令的语法格式
SUB{ <cond>} {S}< Rd>,<Rn>,<shifter operand>
其中,各参数用法与ADD传送指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = Rn - shiftzer_operand<br />if S -= 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S -= 1 then<br />N Flag = Rd[31]<br />Z Flag = if Rd == 0 then 1 else 0<br />C Flag = NOT BorrowFrom(Rn - shifteroperand)<br />V Flag = OverflowFrom(^n - shifter_operand)
指令的使用
SUB指令实现两个操作数相减。典型用法如下所示:
SUB Rx, Rx, #1 ;Rx=Rx-l
当SUBS指令与跳转指令联合使用时可以实现程序中循环。这时就不需要CMP指令。
需要注意的是,在SUBS指令中,如果发生了借位操作,CPSR寄存器中的C标志位 设置成0;如果没有发生借位操作,CPSR寄存器中的C标志位设置成1。这与ADDS指 令中的进位指令正好相反。这主要是为了适应SBC等指令的操作需要。

6. SBC带位减法指令

SBC指令从寄存器中减去表示的教值,再减去寄存器CPSR中C条件标志位的反码,并把结果保存到目标寄存器中,同时根据操作的结果更新 CPSR中相应的条件标志位。
指令的编码格式
image.png
指令的语法格式
image.png
其中,各参数用法与ADD传送指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = Rn - shifter_operand - N0T(C Flag)<br />if S -= 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S 1 then<br />N Flag = Rd[31]<br />'L Flag = if Rd == 0 then 1 else 0<br />C Flag * NCT BorrowFrom(Rn - shifter_operand - NOT(C Flag)) V Flag == Overf lowFrom (Rn - shifter_operand - NOT (C Flag))
指令的使用
SBC指令和SUBS指令联合使用可以实现两个64位的操作数相减。如果寄存器R0 和R1中放置1个64位的源操作数,其中R0中放置低32位数值;寄存器R2和R3中放 置另一个64位的源礫作数,其中R2中放置低32位数值。下面的指令序列实现了两个64 位操作数的减法操作。
SUBS R4,R0,R2<br />SBC R5,R1,R3
需要注意的是,在SBCS指令中,如果发生了借位操作,CPSR寄存器中的C标志位 设置成0;如果没有发生借位操作,CPSR寄存器中的C标志位设置成1。这与ADDS指 令中的进位指令止好相反。

7. RSB逆向减法指令

RSB指令从表示的数值中减去寄存器值,并把结果保存到目标 寄存器vRdA中,同时根据操作的结果更新CPSR中相应的条件标志位。
指令的编码格式
image.png
指令的语法格式
image.png
其中; 其他各参数用法与ADD传送指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = shifter__operand - Rn<br />if S 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S == 1 then<br />N Flag - Rd[3L]<br />Z Flag = if Rd == 0 then 1 else 0<br />C Flag * NOT BorrowFrom(shifter_operand - Rn)<br />V Flag = OverflowFrom(shifter_operand ~ Rn)
指令的使用
RSB指令实现两个操作数相减。典型用法如下所示:
RSE Rd, Rx, #0 ; Rd=—Rx<br />RSB Rd^Rx,Rx,LSL#n ; Rd=Rx*(2**n-l)
需要注意的是,在SUBS指令中,如果发生了借位操作,CPSR寄存器中的C标志位 设置成0;如果没有发生借位操作,CPSR寄存器中的C标志位设置成I。这与ADDS指 令中的进位指令正好相反。这主要是为了适应SBC等指令的操作需要。

8. RSC带位逆向减法指令

RSC指令将表示的数值减去寄存器vRn>的值,再减去寄存器CPSR 中C条件标志位的反码,并把结果保存到目标寄存器vRd>中,同时根据操作的结果更新 CPSR中相应的条件标志位。
指令的编码格式
image.png
指令的语法格式
image.png
其中,各参数用法与RSB逆向减法指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = shifter_operand - Rn - NOT(C Flag)<br />丄f S M= 1 and Rd =- R15 then<br />CPSR = SPSR<br />else if S == 1 then<br />N Flag = Rd[31?<br />Z Flag = if Rd == 0 ^hen 1 else 0<br />C Flag = NOT BorrowFrom[shifter_operand - Rn - NOT (C Flag)) V Flag = OverflowFrom{shifter_operand - Rn - NOT(C Flag))
指金的使用
下面的指令序列可以求•个64位数值的负数。64位数放在寄存器R0与R1中,其负 数放在R2与R3中。其中R0与R2中放低32位值。
RSBS R2,R0,#0<br />RSC R3,R1,#0
需要注意的是,在RSBS指令中,如果发生了借位操作,CPSR寄存器中的C标志位 设置成0;如果没有发生借位操作,CPSR寄存器中的C标志位设置成1。这与ADDS指 令中的进位指令正好相反。

9.AND逻辑与操作指令

AND指令将表示的数值与寄存器vRn>的值按位作逻辑与操作.并把 结果保存到目标寄存器中,同时根据操作的结果更新CPSR中相应的条件标志位c
指令的编码格式
image.png
指令的语法格式
image.png
其中:
寄存器为第1个源操作数所在的寄存器。
为第2个操作数。
其他参数用法与MOV传送指令相同。
指令操作的伪代码
if ConditionPassed(cond) then<br />Rd = Rn AND shifter_operand<br />if S == 1 and Rd == R15 then<br />CPSR = SPSR<br />else if S =- 1 then<br />N Flag = Rd[31]<br />Z Flag = if Rd — 0 then 1 else 0<br />C Flag - shifter_carry_out V Flag = unaffected
指令的使用
AND指令可用于提取寄存器中某些位的值。具体作法是设置个掩码值,将该值中 对应于寄存器中欲提取的位设为1,其他的位设置成0。将寄存器的值与该掩码值作与操 作即可得到想提取的位的值。
10. ORR逻辑或操作指令
ORR指令将>示的数值与寄存器vRn>的值按位作逻辑或操作,并把 结果保存到目标寄存器vRd>中,同时根据操作的结果更新CPSR中相应的条件标志位。
指令的编码格式
31 28 27 26 25 24 21 20 19 16 1.5 12 11 0
cond 00 J 110 0 S Rn Rd shifteroperand
指令的语法格式
0RR.{} {S} , ,
其中,参数用法与AND指令相同c
指令操作的伪代码
if ConditionPassed(cond) then
Rd = Rn OR shifteroperand
if S == 1 and Rd — R15 then
CPSR = SPSR
else if S == 1 then
N Flag = Rd[31]
Z Flag = if Rd 二=0 then 1 else 0
C Flag - shiftercarry_out
V Flag = unaffected
指令的使用
ORR指令可用于将寄存器中某些位的值设置成1。具体作法是设置…个掩码值,将该 值中对应于寿存器中欲提取的位设为b其他的位设置成0°将寄存器的值与该掩码值做 逻辑或操作即可得到想提取的位的值。
示例
下面的代码将R2中的高8位数据传送到R3的低8位中。
MOV R0, R2, LSR #24 ;将R2的高8位数据传送到R0中,R0的高24位设置成。
OKR R3, R0, R3, LSL #8 ;将R3中数据逻辑左移8位,这时R3的低8位为°
;ORR操作将R0 (高24位为0)中低8位数据传送到寄存器R3中
11, EOR逻辑舞或操作指令
EOR指令将表示的数值与寄存器的值按位作逻辑异或操作、并 把结果保存到目标寄存器vRd>中,同时根据操作的结果更新CPSR中相应的条件标志 位。
指令的编码格式
31 28 27 26
25 24 21 20 19 16 15 12 11 _ Q
「cond 00 I I I 100 [s Rn Rd shifter^operand 
指令的港法格式
EOR(){S} , , 〈shifter oper^nd>
其中,参数用法与AND指令相同。
指令操作的伪代码
if ConditionPassed(cond) then
Rd = Rn EOR shifter operand
if S == 1 and Rd == R15 then
CPSR = SPSR
else if S == 1 then
N Flag = Rd[31]
Z Flag - if Rd 亍导 0 then 1 else 0 C Flag = shifter carryout
V Flag = unaffected
指令的使用
ORR指令可用亍将寄存器中某些位的值取反。将某 位与0做逻辑异或操作,该位 值不变:将某一位与I做逻辑异或操作,该位值将被求反。
示例

  1. BIC位清除指令
    BIC指令将<shifter^operand>表示的数值与寄存器vRn>的值的反码按位做逻辑与操 作,并把结果保存到目标寄存器<Rd>中,同时根据操作的结果更新CPSR中相应的条件 标志位。
    指令的编码格式
    31 28 27 26 25 24 21 20 19 16 15 12 11 0
    cond 00 1 1110 s Rn Rd shifter_opCTand
    指令的语法格式
    BIC(}{S} / ,

其中,各参数用法与AND指令相同。
指令操作的伪代码
if ConditionPassed(cond) then
Rd = Rn AND NOT shifter_operand if S == 1 and Rd == R15 then
CPSR = SPSR
else if S == 1 then
N Flag = Rd[31]
Z Flag = if Rd == 0 then 1 else 0 C Flag = shifT.ei.cdiry_out
V Flag = unaffected
指令的使用
B1C指令可用于将寄存器中某些位的值设置成0。将某••位与1做BIC操作,该位值 被设置成0:将某-位与1做BIC操作,该位值不变。
13. CMP比较指令
CMP指令从寄存器vRn>中减去表示的数值,根据操作的结果更新 CPSR中和应的条件标志位,后面的指令就可以根据CPSR中相应的条件标志位来判断是 否执行。
指令的编码格式
31 28 27 26 25 24 21. 20 19 16 15 12 11 0
cond 0 0 I 0 010 S Rn Rd shifleroperand
指令的语法格式
CMP{} ,
其中:
为指令执行的条件码。当忽略时指令为无条件执行° 罚&>寄存器为第}个操作数所在的寄存器。
为第2个操作数,其计算方法在2.2节有详细介绍。
指令操作的伪代码
if ConditionPassed(ccnd) then
alu_out = Rn - shifteroperand
N Flag = alu_out[311
Z Flag 金 if alu out == 0 then 1 else 0
C Flag = NGT BorrowFrom (Rn - shifter_operand)
V Flag - OverflowFrom(Rn - shifter_operand)
措令的使用
CMP指令与SUBS指令的区别在于CMP指令不保存操作结果。
14. CMN基于相反数的比较指令
CMN指令将寄存器vRn>中的值加上<shifter
operand>表示的数值,根据操作的结果 更新CPSR中相应的条件标志位,后面的指令就可以根据CPSR中相应的条件标忐位来判 断是否执行。
指令的编码格式
31 23 2726 25 24 21 20 lg 16 15 lj 11 0
I cond I 00 I Mi l 卜 Rfl I Rd [扁ejoperand |
指令的语法格式
CMN{} ,
其中,各参数与CMP比较指令用法相同。 
指令操作的伪代码
if ConditionPassed(cond) then
alu_out = Rn + shifter_operand
N Flag = alu_out[31]
Z Flag = if alu_out == 0 仁hen 1 else 0
C Flag = CarryFrom(Rn + shifter_operand}
V Flag = OverflowFrom(Rn + shifter operand)
指令的使用
CMN指令将寄存器<Rn>中的值加L<shifter_operand>表示的数值,根据加法操作的 结果设置CPSR中相应的条件标志位°寄存器vRn>中的值加上<shifter_operand>表示的数 值对CPSR中条件标志位的影响,勺寄存器vRn>中的值减去〈shifter.operand〉表示的数值 的相反数对CPSR中条件标志位的影响有细微的差别。当第2个操作数为0或者 0x80000000时二者结果不同,如;

  1. TST位测试指令
    TST指令将<shifter_operand>表示的数值与寄存器<Rn>的值按位做逻韓与操作,根据 操作的结果更新CPSR &相应的条件标志位。
    指令的编码格式
    31 28 27 26 25 24 2120 19 16 15 12 1: 0
    cond 0 0 I 0 0 10 S「Rn Rd shifter operand
    指令的请法格式
    TST{<cond>} <Rn>, <shifter_operand>
    其中,各参数用法与CMP比较指令用法相同。
    指令操作的伪代码
    if ConditionPassed(cond) then
    alu_out = Rn AND shifteroperand
    N Flag = alu_out[31]
    Z Flag = it alu_out == 0 then I else 0
    C Flag = shiftercarry out
    V Flag = unaffected
    指令的使用
    TST指令通常用于测试寄存器中某个(些)位是1还是0。
  2. TEQ相等测试指令
    TEQ指令将<shifter_opgnd>表不的数值与寄存器vRn>的值按位做逻辑异或操作,根 据操作的结果更新CPSR中相应的条件标志位。
    指令的编码格式
    31 28 27 26 25 24 21 20 丄9 16 15 12 1丄 0
    cond 0 0 I 10 01 S Rn Rd shifieroperand
    指令的语法格式
    TEQ{} ,
    其中,各参数用法与CMP比较指令用法相同。
    指令操作的伪代码
    if ConditionPassed(cond) then
    alu out = Rn EOR shifts.operand
    N Flag = alu_out[31]
    Z Flag = if aluout == 0 then 1 else 0
    C Flag = shifter carry o’_it
    V Flag = unaffected
    指令的使用
    TEQ指令通常用于比较两个数是否相等,这种比较操作通常不影响CPSR寄存器中 的V位和C位。
    TEQ指令也可用于比较两个操作数符号是否相同,该指令执行后,CPSR寄存器中的 N位为两个操作数符号位作异或操作的结果。
    3.1.3乘法指令
    ARM有两类乘法指令:一类为32位的乘法指令,即乘法操作的结果为32位:另… 类为64位的乘法指令,即乘法操作的结果为64位。两类指令共有以下6条:
    • MUL 32位乘法指令。
    • MLA 32位带加数的乘法指令。
    • SMULL 64位有符号数乘法指令。
    • SMLAL 64位带加数的有符号数乘法指令。
    • UMULL 64位无符号数乘法指令。
    • UMLAL 64位带加数的无符号数乘法指令°
  3. MUL
    MUL指令实现两个32位的数(可以为无符号数,也可为有符号数)的乘积,并将结果 存放到一个32位的寄存器中,同时可以根据运算结果设置CPSR寄存器中相应的条件标 志位。考虑指令执行的效率,指令屮所有操作数都放在寄存器中。
    指令的编码格式
    31 28 27 21 20 19 16 15 12 11 8 7 4 3 。
    cond 0000000 S Rd 应为 0 Rd 丨 100】 丨 Rm 1
    指令的语法格式
    MUL{〈COnd>”S} , ,
    其中:
    为指令执行的条件码。当忽略vcond>时,指令为无条件执行。
    S决定指令的操作是否影响CPSR屮的条件标志位N位和Z位的值。当有S时指 令更新CPSR屮的条件标志位的值;当没有S吋指令不更新CPSR中的条件标志 位的值i
    W存器为目标寄存器。
    〈Rs〉为第2个乘数所在的寄存器。
    指令操作的伪代码
    if ConditionPassed ;conRd = (Rm ★ Rs) [31:0]
    if S = 1 then
    N Flag = Rd[31]
    Z Flag = if Rd =g 0 then 1 else 0
    C Flag = unaffected /
    See ,rC flag” note _/
    V Flag = unaffected
    指令的使用
    由于两个32位的数相乘结果为64位,而MUL指令仅仅保存了 64位结果低32位, 所以对于带符号的和无符号的操作数来说MUL指令执行的结果相同。
    对于ARM v5及以上的版木,MULS指令不影响CPSR寄存器中的C条件标志位。 对于以前的版本,MULS指令执行后,CPSR寄存器中的C条件标志位数值是不确定的。 寄存器vRm>、vRn>及为R15时,指令执行的结果不町预测。
    示例
    MUL R0,Rl,R2 ; R0=RlR2
    MULS RO,R1,R2 ; ROR1
    R2,同时设置 CPSR 中 N 位和 2 位
  4. MLA
    MLA指令实现两个32位的数(可以为无符号数,也可为有符号数)的乘积,再将乘积 加上第3个操作数,并将结果存放到…个32位的寄存器中,同时可以根据运算结果设置 CPSR寄存器中相应的条件标志位。考虑指令执行的效率,指令中所有操作数都放在寄存 器中。
    指令的编码格式
    31 28 27 _21 20 19 16 15 12 U 8 ~l < 3 0
    指令的语法格式
    MLA{}(S} , , ,
    其中;
    为指令执行的条件码。汽vcond>忽略时指令为无条件执行。
    S决定指令的操作是否影响CPSR中的条件标志位N位和Z位的值。当有S时指 令更新CPSR中的条件标志位的值;没有S时指令不更新CPSR中的条件标志位 的值。
    vRd>寄存器为目标寄存器。
    vRm>寄存器为第1个乘数所在的寄存器。
    为第2个乘数所在的寄存器。
    vRn、为第3个操作数所在的寄存器,该操作数是一,个加数。
    指令操作的伪代码
    if ConditionPassedtcond) then
    Rd = (Rm Rs + Rn) J 31:0]
    if S == 1 then
    N Flag = Rd[31]
    Z Flag = if Rd == 0 then 1 else 0
    C Flag - unaffected
    V Flag = unaffected
    指令的使用
    由于两个32位的数相乘结果为64位,而MLA指令仅仅保存了 64位结果低32位, 所以对于带符号的和无符号的操作数来说MLA指令执行的结果相同。
    对于ARM v5及以上的版本,MLAS指令不影响CPSR寄存器中的C条件标志位。 对于以前的版本,MLAS指令执行后,CPSR寄存器中的C条件标志位数值是不确定的。
    寄存器. vRn>及^jR15时指令执行的结果不可预测。
    示例
    MLA RO,R1,R2,R3 ; RO=R1
    R2+R3
  5. SMULL
    SMULL指令实现两个32位的有符号数的乘枳,乘积结果的高32位存放到一个32 位的寄存器的vRdHi〉中,乘积结果的低32位存放到另-个32位的寄存器vRdLA中,同 时可以根据运算结果设置CPSR寄存器中相应的条件标志位。考虑指令执行的效率,指令 中所有操作数都放在寄存器中。
    指令的编码格式
    31 28 27 啓jj019 16 ;5 12 8 7 4 3 Q
    cond ] 00001 10 S RdHi RjLo Rd [ 1 0 01 | 屜 |
    指令的语法格式
    SMULL]}{S} , , ,
    其中:
    寄存器存放乘积结果的高32位数据。
    - ■ ■ - ■ TT^ -
    §存器存放乘积结果的低32位数据。
    其他参数用法参见MUL指令,
    指令操作的伪代码
    if ConditionPasseci (cand) then
    RdHi = [Rm Rs) [63:32] / Signed rrultiplication /
    RdLQ = (Rm
    Rs)[31:0]
    if S ==- 1 then
    N Flag = RdHi[31j
    Z Flag = if (RdHi == 0) ar.d (RdLo == 0) then 1 else 0
    C Flag - unaffected
    v Flag = unaffected
    指令的使用
    对于ARM v5及以上的版本,SMULL指令不影响CPSR寄存器中的C条件标志位和 V条件标志位。对于以前的版本,SMULL指令执行后,CPSR寄存器中的C条件标志位 数值是不确定的。
    寄存器vRm>、vRn>、及vRdHi>为R15时指令执行的结果不可预测。
    示例
    SMULL R1,R2,R3,R4 ; Rl= (R3TR4)的低 32 位
    ;R2= (R3-R4)的高 32 位
  6. SMLAL
    SMLAL指令将两个32位的有符号数的64位乘积结果与指令的编码格式
    31 28 27 212019 16 15 12 11 87 43 0
    End &000 1 1 1 S RdHi RdLo Rd 1 00 1 Rm
    指令的语法格式
    SMULL{}{S} VRdLo>, , ,
    其中:
    vRdHi>寄存器在指令执行前存放64位加数的高32位,指令执行后存放结果的 高32位数据。
    寄存器在指令执行前存放64位加数的低32位,指令执行后存放结果的 低32位数据。
    其他参数用法参见MUL指令。
    指令操作的伪代码
    if Cond-itionPassed (cond.) then
    RdL© = (Rm Rs) f31 : 0] + RdL。/ Signed multiplication /
    RdHi = (Rm Rs)[63:32) + RdHi + CarryFrom((Rm Rs)[31:0] + RdLo) if S =- 1 then
    N Flag = RdHi[31J
    Z Flag = if (RdHi == 0) and (RdLo == 0) then 1 else 0
    C Flag = unaffected
    V Flag
    unaffected
    指令的使用
    对于ARM v5及以上的版本,SMLAL指令不影响CPSR寄存器中的C条件标志位和 V条件标志位。对于以前的版本,SMLAL指令执行后,CPSR寄存器中的C条件标志位 数值是不确定的。
    寄存器vRmA、vRn>、vRdLo>及vRdHi>为R15时指令执行的结果不可预测。
  7. UMULL
    UMULL指令实现两个32位的有符号数的乘积,乘积结果的高32位存放到一个32 位的寄存器<RdHi>中.乘积结果的低32位存放到另一个32位的寄存器vRdLo>中,同时 可以根据运算结果设置CPSR寄存器中相应的条件标志位。考虑指令执行的效率,指令中 所有操作数都放在寄存器中。
    指令的编码格式
    3j 28 27 21 2019 16 15 12 11 87 4 3 0
    <ond 0000 也 S RdHi RdLo | Rd | J 0Oj Rm
    指令的语法格式
    UMULL{<cond>}{S} <RdLo>, <RdHi>r <Rm>, <Rs>
    其中,各参数用法参见SMULL指令。
    指令操作的伪代码
    if ConditionPassed(cond) then
    RdHi = (Rm
    Rs)[63:32]尸 Unsigned multiplication /
    RdLo = (Rm ‘ Rs)[31:0]
    if S == 1 then
    N Flag = RdHi[31]
    Z Flag = if (RdHi == 0) and (RdLo =- 0) then 1 else 0
    C Flag = unaffected
    V Flag = unaffected
    指令的使用
    对于ARM v5及以上的版本,UMULLS指令不影响CPSR寄存器中的C条件标志位 和V条件标志位。对于以前的版本,UMULLS指令执行后,CPSR寄存器中的C条件标 志位数值是不确定的。
    寄存器<Rm>、vRn>、<RdLo>及<RdHi>为R15时指令执行的结果不可预测。
    示例
    UMULL R:,R2,R3,R4 ; R2 R1=R3*R4
    6・ UMLAL
    UMLAL指令将两个32位的无符号数的64位乘积结果与和中的64位 无符号数相加,加法结果的高32位存放到一个32位的寄存器中,乘积结果的低32位存 放到另-个32位的寄存器中,同时可以根据运算结果设置CPSR寄存器中相应的 条件标志位。
    指令的编码格式
    31 2g_27
    21 20 19 16 15 12 11 8 7 4 3 0
    cop0」0四0 1」1 £ RdHi J指令的语法格式
    UMLAL{}(S) , ,
    其中:
    寄存器在指令执行前存放64位加数的高32位,指令执行后存放结果的 高32位数据。
    寄存器在指令执行前存放64位加数的低32位,指令执行后存放结果的 低32位数据。
    其他参数用法参见MUL指令。
    指令操作的伪代码
    if ConditionPa^sed(cond) then
    RdLo = (Rm
    Rs)[31:。: + RdL。 / Unsigned multiplication */
    RdHi = (Rm
    Rs) [63:32] + RdHi + CarryFroir,((Rm _ Rs) [31:0] + RdLo) if S == 1 then
    N Flag = RdHi[31]
    3 Flag = if (RdHi == 0) ard (RdLo == 0) then 1 else 0
    C Flag = unaffected
    V Flag = unaffected
    指令的使用
    对于ARM v5及以上的版本,UMLAL指令不影响CPSR寄存器中的C条件标志位和 V条件标志位。对于以前的版本,UMLAL指令执行后,CPSR寄存器中的C条件标志位 数值是不确定的。
    寄存器vRm>、. 及vRdHi>为R15时指令执行的结果不可预测。
    示例
    UMLAL R1,R2,R3,R4 ; R2 Rl= R3*R4 + R2 R1
    3.1.4杂类的算术指令
    在ARM v5及以上的版本中包含一条特别的指令CLZ,用于计算操作数最高端°的 个数。这条指令主要用于以下两种场合:
    • 计算操作数规范化(使其最高位为I)时需要左移的位数。
    • 确定个优先级掩码中最高优先级(最島位的优先级)。
    CLZ前导0个数计数指令
    CLZ扌旨令用于计算寄存器中操作数最高端0的个数。如果操作数的bit[31]为1,则指 令返回0;如果操作数为0,则指令返回32。
    指令的编码格式
    31 一 28 27 212。 19 1G15 12 11 87 430
    cgd 000 1 0 1 1 0 应为 0 | Rd 应为 0 000 1 〔Rm
    指令的语法格式
    CLZ{} ,
    其中:
    为指令执行的条件码。当忽略时指令为无条件执行。
    〈]<(1>为目标寄存器。
    寄存器为第1个乘数所在的寄存器。
    为源操作数寄存器。当为R15时,指令执行结果不可预知。
    指令操作的伪代码
    if Rm == 0
    Rd = 32
    else
    Rd = 31 - (bit. position of most significant ‘ 1’ in Rm}
    指令的使用
    下面的指令序列可以实现将寄存器[l>的数规范化。
    CLZ Rd, Rm
    MOVS Rm, Rn, LSL Rd
    3.1.5状态寄存器访问指令
    ARM中有两条指令用于在状态寄存器和通用寄存器之间传送数据。
    关于状态寄存器的详细知识在1.2节己有详细介绍,这里不再重复,仅强调以下几 点e
    状态寄存器中有些位是当前没有使用的,但在ARM将来的版本中有可能使用这地 位,因此用户程序不要使用这些位。
    程序不能通过宜接修改CPSR屮的T控制位直接将程序状态切换到Thumb状态,必 须通过BX等指令完成程序状态的切换。
    通常修改状态寄存器是通过“读取•修改•写冋”的操作序列来实现的。
    状态寄存器访问指令包括以下两条:
    • MRS状态寄存器到通用寄存器的传送指令。
    • MSR 通用寄存器到状态寄存器的传送指令。
  8. MRS
    MRS指令用于将状态寄存器的内容传送到通用寄存器中。 指令的编码格式
    0 0 0 I 1 0 R 0 0 SBO j Rd SBZ
    31 28 27 26 25 24 23 22 21 20 19 16 15 12 11
    Cond
    指令的虐法格式
    MR$(gnd>} , CPSR
    MRS() , SPSR
    其中:
    <cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行。其他指令中 <cond>的用法与此相同D
    vRd>为目标寄存器。
    指令操作的伪代码
    if if Condi二ionPassed(coed) then
    if R == 1 then
    Rd - SPSR
    else
    Rd = CPSR
    指令的使用
    MRS指令主要用于以下3种场合:
    • 通常通过“读取•修改•写回”操作序列修改状态寄存器的内容。MRS指令用于将 状态寄存器的内容读到通用寄存器中。
    • 当异常中断允许嵌套时,需要在进入异常中断之后,嵌套中断发生之前保存当前 处理器模式对应的SPSR。这时需要先通过MRS指令读出SPSR的值,再用其他 指令将SPSR值保存起来。
    • 在进程切换时也带要保存当前状态寄存器值。
  9. MSR
    MSR指令用于将通用寄存器的内容或••个立即数传送到状态寄存器「K
    指令的编码格式
    指令的源操作数为通用寄存器时,指令编码格式如R
    31 28 27 26 25 24 23 22 21 20 19 16 15 12 1187 4 3 0
    cond 0 0 0 1 0 R 1 0 field_niask SBO SBZ 0000 Rm
    指令的源操作数为立即数时,指令编码格式如下;
    31 28 27 26 25 24 23 22 21 20 19 16 15 12 11 8 1 0
    cond 0 0 1 1 0 R 1 0 fteld_mask SBO Rotatejmm 8_bit immediate I

指令的语法格式

其中;
设置状态寄存器中需要操作的位。状态寄存器的32为可以分为4个8位 的域;bi副31:24]为条件标志位域,用f表示;bits[23:t6]状态位域,用s表示; bits[15:8]r展位域,用x表Z5: bits[7:0]控制位域,用c表示。
〈immediate〉为将要传送到状态寄存器中的立即数,该立即数的计算方法在2.2节 有详细介绍。
寄存器包含将要传送到状态寄存器中的数据。
指令操作的伪代码
if ConditionPassed(cond) then
if opcode[25] == 1
operand = 8bit_iminediate Rotate_Right (rctate_imin 2) 角丄50 / opcode[25] 0 */
operand = Rm
if R == 0 then
if field_mask[O] :== 1 and InAPrivilegedMode (\ then CPSR[7 i 0] = operand[7:0]
iz f ield_niask [1] === 1 and InAPrivilegedMode () then CPSR[15:8] = operand[15:8]
if f ield_mask [2] === 1 and InAPrivilegedMode (} then CPSR[23;16] = operand[23:16]
if field_maskI3J 七=1 then
CPSR[31:24] = operand[31:24j
else /■
R == 1 _/
if field_mask[0]七* 1 and CurrentModeHasSFSR() then SPSR[7:0] = operand[7;0]
if field mask[1] w= i and CurrentModeHasSPSR() then
SPSR[15:8] = operand[15:8)
if field__mask:[2] “ 1 and CurrentModeHasbFSFif) then SPSR[23:16] = operandf23:16]
if field mask[3] === 1 and CurrentModeHasSPSR() then
SPSR[31:24] = operand[31:24]
指令的使用
MSR指令通常用于恢复状态寄存器的内容或者改变状态寄存器的内容。
当退出异常中断处理程序时,如果事先保存了状态寄存器的内容(如在嵌套的异常中 断处理中)通常通过MSR指令将事先保存的状态寄存器内容恢复到状态寄存器中。
当需要修改状态寄存器的内容时,通过“读出•修改•写回”指令序列完成。写冋操作 也是通过MSR指令完成的。
考虑到指令执行的效率,通常在MSR指令中指定指令将要修改的位域。例如,下面
的指令序列将处理器模式切换到特权模式,这里只修改状态寄存器的控制位域,所以在指 令中指定该位域。
;读取CPSR
;修改,去除当前处理器模式
;修改,没置特权模式
;写四,仅仅修改GPSR中的控制位域
但是,当进程切换到应用场合,应指定SPSR_hxc,这样将来ARM扩展了当前未用 的一些位后,程序还可以疋常运行°
当欲修改的状态寄存器位域中包含未分配的位时,最好不要使用立即数方式的MSR 指令。•■个例外的情况是可以使用立即数方式的MSR指令修改状态寄存器中的条件标志 位位域。
3.1.6 Load/Store内存访问指令
Load指令用于从内存中读取数据放入寄存器中:Store指令用于将寄存器中的数据保 存到内存。ARM有两大类的Load/Store指令;-类用于操作32位的字类型数据以及8位 无符号的字节类型数据;另-类用于操作16位半字类型的数据以及8位的有符号字节类 型的数据。
Load/Store内存访问指令的…个操作数放在寄存器中,另■…个操作数的寻址方式参见 2.2 节。
用于操作32位的孑类型数据以及8位无符号的字节类型数据的Load/Store指令有以 下指令。
• LDR字数据读取指令.
• LDRB字节数据读取指令。
• LDRBT用户模式的字节数据读取指令。
• LDRH半字数据读取指令。
• LDRSB有符号的字节数据读取指令。
• LDRSH有符号的半字数据读取指令。
• LDRT用户模式的字数据读取指令。
• STR 字数据写入指令。
• STRB字节数据写入指令。
• STRBT用户模武字节数据写入指令。
• STRH半字数据写入指令。
• STRT用户模式字数据勾入指令°

  1. LDR(字数据读取指令)
    LDR指令用于从内存中将一个32位的字读取到指令中的目标寄存器中。如果指令中 寻址方式确定的地址不是字对齐的,则从内存中读出的数值要进行循环右移操作,移位的 位数为寻址方式确定的地址的bits[l:O]的8倍。这样对于little-endian的内存模式,指令想 要读取的字节数据存放在目标寄存器的低8位;对于big-endian的内存模式,指令想要读
    取的字节数据存放在目标寄存器的bits[31:24](寻址方式确定的地址bit[O]为0或者 bits[15:8]寻址方式确定的地址bit[O]为》
    指令的编码格式
    31 28 27 26 24 23 22 21 20 19 16 25 12 11 0
    I cond 0 1 I ) P U 0 W 1 Rn Rd | address] ng_modc
    指令的语法格式
    LDR{} ,
    其中;
    vcond>为指令执行的条件码。当忽略时指令为无条件执行。本小节其他指 令中vcond>用法与此相同。
    vRd>为目标寄存器°
    为指令的寻址方式参见2.2节。
    指令操作的伪代码
    if ConditionPassed(cond) then if address[1;0] == ObOO then value = Memory[address, 4] else if address[1:0] == ObOl value = Memory[address,4] else if address[1:0] =- OblO ‘ value = MenoryFaddress,4] else /* address[1:0] =- Obll value = Memory[address,4] if (Rd is R15) then
    if (architecture version 5 or above) then ?C = value ANE OxFFFFFFFE
    T Bit = value [0]
    else
    ?C = v^lue ANE OxFFFFFFFC
    else
    Rd = value
    指令的使用
    LDR指令通常的用法有以下两种:
    • 用于从内存中读取32位字数据到通用寄存器中,然后可在该寄存器中对数据进 行一定的操作。
    • 当PC作为指令中的目标寄存器时,指令可以实现程序跳转的功能。
    当PC被作为LDR指令的目标寄存器时,指令从内存中读取的字数据将被当作目标 地址值,指令执行后程序将从目标地址处开始执行,即实现了跳转操作。在ARMv5及以 上的版本中,地址值的bit[O]用来确定目标地址处的程序状态,当bit[O]为1时目标地址处 指令为Thumb指令;当bit[O}为0时目标地址处指令为ARM指令。在ARM v5及以前的 版本中,地址值的bits[l:O]被忽略,程序继续执行在ARM状态。

;将内存单元Rl+4中的字读取到RO寄存器中
;将内存单AR1-4中的宇读取到R0寄存器屮
;将内存单元R1+R2中的字读取到R0寄存器中
;将内存单兀R1-R2中的字读取到R0寄存器中
;将地址単兀(Rl+R24)中的数据读取到R0中
;将内存单元(R1 + 4)中数据读取到R0中,同旳Rl=Rl + 4
;将内存单元(R1+R2)中数据读取到R0中,同吋R1MRL + R2
;将内存单元(Rl+R2
4)中数据读取到R0中,同时
;R1=R1+R24
:将地址为R1的内存单元数据读取到R0中,然后Rl=Rl + 4
;将地址为R1的内存单元数据读取到R0中.然后Rl=Ri + R2
;将地址为R1的内存单元数据读取到R0中,然后R】=R1+R2
4
2. LDRB(字节数据读取指令)
LDRB指令用丁从内存中将一个8位的字节数据读取到指令中的目标寄存器中。并時 寄存器的髙24位清零。
指令的编码格式
31 28 27 26 25 24 23 22 21 20 1.9 16 15 12 11 0
cond ! 0 1 I P U 1 W 1 Rn Rd addressing mode
指令的语法格式
LDR{}B ,
各参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cond)二hen
Rd = Memory[address,1 ;
指令的使用
LDRB指令通常的用法有以下两种:
• 用于从内存中读取8位字节数据到通用寄存器中,然后可在该寄存器屮对数据进 行一定的操作。
• 当PC作为指令中的目标寄存器时,指令可以实现程序跳转的功能。
示例
LDRB R0,[R2,#3);将内存单兀(R2 + 3)中的字节数据读取到R0中,R0中高24位设壕成0 LDRB RO,[R1] ;将内存堂元(R1)中的了节数据读取到R0中,叫中高24位设置成0
3. LDRBT(用户模式的字节数据读取指令)
LDRBT指令用于从内存中将 个8位的字节数据读取到指令中的目标寄存器中。并 将寄存器的高24位清零。当在特权级的处理器模式下使用本指令时,内存系统将该操作 当作•殷用户模式下的内存访问操作。
cond 0 1 ] 0 U 1 1 1 Rn Rd addressingmode
指令的编码格式
31
28 27 26 25 24 23 22 21 20 19
16 15
12 11
指令的语法格式
LDR(IBT ,

其中,其他参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cond) then
Rd = Memory[address,1]
指令的使用
异常中断程序是在特权级的处理器模式下执行的,这时如果需要按照用户模式的权限 访问内存,可以使用LDRBT指令。
4. LDRH (半字数据读取指令)
LDRH指令用于从内存中将,个16位的半字数据读取到指令中的目标寄存器中。并 将寄存器的高16位清霎。
如果指令中的内存地址不是半字对齐的,指令会产生不可预知的结果•
指令的编码格式
31 28 27 26 2= 24 23J2 21 20 19 1615 12 也 8 7 4 = 0
| cond | 0 I 0 P U I W 1 Rji Rd 」addr_mode |1。1丨 I addr_mode |
指令的语法格式
LDR{«ond>}H ,
其中,参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cond) then
if address[0] == 0
data = Memory[address,2|
else /
address[0] == 1 /
data = UNPREDICTABLE
Rd = data
指令的使用
LDRH指令通常的用法有以下两种:
•用于从内存中读取16位半字数据到通用寄存器中,然后可在该寄存器中对数据 进行一定的操作。
•当PC作为指令中的目标寄存器时,指令可以实现程序跳转的功能。
示例
LDRH RO, [Rl] ;将内存单元(Rl)中的半字数挺读取到R0中,R0中髙16位设置成0
LDRH RO,〔R1,#2J ;内存单元(fU , 2)中的半字数据读取到RG中,冏屮髙16位设置成0 LDRH RO, [R1,R2];将内存単元(R1+R2)中的半字数锯读取到R0屮.R0中髙16位设•置成0
LDRH RO,[R1],#2;将内存单元(R1)中的平•字数据读取到叫中,R)中岛」6仲设置成0;
;Rl=Ri”
5. LDRSB «符号的字节数据读取指令)
LDRSB指令用于从内存中将■•个8位的字节数据读取到指令屮的冃标寄存器中。并 将寄存器的高24位设置成该孕有数据的符号位的值(即将该8位字节数据进行符号位扩 展,生成32位字数据)。
指令的编码格式
31 28 27 26 2§ 2勺 23 22 21 20 19 16 15 12 1丄 8。 4 3
0
cond 000PU1 WIRn Rd addr mode 1101 addjmode
指令的语法格式
LDR{)SB ,
其中,各参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cond) then
data = Memory[addressy1]
Rd = SignExtend(data)
指令的使用
LDRSB指令通常的用法有以下两种;
• 用于从内存中读取8位有符号字节数据到通用寄存器中,然后可在该寄存器中对 数据进行一定的操作。
• 当PC作为指令中的冃标寄存器时,指令可以实现程序跳转的功能。
示例
LDRSB RG,[R1,#3} ;将内再単元(R1 + 3)中的有符号字节数据读取到R0中,R。中髙24位
;设置成亥了节数据的符号位,
LDRSB R7,iR6,#-l〕!;将内存单元(R6-1)中的有符号字Y数据读取到2中・质中商24位 ;设置成演字节数据的符另•位;R6=R6-1
6. LDRSH(有符号的半字数据读取指令)
LDRSH指令用于从内存中将-个16位的半字数据读取到指令中的目标寄存器中。并 将寄存器的高12位设置成该半字数据的符号位的值(即将该16位半字数据进行符号位扩 展,牛成32位字数据)。
如果指令中的内存地址不是半字对齐的,指令会产生不可预知的结果。
指令的编码格式
31 矣 27 2 6 25 24 2321 2。19 1615. 12 11 f 7 4 3 °
I C(>nd 0 0 0 P U 1 W 1 Rn Rd addr,modc 11H addr mode
指令的语法格式
;j?R/ JSB ,〈addressing mode〉 其中,各参数用法参见LDR指令。
指令澡作的伪代码
if ConditionPassed(cond) then
if address[0j == 3
data = Memory[address, 21
else / address[0] “ 1 /
data - UNPREDICTABLE
Rd = SignEx”nd (data)
指令的使用
LDRSH指令通常的用法有以下两种;
• 用于从内存中读取16位的有符号半字数据到通用寄存器中,然后可在该寄存器 中对数据进行一定的操作。
• 当PC作为指令中的目标寄存器时,指令可以实现程序跳转的功能。
示例
LDRSH RO,[R1,#3) ;将内存里元(R1+3)中有符号的半字数据读取到R0中.R0中高位
;设置成该半字的符弓位;
LDRSH F7, [R6,#2J!;将内存車元(K6R)中的•宇节■数据读取到R7中,R0中髙拓位没置成
;该半字的符号位;RER6+2
7. LDRT(用户模式的字数据读取指令)
LDRT指令用于从内存中将一个32位的字数据读取到指令中的日标寄存器中。如果 指令中寻址方式确定的地址不是字对齐的,则从内存中读出的数值要进行循环右移操作, 移位的位数为寻址方式确定的地址的bits[l:O]的8倍。这样对于iittie-endian的内存模式, 指令想要读取的字节数据存放在目标寄存器的低8位;对T big-endian的内存模式,指令 想要读収的字节数据存放在目标寄存器的bits[31:24](寻址方式确定的地址bit[O}为0)或者 bits[15:8](寻址方式确定的地址bit[O]为1)。
当在特权级的处理器模式下使用本指令时,内存系统将该操作当作•般用户模式F的 内存访问操作。
指令的编码格式
31 28 27 26 25 24 £3 弟 21 20 19 16 15 12 11 一. 。
2混 01 I 0 U 0 1 1 Rn Rd addressing modc
指令的语法格式
LDR(}T ,
其中,各参数用法参见LDR指令。 指令操作的伪代码
if ConditionPassed (cond.) then
if address * 1:0] == ObOO
Rd 尘 Memory[address,] else if address[i:0] == ObOl
Rd - Memory[address,4] RotateRight 8 else if address [1:0] == Ot)l 0
Rd = Memory;address,4] Rotate_Right 16 else /
addressfl:0] == Qbll _/
Rd = Memory ^address,4 J Rotate_Right 24
指令的使用
异常中断程序是在特权级的处理器模式卜执行的, 访问内存,可以使用LDRT指令。
8. STR字数据写入指令
STR指令用于将一个32位的字数据写入到指令中指定的内存单元。
指令的编码格式
3丄 28 27 26 25 ?4 23 刀 21 20 19 16 JL5 12 11 0
cond 0 1 IPUOWORn Rd addressingmode
指令的语法格式
STR{〈cond、} ,
其中:
为指令执行的条件码。当忽略时指令为无条件执行。 为目标寄存器。
为指令的寻址方式。
指令操作的伪代码
if CcnditionPassed(cond) then
Memory[address;4] ・ Rd
指令的使用
STR指令用于将一,个32位的字数据写入到指令中指定的内存单元。
示例
;将R0中的字数据保存到内存单元(R1+0X100)中
;将R0中的字数据保存到内存单元(R1)中,R1-R1+8

  1. STRB(字节数据写入指令)
    STRB指令用于将一个8位的字节数据写入到指令中指定的内存单元,该字节数据为 指令中存放源操作数的寄存器的低8位。
    指令的编码格式
    31 28 27 26 25 24 23 22 21 20 19 16 15 12 11
    addressing_mode
    cond
    ll P U J I W 0 j Rn
    Rd

L,—, —^―>* .
指令的语法格式
STR{}B ,
其中,各参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cord) then
Memory[address,]] = Rd[7:0]
指令的使用
STRB指令用于将寄存器中低8位的字节数据弓入到指令中指定的内存单元.
示例
STRB R3, (R5, #0x200] ;将R3中的低8位数据保存到内有单元(R5+0x200)中
S7RB R3,【R5, #0x200] ! ;将R3中的低8位数据保存到内存.单元(R5 + 0x200)中,
;R5=R5・Ox200
10. STRH(¥字敏据写入指令)
STRH指令用于将-个16位的半字数据写入到指令中指定的内存单兀,该半字数据 为指令中存放源操作数的寄存器的低16位。
如果指令中的内存地址不是半字对齐的,指令会产生不可预知的结果。
指令的编码格式
31 28 27 26 25 £4 23^22 21 20 19 16 15 12 11 足「: .43 。
cond 000 PUI W 0 Rn Rd Addrmode I OH Addrmode
指令的语法格式
STR{}H ,
其中,各参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed(cond) then
if address[0] == 0
datm = Rd[15:0]
else / address[0J == 1 /
data = UNPREDICTABLE
Memory[address F 2] = data
指令的使用
STR指令用于将寄存器中低16位的半字数据写入到指令中指定的内存单元。
示例
STRH R0, [R1,R2] ;将R0中的低16位数据保存到内存单四(R1+R2)中
STRH RO”R1],#8 ;将R0中的低16位数据保存到内存单元(Rl)。同RMR17 
11. STRT(用户模式的字数据写入指令)
STRT指令用丁将一个32位的字数据写入到指令中指定的内存单元。
当在特权级的处理器模式下使用本指令时,内存系统将该操作当作•般用户模式下的 内存访问操作°
cond 0 1 1 ° U 0 1 0 Rn Rd address ingmode
指令的编码格式
31
28 27 26 25 24 23 22 21 20 19
16 15
0
指令的语法格式

$TR{〈8nd>}T ,
其中,各参数用法参见LDR指令°
指令操作的伪代码
if ConditionPassed(cond) then
Memory[acdress,4] = Rd
指令的使用
异常中断程序是在特权级的处理器模式下执行的,这时如果需要按照用户模式的权限 访问内存,可以使用STRT指令。
12. STRBT(用户模式的字节数据写入指令)
STRBT指令用于将一个8位的字节数据写入到指令中指定的内存单元。
当在特权级的处理器模式下使用本指令时,内存系统将该操作当作一般用户模式下的 内存访问操作。
指令的编码格式
31 …28 27 26 25 24 23 22 21 20 19 15 12 11 9
cond 0 1 I 0 U 1 1 0 Rn Rd addressingmode
指令的唐法格式
STR{VRd>,
其中,各参数用法参见LDR指令。
指令操作的伪代码
if ConditionPassed. (condt then
Memory[address,1] = Rd:7;0]
指令的使用
异常中断程序是在特权级的处理器模式下执行的,这时如果需要按照用户模式的权限 访问内存,可以使用STRBT指令°
92 ARM体系结枸与编程
3.17 批量Load/Store内存访间指令
批量Load内存访问指令可以一次从连续的内存単元中读取数据,传送到指令中的内 存列表中的各个寄存器中。
批量Store内存访问指令可以将指令中寄存器列表中的各个寄存器值写入到内存中, 内存的地址由指令中的寻址模式确定。
Load/Store内存访问指令的语法格式如下:
LDM I STM{ } Rn ( ! } , { A }
其中,操作数的寻址方式参见2.2节。
批量Load/Store内存访问指令主要有以下几条:
• LDM(l)批暈内存字数据读取指令。
• LDM(2)用户模式的批量内存字数据读取指令。
< LDM(3)带状态寄存器的批景内存字数据读取指令。
• STM(l)批量内存字数据写入指令。
• STM(2)用户模式的批童内存字数据写入指令。
1- LDM(1)(批童内存字数据读取指令)
LDM(l)指令将数据从连续的内存单元中读取到指令中寄存器列表中的各寄存器 中。它主要用于块数据的读取、数据栈操作以及从了程序中返回的操作。
当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的字数据将被当作目 标地址值,指令执行后程序将从目标地址处开始执行,即实现了跳转操作。S ARM v5及 以上的版木中.地址值的bit0用来确定目标地址处的程序状态,当bit[0]为1时目标地址 处指令为Thumb指令;当bit[0}为0时目标地址处指令为ARM指令°在ARM v5及以前 的版本中,地址值的bits[l:O]被忽略,程序继续执行在ARM状态。
指令的编码格式
31 28 27 26 25 24 23 22 21 19 16 項 0
cond I 1 0 0 P JJ 0 刖丄 Rn register_Iisi I
指令的语法格式
LDM{) (:},
其中:
为指令执行的条件码。当忽略时指令为无条件执行。 VRRA为指令寻址模式中的基址寄存器。存放地址块的最低地址值。
!设置指令中的W位,使指令执行后将操作数的内存地址写入基址寄存器 中。
为指令的寻址方式。
〈registers〉”寄存器列表。其中寄存器和内存单元的对应关系满足这样的规则, 即编号低的寄存器对应于内存中低地址单元,编号高的寄存器对应于内存中高地
址单兀。
指令操作的伪代码
i f ConditionPassed tcond) then
address 二 start address
for i n 0 co 14 if register_list ;i] == 1 then
Pi = Menory[address, 4]
address = address + 4
if register_list[15] == 1 then
value = Memory[address,4j
if (architecture version 5 or above) Lhen
pc = value AND OxFFFFFFFE
T Bit - valueJO]
else
pc = value AND OxFFFFFFFC
address = address * 4
assert end address = address - 4
指令的使用
如果指令中基址寄存器在寄存器列表中,而且指令中寻址方式指定指 令执行后更新基址寄存器的值,则指令执行会产生不可预知的结果。
2. LDM(2)(用户模式的批量内存字数据读取指令)
LDM(2)指令将数据从连续的内存单元中读取到指令中寄存器列表中的各寄存器中。它 主要用于块数据的读取、数据栈操作以及从子程序中返回的操作。
PC寄存器不能包含在LDM指令的寄存器列表中。
当在特权级的处理器模式下使用本指令时,内存系统将该操作当作一般用户模式下的 内存访问操作。
指令的编码格式
3: 28 27 26 25 24 23 22 21 2。】9 16 止 . Q

| cond I 1 0 P U [丄 0 1 Rn register list —
指令的语法格式
LDM{} , A
其中;
为寄存器列表,本列表不能包含PC寄存器。其中寄存器 和内存单总的对应关系满足这样的规则,即编号低的寄存器对应于内存中低地址 单元,编号高的寄存器对应于内存中高地址单无。vRn>中存放地址块的最低地 址值。
八在寄存器列衣中不含PC寄存器时,指示指令中所用的寄存器为用户模式下的 寄存器。
其他参数用法参见LDM(l)指令。
指令操作的伪代码
if ConditionPa^sed(cond) then
address = start address
for i = 0 to 14
if registerlist[i] == 1 Riusr = Memory[address, 4]
. address = address 卜 4
T
assert endaddress == address - 4
指令的使用
本指令后面不能紧跟访问备份寄存器(banked registers)的指令,最好跟条NOP指 令。
在用户模式和系统模式下使用本指令会产生不可预知的结果C
指令中的基址寄存器是指令执行时的当前处理器模式对应的物理寄存器,而不是用户 模式对应的寄存器。
本指令忽略指令中内存地址的低2位.而不像LDM(l)指令那样进行数据的循环右移 繰作。
异常中断程序是在特权级的处埋器模式下执行的,这时如果需要按照用户模式的权限 访问内存,可以使用LDM(2)指令。
3. LDM(3)(带状态寄存器的批■内存字数据读取指令)
LDM(3)指令将数据从连续的内存单元中读取到指令中寄存器列表f的各寄存器中。它 同时将当前处理器模式对应的SPSR寄存器内容复制到CPSR寄存器中。
当PC包含在LDM指令的寄存器列表中时,指令从内存中读取的字数据将被当作目 标地址值,指令执行后程序将从目标地址处开始执行,即实现了跳转操作。在ARMV5及 以上的版本和T系列的ARM v4版本中,SPSR寄存器的T位将复制到CPSR寄存器的T 位,该位决定目标地址处的程序状态。在以前的版本中程序继续执行在ARM扶态。
指令的编码格式
31 28 27 26 25 24 23 22 21 20 19 15 C
| cond 1 0 0 P U 1 区 1 Rn register list I
指令的语法格式
LDM{} {!If -
其中;
vregisters.with_pc>为寄存器列表,在本格式的指令中寄存器列表中必须包含PC 寄存器。患中寄存器和内存单元的对应关系满足这样的规则,即编号低的寄存器 对应于内存中低地址单元,编号高的寄存器对应F内存中髙地址单元。<丽>中 存放地址块的最低地址值。
人指示指令中执行时将当前处理器模式下的SPSR值复制到CPSR中。若指令的 寄存器列表中不包含PC寄存器,则该指令为一条LDM(2)格式的指令。
其他参数用法参见LDM(l)指令。
指令操作的伪代码
if CondiUonPassed (ccmd) then
address =■ start_3ddress
for i = 0 to 14 if register_list[i] == 1 then
Ri = Memory[address,4]
address = address + 4
CPSR = SPSR
value = Memory(address, 4]
if (architecture version 4T, 5 or above) and (T Bit == 1) then pc = value AND OxFFFFFFFE
else
pc = value AND OxFFFFFFFC
address = address + 4
assert end address = address - 4
指令的使用
如果指令中基址寄存器<Rn>在寄存器列表<registers>中,而且指令中寻址方式指定指 令执行后更新棊址寄存器vRn>的值,则指令执行会产生不可预知的结果。
本指令主要用于从异常中断模式下返回,如果在用户模式或系统模式卜使用该指令, 会产生不可预知的结果。
4. STM(1)(批■内存字数据写入指令)
STM(l)指令将指令中寄存器列表中的各寄存器数值写入到连续的内存单元中。它主 要用于块数据的写入、数据栈操作以及进入子程序时保存相关的寄存器的操作。
指令的编码格式
31 28 27 26 25 24 23 22 21 20 19 16 15

cond 10 0 P JJ 0 W 0 Rn
register list |
指令的语法格式
STM{)Caddressi ngmode> { I}/
其中;
为指令寻址模式中的基址寄存器,用于存放地址块的最低地址,如果R技 被作为,指令会产生不可预知的结果。
其他参数用法参见LDM(l)指令
指令操作的伪代码
if ConditionPassed [cond) then
address = start_address for i = 0 to 15
if register_list [i] === 1 Memory[addressr 4] = Ri address - address + 4 -
assert end address address - 4
指令的使用
如果指令中基址寄存器在寄存器列表〈registers〉中,而且指令中寻址方式指定指 令执行后更新基址寄存器vRn>的值,则当是〈register〉中编号最小的寄存器时,指令 将vRn>的初始值保存到内存中;否则,指令执行会产生不可预知的结果。
5. STM(2)(用户模式的批■内存字数据写入指令)
STM(2)指令将指令中寄存器列表中的各寄存器(用户模式对应的寄存器)数值号入到 连续的内存单元中。它主要用于块数据的写入、数据栈操作以及进入子程序时保存相关的 寄存器的操作。
指令的编码格式
3: 28 27 26 25 * 23 22 21 20 19 16 15 0
cond 1 0 0 P U | 1 0 0 Rn
register list |
指令的语法格式
STM( } F A
其中:
为指令寻址模式中的基址寄存器,存放地址块的最低地址值,如果R15被 作为vRn>,指令会产生不可预知的结果。
八指示指令中所用的寄存器为用户模式对应的寄存器。 其他参数参见LDM(l)指令。
指令操作的伪代码
if Conditionpass如(cond) then
address = startaddress
for i = 0 to 15
if registerList[i] == 1 Memcry[address,4] = Riusr address = address + 4 assert end__address == address - 4
指令的使用
本指令主要用于从异常中断模式下返回,如果在用户模式或系统模式下使用该指令, 会产生不可预知的结果。
本指令后面不能紧跟访问备份寄存器(banked registers)的指令,最好跟…条NOP指 令。
指令中的基址寄存器是指令执行时的当前处理器模式对应的物理寄存器,而不是用户 模式对应的寄存器。
3.1.8信号量操作指令
信号量用于进程间的同步和互斥。对信号景的操作通常要求是个原子操作,即在一
第3* ARM指令集介绍 97
1 III. ■
;■ |
条指令中完成信号量的读取和修改操作。ARM提供了如下两条指令完成信号最的操作:
• SWP交换指令。
• SWPB字节交换指令。
1- SWP(交换指令)
SWP指令用于将一个内存学单元(该单元地址放在寄存器vRn>中)的内容读取到一个 寄存器<RdA中,同时将另-个寄存器的内容写入到该内存单元中。当<Rd>和<Rni> 为同…个寄存器时,指令交换该寄存器和内存单元的内容。
指令的编码格式
31 28 27 20 19 16 15 12 11 8 7 4 3 0
cond 0 0 0 1 0 0 0 0 Rn 「Rd 应为 Q 项01 RE
指令的语法格式
SWP{<cond>} <Rd>, <Rrn>, [<Rn>]
其中:
<cond>为指令执行的条件码。当<cond>忽略时指令为无条件执行°
<Rd>为目标寄存器。
<Rm>寄存器包含将要保存到内有中的数值。
<Rn>寄存器中包含将要访问的内存地址。
指令操作的伪代码
if ConditionPassed(cond) then
if Rn [ 1: 01 ==■ ObOO then
temp = Memory(Rn,4]
else if Rn[l:0] == ObOl then
temp = Memory[Rn,4] Rotate_Right 8
else if RnI1:0] “ OblO then
temp = Memory[Hn,4] Rotate_Right 16
else /
Rn[1!0] == Obll _/
temp = Memory4] Hotate_Right 24
Memory[Rn,4 j = Rm Rd = temp
指令的使用
本指令主要用于实现信号量操作。
示例
SWP RLR2, [R3];将内存单元(R3)中字数据读取到R1寄存器中’同时将R2寄存器的数据写 ;入到内存单元(R3)中
SWP R1,R1, [R2];将R1寄存器内容和内存单元(R2)的内容巨换
2. SWPB(字节交換指令)
SWPB指令用于将一个内存字节单元(该单元地址放在寄存器<丽>中)的内容读取到• 个寄存器vRd>中,寄存器<Rd>的高24位设置为0,同时将另一个寄存器<Rm>的低8位
数值写入到该内存单元中。当?U为同一,个寄存器时.指令交换该寄存器低8位 和内存字节单元的内容。
Ccnd 0 0 0 1 0 1 0 0 Rn ! Rd 应为0 1001 Rm
指令的语法格式
8 7
20 19 1615 12 11
指令的编码格式
31 28 27
3 0
SWP(} , []

其中,各参数用法参见SWP指令。 指令操作的伪代码
if ConditionPassed(cond) then temp = Memcry[Rn,1] Memory [Rn, Ij = Rm口;0] Rd = temp
指令的使用
本指令主要用于实现信号童繰作,
示例
SWPB R1.R2, [R3];将内存单元(R3)中字节数据读取到R1寄存器中,R1的髙24位为0,
;同时将R2寄存器的低8位写入到内存单兀(R3)中
3.1.9异常中断产生指令
ARM有两条异常中断产生指令:软中断指令SW1用于产生SW1异常中断,ARM正 是通过这种机制实现在用户模式对操作系统中特权模式的程序的调用;断点中断指令 BKPT在ARMv5及以上的版本中引入,主要用于产生软件断点,供调试程序使用。
• SW1软中断指令。
• BKPT断点中断指令。

  1. SWI(软中断指令) SWI指令用于产生软中断。
    指令的编码格式
    32 28 27 24 23 ?
    cond 1111 immed 24
    指令的语法格式
    SWI {!
    其中:
    为指令执行的条件码。当忽略时指令为无条件执行。
    vimmed 24>为24位的立即数。该立即数被操作系统用来判断用户程序请求的服
    务类型。
    指令操作的伪代码
    if ConditionPassed(cond) then
    R14〜sue = address of next instructioEi after the SWI instruction
    SPSR£VC - CPSR
    CPSR[4:0] = OblOOll /
    Enter Supervisor mode /
    CPSR[5J = 0 /
    Execute in AKM state /
    /
    CPSR(6] is unchanged /
    CPSB [?] = 1 /
    Disable normal interrupts _/
    if high vectors configured then
    PC = OxFFFF0008
    else
    PC = 0x00000008
    指令的使用
    本指令主要用F用户程序调用操作系统的系统服务。操作系统在SWI的异常中断处 理程序中提供相关的系统服务,并定义了参数传递的方法。通常有以卜•两种方法;
    • 指令中24位的立即数指定了用户请求的服务类型,参数通过通用寄存器传递。
    • 指令中的24为立即数被忽略,用户请求的服务类型由寄存器R0的数值决定, 参数通过其他的通用寄存器传递。
  2. BKPT(断点中断指令)
    BKPT指令用于产生软件断点中断。软件调试程序可以使用该中断。当系统使用硬件 调试部件时可忽略该中断。
    指令的编码格式
    31 28 27 20 19 8 7 4 3 0
    1110 Q 0 0」0 010 | itnmed 0 111 immed
    指令的活法格式
    BKPT
    其中,〈immediate〉为16位的立即数。该立即数被调试软件用来保存额外的断点信 息o
    指令操作的伪代码
    if (not overridden by debug hardware)
    R14abt = address of BKPT instruction + 4
    SPSRabt = CPSR
    CPSR【4;0] = 0^10111
    CPSR[5] = 0 /
    使程序处于ARM状态/
    /
    CPSR [6] is tinchangec /
    CPSR[7] = 1 /
    禁止正常中断_/
    if high vectors configured then
    PC = OxFFFFOOOC
    else
    PC % OxOOOOOOGC
    指令的使用
    木指令主要供软件调试棉序使用
    3110 ARM协处理器指令
    ARM支持I6个协处理器。在程序执行过程中,每个协处理器忽略属T ARM处理器 和其他协处理器的指令。•当•个协处理器硬件不能执行属于它的协处理器指令时,将产生 未定义指令异常中断,在该异常中断处理程序中,可以通过软件模拟该硬件操作。比如, 如果系统中不包含向量浮点运算器,则可以选择浮点运算软件模拟包来支持向量浮点运 算。
    ARM协处理器可以部分地执行•…条指令,然后产生异常中断,如像除法运算除数为 0的情况。这些所有操作均由ARM协处理器决定,ARM处理器并不参与这些操作。同样 ARM协处理器指令中的协处理器的寄存器标识符以及操作类型助记符也由各种不同的实 现定义,程序员可以通过宏定义这些指令的语法格式。
    ARM协处理器指令包括以下3类;
    • 用于ARM处理器初始化ARM协处理器的数据处理操作。
    • 用T ARM处理器的寄存器和ARM协处理器的寄存器间的数据传送操作。
    • 用于在ARM协处理器的寄存器和内存整元之间传送数据。
    这些指令包括以下5条:
    • CDP协处理器数据操作指令。
    • LDC协处理器数据读取指令。
    • STC协处理器数据写入指令。
    • MCR ARM寄存器到协处理器寄存器的数据传送指令。
    • MRC 协处理器寄存器到ARM寄存器的数据传送指令。
  3. CDP (协处理器数据操作指令)
    CDP指令是ARM处理器用于通知ARM协处理器执行特定的操作。该操作由协处理 器完成。如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断。
    指令的编码格式
    31 28 M 24 ?3 20 19 JL&15 12 旦 8? 5 4 1 0
    I 1110 ooo 1 opcode」 CRn CRd opcode^ 0 CRm
    指令的语法格式
    CDP{} , , , ,
    CDP2 , , , , ,
    其中;
    vccnd>为指令执行的条件码。当<condA忽略时指令为无条件执行。 CDP2格式中,vcond,为Obllll,指令为无条件执行指令。
    <coproc>为协处理器的编码。
    〈opcode」〉为协处理器将执行的操作的操作码。
    作为目标寄存器的协处理器寄存器。
    为存放第1个操作数的协处理器寄存器.
    为存放第1个操作数的协处理器寄存器。 vopcode.2>为协处理器将执行的繰作的繰作码。
    指令操作的伪代码
    if ConditionPassed(cond) then
    Coprocessor(Gp_num]-dependent operation
    指令的使用
    本指令是ARM处理器用于通知ARM协处理器执行特定的操作。该操作中不涉及 ARM寄存器和内存单元。
    示例
    CDP p5, 2, C12, clO, c3, 4 ;协处理器p5的操作初始化。其中,
    ;操作码1为2,操作码2为4
    ;目标寄存器为C12
    ;源操作数寄存器为C10和C3
  4. LDC (协处理器数据读取指令)
    LDC指令从一系列连续的内存单元将数据读取到协处理器的寄存器中。如果协处理 器不能成功地执行该操作,将产生未定义的指令异常中断。
    指令的编码格式
    31 28 27 24 23 20 丄9 16 15 L2 11 8 / 54 3 0
    cond 1 10 PUN W 1 Rn CRd cpnum 8_bit_word_offeet |
    指令的诲法格式
    LDC(}{L} , ,
    LDC2IL} , ,
    其中:
    LDC2格式中,^Oblllh指令为无条件执行指令。
    L指示指令为长读取操作,比如用于双精度的数据传送。
    为指令的寻址方式。
    其他参数参见CDP指令°
    指令操作的伪代码
    if ConditionPassed(cond) then
    address = start_address
    load Memory [address, 4] for Coprocessor [cp_ni,]m]
    while (NotFinished(Coprocessor[cp_num]))
    address - address 4- 4
    load Memory(address,4] for Coprocessor[
    assert address == end _aridress
    指令的使用
    LDC指令从•系列连续的内存单元将数据读取到协处理器的寄存器中。
    示例
    LDC p6, CR4, [R2, #4] ; R2为ARM寄存器,指令读取内存单元(R2 + 4)的字數据,传送
    ;到协处埋器p6的CR4寄存器中
  5. STC (协处理器数据写入指令)
    STC指令将协处理器的密存器中的数据写入到•-系列连续的内存单元中。如果协处理 器不能成功地执行该操作,将产生未定义的指令异常中断。
    指令的编码格式
    契 28 27 24 23 20 19 耻 15 12” 8 7 0
    cond 1 10 P U N W 0 Rn CRd cpjwm 8 brt word offset
    指令的语法格式
    STC { } {LI , , addi:essing_mode STC2{L} , f
    其中:
    L指示指令为长写入操作,比如用于双精度的数据传送。 其他参数用法参见LDC指令和CDP指令。
    指令操作的伪代码
    if ConditionPassed(cond) then
    ‘ address = start_5ddress
    Memory[address,4] - value from Coprocessor[cp numj while (N。匕Finished(coprocessor[cp_num]})
    address = address + 4
    Nemory[address,J = value from Coprocessor[cpnum]
    assert address -= end_address
    指令的使用
    STC指令将协处理器的寄存器中的数据写入到一系列连续的内存单元中。
    示例
    STC pB, CR8, [R2, #4]! ; R2为ARM寄存器。指令将协处理器p8的CR8寄存器中的字数 ;据写入到内存单元(R2 + 4)中,指令执行后R2F2 + 4
  6. MCR(ARM寄存器到协处理鬍寄存器的数据传送指令)
    MCR指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中。如果协处 理器不能成功地执行该操作,将产生未定义的指令异常中断。
    指令的编码格式
    J1 28 27 24 23_ 21 20 19 16 15 12 11 8 7 5 < 3 0
    Rond 1110 I Opcode」]0 CRn Rd cp_num I Opcode^ 1 CRm J
    第3章 ARM指令集介绍103 g—f ・gaC8—sz^ar V ■-!•, .,. ]丄
    指令的语法格式
    MCR(} / / r , ! MCR2 , , , f (, ;
    其中;
    MCR2格式中,为OblUh指令为无条件执行指令。
    为ARM寄存器,其值将被传送到的协处理器寄存器中°
    为目标寄存器的协处理器寄存器。
    为附加的目标寄存器或者源操作数寄存器. 其他参数用法参见CDP指令。
    指令操作的伪代码
    if ConditionPassed fco^d) then
    send Rd value to Coprocessor fcp num)
    指令的使用
    MCR指令将ARM处理器的寄存器中的数据传送到协处理器的寄存器中c
    示例
    MCR pl4, 3, R7, c7, ell, 6 ;指令从ARM寄存器中将数据传送到协处理階pl4的寄存器 ;中,其中R7为ARM寄存器,存放源操作数:C7和C11为 ;协处理器寄存器,为目标寄存器:操作码1为3;株作矶2 ;为6
  7. MRC (协处理器寄存器到ARM寄存器的数据传送指令)
    MRC指令将协处理器寄存器中的数值传送到ARM处理器的奇存器中。如果协处理 器不能成功地执行该操作,将产生木定义的指令异常中断。
    指令的编码格式
    31 28 27 2^ 23 21 20 19 16 15 12 11 8 7 _ 5 4 3 0
    cond 1110 Opcode」 1 CRn Rd cpnum opcode 2 1 CRm
    指令的语法格式
    MRC{} , , , , (, ) MRC2 , , , , {, }
    其中:
    MRC2格式中,为OblllL指令为无条件执行指令。 vRd>为目标寄存器的ARM寄存器。
    为协处理器寄存器,存放第1个源操作数。
    为附加的目标寄存器或者源操作数寄存器。 其他参数用法参见CDP指令。
    指令操作的伪代码
    if ConditionPassed(cond) then
    datA = value from Coprocessor[cpnumj
    if Rd is R15 then
    N flag - data[31;
    Z flag = data[30]
    C flag = data[29]
    V flag = data [28]
    else /
    Rd is not R15 _/
    Rd = data
    指令的使用
    MRC指令将协处理器的寄存器中数值传送到ARM处理器的寄存器中。
    示例
    MRC pl5,2,R5,E,c2,4 ;指令将协处理器pl5寄存器中的数据传送到ARM寄存器中。J(-
    ;中,R5为ARM寄存器,是目标寄存器;C0和C2为协处理器奇 ;存器,存放源操作数;操作码1为2;操作码2为4
    3.2 一些基本的ARM指令功能段
    本节介绍~些基本的ARM指令代码段。通过对这些代码段的分析,进-步理解相犬 的ARM指令的用法,逐步学习如何使用ARM指令编写高效率的程序。本节主要包括以 下几部分的内容:
    • 算术逻辑运算指令的应用。
    • 跳转指令的应用。
    • Load/Store指令的应用°
    • 批量Load/Store指令的应用,
    • 信号量指令的应用。
    • 与系统相关的一些指令的应用。
    3.2.1算术逻辑运算指令的应用
  8. 彳立操作指令应用举例
    下面的代码将R2中的高8位数据传送到R3的低8位中。
    MOV RO, R2, LSR #24 ;将R2的高8位数据传送到R0中,R0的高24位设置成。
    ORR R3, RO, R3, LSL #8 ;将R3中数据逻辑左移8位,这时R3的低8位为。
    ;ORR操作将M (高24位为D)中低8位数据传送到得存器R3中
  9. 实现乘法的指令段举例
    MOV RO, R0「 LSL #n ;RO =RO VV n ; R0=R0(2n)
    ADD RO, RO, RO, LSL #n ;RO =RO+RO_(2
    n)=R0(2n+l)
    RSB RO, RO, RO, LSL #n ;RO =RO
    (2
    n)-RO=RO**(2_n・l)
    ADD RO, RO, RO, LSL #2 ;RO =RO+RO
    (22)= RO 5
    ADD RO, RL RO, LSL #1 ;RO =R1 + RO _ (2_F
  10. 64位数擔运算举例
    假设R0和R)存放了 64位数据.RO中存放数据的低32位;R2和R3中存放了 另 个64位数据,R2中存放低32位数据。卩面的指令实现了灼个64位数据的加汶还 算,結果仍然保存在R0和R1屮。
    ADDS RO, RO, R2 ;低32位fij加.同时设置CPSR中的C标志位
    ADC Rl, Rl, R3 ;高32位的带位相加
    下面的指令实现了两个64位数据的减法运算,结果仍然保存在R0和R1中。
    SUBS RO, RO, R2 ;低32位祖加,同时设優CPSR中的。标忘位
    SBC Rl, Rl, R3 ;尚’32位的帯位相减
    下面的指令实现了两个64位数据的比较操作.治E确设置CPSR巾的N、Z及C条 件标志位,而V标志位的役置时能有错误..
    CMP Rl, R3 ;比较高32位
    CMPEQ RO, R2 ;如果高32仞相等.比较低32位
  11. 转换内存中数据存储方式的指令段
    数据在内存中有两种存储方式:一种是字数据中的高位数据存放在高地址处,低位数 据存放在低地址处,如果数据的bits[7:0]存放在地址A处,则数据的bits[]5:8]存放在地址 A+1处,则数据的bits[23:16]存放在地址A+2处,则数据的bits[31:24]存放在地址A+3 处,这种存储方式称为little endian方式;另种是字中高位数据存放在低地址处,低位 数帝存放在高地址处.如果数据的bits[7:0]存放在地址A+3处,则数据的bits卩5:8]存放在 地址A+2处,则数据的bits【23:16]存放在地址A+1处,则数据的bits[31:24]存放在地址A 处,这种存储方式称为bigendian方式。下面的代码段可以实现两种存储方式的转换。
    下面的代码段将寄存器R0中的数据存储方式转换成另外…种存储方式,指令执行前 RO中数据存储方式为:R0 = A,B,C,D;指令执行后R0中数据存储方式如 R0 = D, C,B , A。
    EOR Rl, RO, RO, ROR #16 ;R1 =At 顷 D,LA 顷 B
    BIC RL Rl, #DxFFOOOO ;R1 =AAC, 0 ,CAA,D”B
    MOV RO, RO, ROR #8 ;RO = D/ A, B < C
    EOR RO, RCJ, Rl, LSR #8 ;RO u D』C , B , A

下面的代码段用于转换大量的字数据的存储方式。指令执行前R0存放需要转换的数 据,其存储方式为RO = A , B , C , D;指令执行后R0中存放转换后的数据,其存储方式 为 R0 = D,C,B,A。
MOV R2, #OxFF ; R2 = OxFF
ORR R2, R2, tOxFFOOOO ; R2 = OxOOFFOOFF
重复下面的指令段,实现数据存放方式的转换
AND Rl, R2, RO ; R1 - 0 B 0 D
AND RO, R2, RO, ROR #24 ; R。 = 0 C 0 A
ORR HO, RO, Rl, ROR #8 ; RO = D C B A 
3.2.2跳转指令的应用
本节介绍在ARM中如何实现程序流程的改变。
1・于程序调用
BL指令在执行跳转操作的同时保存当前PC寄存器值,用于从被调用的子程序中返 回。下面的代码段说明了子程序的调用和返回方法。
;调用于程function
;子程序结束后,程序将返旧到这里执行

  1. 条件执行
    下面介绍如何实现类似于C语言中的iMhen-else功能的ARM代码段。程序功能为求 最大公约数。相应的C语言代码如下:
    int gcd(int a, int b) J while (a 1= b)
    i f (a > b )
    a = a - b ;
    else b = return a ;
    }
    对应的ARM代码段如下,代码执行前R0中存放a,R1中存放A代码执行后R0中 存放&和b的最大公约数。
    比较a和b大小
    if (a>b) a=a-lJ (if a-=b do nothing)
    if (b>a) b=b-a {if a==b do nothing) if (aJ=b) then跳转到gcd处继续执行 于程序执行结束,返回
  2. 条件判断语句
    下面介绍如何实现类似于c语言中条件判断语句功能的ARM代码段。相应的C语言 代码如下:
    对应的ARM代码段如下。代码执行前R0中存放a, R1中存放b。代码执行后R2中 存放d和e的和。 
    ;判断R。是否等于0
    ;如果R0不等丁 0,判断R1是否等丁 1
    ;ROO 或 Rl = l 时 R2=R3+R4 
    2.简单的串比较
    下面的代码段实现比较两个串的大小。代码执行前,R0指向笫1个串,R1指向第2 个串。代码执行后R0中保存比较结果,如果两个串相同,R0为0;如果第1个串大「第 2 个串,R0>0:
    3.长桃转
    通过直接向PC寄存器中读取字数据,程序可以实现在4 GB的地址空间的任意跳 转,这种跳特叫做长跳转。在下面的代码段中,程序将跳转到于程序function处开始执 行。自程序执行完成后,
  3. 多路跳转
    下面的代码段通过函数地址表实现多路转移。其中,maxindex为跳转的最大索引 号,R0中为跳转的索引号。
    ;判断索引号是否超出了最大索引号
    ,;如果没有超过,跳转到相应的程序处
    ;如果超过,跳转到错误处理程序处
    ;子程序1的地址
    ;子程序1的地址
    ;了程序1散地址
    324 批量Load/Store指令的应用
    1.简单的块复制
    下面的代码段实现简单的数据块复制。程序一•次将48个字数据从R12作为首地址的 一段连续的内存单元复制到R13作为首地址的一段连续的内存单元。代码执行前R12为
    源数据区首地址,R13为冃标数据区首地址,R14为源数据区末地址。
    ;从源数据区读取48个字
    ;将48个宁•保存到目标数据区
    ;是否到达源数据结尾
    ;如果没有到込源数据结尾
    2.子程序进入和退出时数据的保存和恢复
    在调用子程序时,通常利用寄存器R。〜R3传递参数和返回结果,这几个参数由子程 序的调用者来保存,其他的子程序将要用到的寄存器在于程序入口处保存,在子程序返回 前恢复这些寄存器,下面的代码段是这个过程的示例。
    STMFDR13!, {R4 - R12, R14} ;保存所有的本地寄存器、返回地址并•更新栈指针
    Insert the functiori body here
    LD14FD RI3!, t R4 - R12, PC} ;恢复本地寄存器、PC寄存器,并更新栈指针
    3.2.5信号量指令的应用
    信号堆用于实现对临界区数据访问的同步。下面的代码说明了在ARM中如何实现这 ••过程。代码中用进程标识符来表示各信号量的所有者,代码执行前进程的标识符保存/ R1中,信号量的地址保存在R0中。当信号最值为0时,表示与该信号量相关的临界区可 用;当信号量值为-1时,表不当前有进程止在査看该信号量的值。如果当前进程査看的 信号单正忙,当前进程将一直等待该信号量。为了避免当前进程的查询操作阻塞操作系统 的进程调度,可以在下一次査询之前调用操作系统中系统调用,使当前进程休眠一段时 间。
    ;将信号置值读取到R3中,同时将其值设宜成-1
    ;判断读取到的信号扯值是否为・1,即是否有其他进程上在访问该信号量
    ;%果有其他进程正在访问该信号最,则使当前进程休眠-•段时间,以保证操作系统能够进行任务 ;调度
    ;如果有其他进程iE在访问该信号暈,跳转到spinin处执行,
    ;判断当前信号昱是否可用,即内存单元R0中值是否为0,当不为0
    ;时表小其他的讲程正拥有该信号置
    STRNE R3, [RO] ;这时恢复该信号童的值,即该信号量拥有者的进程标识符
    「上果该信号觉正被别的进程占用’则使当茵进程休眠一段时间,以保证櫟作系统能够进行任务调度
    ;进程重新会试获取该信号置
    ;当前进程得到该信号量,将自己的进程标识符写入到内存单元R0处
    ;这里是该信号皇所保护的临界区数据 
    spinout
    SWP F3, R2,【R0];将信号蚩值读取到R3中,同时将其偵设置成T
    CMN R3, #1 ;判断读取至!的信号貴值是否炉1,即是由有其他进程正在访问该倍号虽
    ;如果有其他进程正在访问该信号量.则使当前进程休眠一段时间,以保讪操作系统能够进行任务 ;调度
    spiiQul ;如果有其他进程正在访问该倍号量.跳捋到spinin处执行.
    R3, R1 ;判断是否当前进程拥有该信号置
    CorruptSemaphore ;如果不是则系统出现错误
    R2, #0 ;如果系统正常,重新将该信号覺设置为可用,即0
    R2, [R0] ;
  4. SWI申断处理程序示例
    SW1指令使处理器切换到特权模式,在特权模式下请求特定的系统服务(这些系统服 务通常由操作系统提供)。当SW[指令执行时通常完成下面的工作。
    R14_Svc = SWI指令的下面-•条指令的地址(叩SWI中断处理程序的返回地址)
    SPSR svc = CPSR ;保存当前 CPSR
    CPSRH : 0] - OMOOH ;使处理器切换到特权模式
    CPSRC5] = 0 ;使程序进入ARM状态
    CPSRf?] = 1 ;禁止正常中断响应
    if high vectors configured then ;程序跳转到相应的中断向最处
    £C = OxFFFFOOOS
    else
    PC = 0x00000008
    下面的代码段是SW1中断处理程序的基木框架。SWI中断向量存放在内存単元 0x00000008处。通常在该地址处放一条跳转指令,其目标地址为下面代码段的首地址。 SWI指令中包含24位的立即数,用于指定指令请求的具体SWI的服务。对于Thumb指 令而言,指令中包含8位立即数来指定指令请求的具体SWI服务。
    SWI中断处理过程如下面所介绍的。当程序执行到SW1指令时,程序跳转到 0x00000008处执行,由于该处是一条跳转指令,程序接者跳转到下面介绍的代码段的首 指令处开始执行。在下面的代码段中程序保存相关的寄存器,接着提取SWJ指令中的立 即数,以确定SWJ指令请求的具体服务。对于ARM状态和Thumb状态分别得到24位和 8位立即数。根据得到的立即数程序跳转到相应的代码处执行。
    在下面的代码段中,仅仅保存了寄存器R0〜R3、R12和LR(R14)。如果实际代码还 用到了其他的寄存器,可以修改代码中的保存和恢复指令中的寄存器列表;也可以在各个 具体服务程序中保存各自用到的寄存器。
    SWIHandler
    STMFD sp!, Jr0-r3, rl2,;保存相关的寄存器
    MRS rO, spsr ;将SPSR内容传送到R。中
    TST r0, #0x20 ;判断程序状态是否为ARM状态
    LDRNEH r0, [lr, #-2] ;如果是Thumb状态,提取SWI指令中相应的BICNE匚0, 
    ;8位宅即数
    ;如果是ARM状态,提取SWI指令中相应的
    ;24位立即数
    ;判断指令请求的服务的序矽是否超过合法范围
    ;如果没有超出合法范围,跳转到相应的服务程序执行
    ;如果超出了合法范围,跳转到错误处理程序
    ;下面是各月艮务程序的函数地址表
    ;该服务对应的SWI指令中立即数为0
    ;服务程序do_swi_l的首地址,该服务对应的SWI指令中
    ;立即数为1

Insert sde to handle SWI Q hece
LDMFD sp!, (rO-r3,rl2fpc}A ;从服务程序 do_swi_0 返回 do_swi_l ;服务程序do_swi_l的代码
2. IRQ中断处理程序示例
在ARM中,外部中断管理器或外设通过使能ARM处理器中的IRQ输入骨脚产生 IRQ异常中断。CPSR寄存器中的1控制位设置为】时禁止ARM处理器响应IRQ中断请 求,CPSR寄存器中的I控制位设置为0时ARM处理器在指令边界处检查是否有IRQ中 断请求。
ARM处理器响应IRQ中断清求时,完成以下工作。
保存当前PC值
保存CPSR
将处理器模式切换到IRQ模式
进入ARM状态
禁止常规中断
跳转到IRQ异常中断的中断向最
下面的代码段是IRQ中断处理程序的基本框架。通常,IRQ中断向量存放在内存单 元0x00000018处。通常在该地址处放-,条跳转指令,其目标地址为下面代码段的首地 址。外围中断管理硬件将所有的IRQ异常中断请求按优先级排队,并把优先级最高的 [RQ异常中断的相关信息保存到寄存器中。IRQ中断处理程序读取这些信息,并跳转的相 应的代码处执行。
;保存工作寄存器,返冋地址和当前程序现场
SUB ri4, rl4, #4 ;调整RL4值・使其指向发牛IRQ中断的指令的下一条指令
STMFD rl3I, {匸12, ”4} ;保存返回地址和相关的寄存器,”3为这里所用的栈的栈 
;指针
MRS r12r SPSR :保存SPSR
STMFD rl3 J, (rl2) ;读取当布优先级最高的IRQ请求的相关信息
MOV 口2, tflntBase ;读取中断控制器的基地址
LDR rl2, [rl2, #IntLevelJ ;读取优先级录髙的IRQ的中断-■} (level) IntLevel为存
;放优先级最髙的IRQ的中断号的寄存器的偏移地址修改
;CPSR中控制位,重新允许IRQ中断
MRS rl4f CPSR ;读取CPSR
BIC rl4f #0x80 ;淸除中断禁止位
MSR CPSR c, rl4 ;将R14值写入CPSR
;跳转到当前IRQ对应的中断处理程序
LDR PC, 【PC, rl2, LSL #2] ;跳转到当前IRQ对应的中断处理程序;NOP
;插入本指令以保证上面跳转的正确
;中断处理程序地址表
DCD PriorityOHandler ;PriorityOHandler
DCD PrioritylHandler ;PrioritylHandler 的地址
PriorityOHandler
STMFD r!3!, {E ・ rll}
;PriorityOHandy 程序体
;保存匸作寄存器组

;这里为中断处理程序主体
;修改CPSR相关位,禁止响应中断
;注意这里不要使用R14,否则发生了中断,R14内容会被 -破坏
;恢复工作寄存器和SPSR
;恢复所有寄存器,并返回
:PriorityOHandler 程序体
3. 进程切换
进程是操作系统中任务调度的基本单位。每个进程由••个进程控制块PCB来表示, 进程控制块PCB中包含了进程相关的一些信息。进程间切换就是通过某种方式保存当前 进程的PCB,恢复新进程的PCB内容到处理器中。这里介绍的仅仅是■个简単的演示性 的例子,通过以下约定使这个例子简单并且清晰一•些。
这里讨论用户模式的进程间切换。切换过程是通过IRQ中断处理程序完成的。比如 在进程1执行到特定时机时,希望切换到进程2。这时系统产生IRQ中断,首先执行常规 的中断处理糅作,然后判断是返回到被中断的进程1,还是切换到新的进程2执行。这里 仅仅讨论用户模式的进程间切换。如果在特权模式下发生了 IRQ中断,中断处理程序. 定返回到被中断的进程。
这里假设IRQ中断处理程序仅仅保存寄存器R0〜R3、R12及R14;使用R13作为栈 指针;栈的类型为FD(Full Descending);其他寄存器保持不变。在中断处理程序中始终禁 止中断,也不进行处理器模式切换。
这里假设进程控制块格式为从低地址到髙地址成次为下列寄存器:CPSR、返回地
址、RO〜R】4。
下面分3部分介绍进程间切换的过程c
在进入IRQ中断处理程序时,首先计算返I可地址,并保存相关的寄存器°
SUB R14, RW, #4 ;使24指向发生IRQ中断的指令的卜榆•条指今
STMFD R13!, {R0-R3, R12, R14};保存 R0-H3, R12, R14
如果IRQ中断处理程序返回到被中断的迸程,则执行rm指令。该指令从数据找 中恢复寄存器R0〜R3及R12的值,将返回地址传送到PC中,并将SPSRJrq值复制到 CPSR 中 0
LDMFD R13!, {R0-R3, R12, PC 1A
如果IRQ切换到新的进程,则要保存被中断的进程的PCB,然后恢复新进程的PCB 到处理器中。
;保存被中断的进程的2CB,该PCB存放在R0所指向
;的连续的内存单元中
;读取被屮断的进程的CPSR
;将其保存到R0指向的内存单元,芥更新R0值
;读取被中断进程的R0和R2
;将札保洋到R0指向的内存单元.并更新R。值 R14};读取栈中其他数据
;将返何地址值R14保存彳MCB中第2个字単兀.即
;CPSR之后
;保存其他所有的存存器
;恢0RO〜R14
;因为在用广模式的LDM指令后不能立即探作备
;价寄存器,故插入本指令
;切擬到新进程执行,同时恢复CPSR
3.3 Thumb指令介绍
在ARM体系结构中,ARM指令集中的指令是32位指令,其执行效率很髙。对于存 储系统数据总线为16位的应用系统,ARM体系提供了 Thumb指令集。Thumb指令.集是 对ARM指令集的•个子集进行重新编码而得到的,其指令长度为16位.在ARM体系的 T变种(T Variant)的版本中,同时支持ARM指令集和Thumb指令集,而3.遵守一定的调 用规则时,Thumb子程序和ARM子程序可以相互调用。
通常在处理器执行ARM程序时,称处理器处于ARM状态:在处理器执行Thumb程 序时,称处理器处于Thumb状态。注意处理器状态和处理器模式指的是不同的概念。
Thumb指令集并没有改变ARM体系底层的程序设计模型,只是在该模型E增加了… 些限制条件。Thumb指令集中的数据处理指令的操作数仍然M 32位,指令丁址地址也是
114 ARM体系结构与编程
32位的。
处理器执行Thumb指令时,可以使用的整数寄存器通為为R0〜R7,有些指令还使用 到了程序计数器寄存器PC(R15)、程序返回寄存器LR(R14)以及栈指针寄存器SP(R13)。 在Thumb状态下,读取R15寄存器时,位[0]值为0,位[31 : 1]包含了程序计数器的值; 在向R1S寄存器写入数据时时,位[0]被忽略,位[31 : 1]被设置称当前程序计数器的值。
Thumb指令集没有提供访问CPSR/SPSR寄存器的指令。处理器根据CPSR寄存器中 的T位来确定指令类型:
• 当T位为0时,指令为ARM指令。
• 当T位为1时,指令为Thumb指令。
关于ARM状态和Thumb状态的切换以及ARM程序与Thumb程序的相互调用的方 法将在第7章中详细介绍。
在本书中没有详细介绍Thumb指令集。这并不是因为Thumb指令集不重要,而是因 为从功能上来讲它是ARM指令集的子集,在了解ARM指令集的基础上很容易理解 Thumb指令。对于各指令仅介绍其编码格式、语法格式、执行的操作以及应用方法。
第4章ARM汇编语言程序设计
本章介绍如何编写ARM 和Thumb汇编语言程序。同时介绍ARM 汇编编译器 armasm的使用方法。
4.1伪操作
ARM汇编语言源程序中语句由指令、伪操作和宏指令组成。在ARM中伪操作称为 detective,这里为保持和国内在IBM PC汇编语言中对名词翻译的-致性defective称为伪 操作;同样在ARM中宏指令被称为pseudo-instruction,这里将其称为宏指令,宏指令也 是通过伪操作定义的。本节介绍伪操作和宏指令。伪操作不像机器指令那样在计算机运行 期间由机器执行,它是在汇编程序对源程序汇编期间由汇编程序处理的。宏是一段独立的 程序代码。在程序中通过宏指令调用该宏。当程序被汇编时,汇编程序将对每个宏调用作 展开,用宏定义体取代源程序中的宏指令°本节介绍以下类型的ARM伪操作和宏指令.
• 符号定义(Symbol definition)伪操作。
• 数据定义(Data definition)伪操作。
• 汇编控制(Assembly control)伪操作。
• 框架描述(Frame description)伪操作。
• 信息报告(Reporting)伪操作。
•其他(Miscellaneous)伪操作。
4.1.1符号定义伪操作
符号定义(Symbol definition)伪操作用于定义ARM汇编程序中的变豈’对变量进行赋 值以及定义寄存器名称。包括以下伪操作。
• GBLA, GBLL及GBLS声明全局变量。
• LCLA, LCLL及LCLS声明局部变量。
・SETA, SETL及SETS 给变量赋值。
• RLIST为通用寄存器列表定义名称。
• CN为协处理器的寄存器定义名称。
• CP为协处理器定义名称。
• DN及SN为VFP的寄存器定义名称.
. FN 为FPA的浮点寄存器定义名称。

  1. GBLA. GBLL 及 GBLS
    GBLA, GBLL及GBLS伪操作用于声明-个ARM程序中的全局变量,并将其初始 化。
    GBLA伪操作声明一个全局的算术变量,并将其初始化成0。