第四章 ARM 指令集

130
第第第 ARM 第第第 ARM 第第第第第 ARM 第第第第 ARM 第第第第第第 第第第第 ARM 第第第第第

description

第四章 ARM 指令集. ARM 指令集概述 ARM 寻址方式 ARM 指令详细介绍 一些基本的 ARM 指令功能段. (一) ARM 指令集概述 1.1 ARM 指令分类 ARM 指令集总体分为 6 类指令 数据处理指令 :完成寄存器中数据的算术和逻辑运算操作。 程序状态寄存器处理指令 : mrs 和 msr 。 跳转指令 : b 和 bl 。 Load/Store 指令 :唯一用于寄存器和存储器之间进行数据传送的指令。 异常中断产生指令 : swi 和 bkpt 。 协处理器指令 。. 1.2 ARM 指令的特点: 所有指令都是 32bit 。 - PowerPoint PPT Presentation

Transcript of 第四章 ARM 指令集

Page 1: 第四章   ARM 指令集

第四章 ARM 指令集 ARM 指令集概述 ARM 寻址方式 ARM 指令详细介绍 一些基本的 ARM 指令功能段

Page 2: 第四章   ARM 指令集

(一) ARM 指令集概述 1.1 ARM 指令分类ARM 指令集总体分为 6 类指令

数据处理指令:完成寄存器中数据的算术和逻辑运算操作。

程序状态寄存器处理指令: mrs 和 msr 。 跳转指令: b 和 bl 。 Load/Store 指令:唯一用于寄存器和存储器之间

进行数据传送的指令。 异常中断产生指令: swi 和 bkpt 。 协处理器指令。

Page 3: 第四章   ARM 指令集

1.2 ARM 指令的特点: 所有指令都是 32bit 。 大多数指令都在单周期内完成。 所有指令都可以条件执行。 load/store 体系结构。 指令集可以通过协处理器扩展

Page 4: 第四章   ARM 指令集

1.3 ARM 指令的格式 一条典型的 ARM 指令编码格式为:

Cond 001 Opcode S Rn Rd Operand2

0111215161920212425272831 78

一条典型的 ARM 指令语法格式为:<Opcode>{<cond>}{s} <Rd>, <Rn>{, <Operand2>} Opcode :指令操作码。 cond :指令的条件码。 S :决定指令的操作是否影响 cpsr 的值。 Rd :目标寄存器编码。 Rn :包含第一个操作数的寄存器编码。 Operand2 :第 2 操作数。 例: ADDS R2 , R1 , #1

SUBNES R2 , R1 , #0x20

LDR R0 , [R1]

Page 5: 第四章   ARM 指令集

1.4 条件执行每条 ARM 指令包含 4 位条件码域 < cond >, 它占用指令编码的最高四位 [31 : 28] 。条件编码共 24 = 16 种,其中, 15 种用于指令的条件码。每种条件码用 2 个英文缩写字符表示。(见 P.101 表 3-1 )ARM 处理器根据指令的执行条件是否满足,决定当前指令是否执行。只有在 cpsr 中的条件标志位满足指定的条件时,指令才会被执行。不符合条件的代码依然占用一个时钟周期(相当于一个 NOP 指令)。书写时,条件码的位置在指令助记符的后面(因此也称为条件后缀。),例如: MOVEQ R0, R1;

指令条件后缀如下表所示:(见 P.101 表 3-1 )

Page 6: 第四章   ARM 指令集

NV 无 从不(未使用)

Page 7: 第四章   ARM 指令集

默认情况下,数据处理指令不影响条件码标志位,但可以选择通过添加“ S” 来影响标志位。 CMP 不需要增加 “ S” 就可改变相应的标志位。

loop … SUBS r1,r1,#1 BNE loop 如果 Z 标志清零则跳转

R1 减 1 ,并设置标志位

Page 8: 第四章   ARM 指令集

(二) ARM 寻址方式 寻址方式:

根据指令编码中给出的地址码字段来寻找真实操作数的方式。

立即寻址寄存器寻址寄存器间接寻址基址加偏址寻址 堆栈寻址 块拷贝寻址 相对寻址

Page 9: 第四章   ARM 指令集

2.1 立即寻址 立即寻址 —— 操作数本身在指令中直接给出(立即

数由指令的后 12 位给定),这个操作数被称为立即数,对应的寻址方式也就叫做立即寻址。

例如以下指令: ADD R0 , R0 ,# 1 ; R0←R0 + 1 MOV R0 ,# 0x3f ; R0← # 0x3f 书写立即数时,要求以“#”为前缀。 十六进制数,#后加 0x 或 &, 如 #0x3f,#&3f. 二进制数,#后加 0b, 如 #0b1011 十进制数, # 后加 0d 或缺省,如 #0d678,#789 如何构造 32 位立即数?

Page 10: 第四章   ARM 指令集

数据处理指令格式中,第二个操作数有 12 位

因此有效立即数 immediate 可以表示成:

<immediate>=immed_8 循环右移( 2×rot )

4 bit 移位值 (0-15)乘于 2 ,得到一个范围在 0-30 ,步长为 2 的移位值。

记住一条准则: “最后 8 位一定要移动偶数位”。

0711 8

immed_8

ShifterROR

rot

x2

Page 11: 第四章   ARM 指令集

031ror #0

ror #8

ror #30

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

7

例:

下列命令中,汇编器把立即数转换为移位操作:

MOV r0,#4096 ; uses 0x40 ror 26 ADD r1,r2,#0xFF0000 ; uses 0xFF ror 16

带有立即数的 MOV 指令的二进制编码为:MOV R0 , 0xF200 ; E3A00CF2

MOV R1 , 0x110000 ; E3A01811

MOV R4 , 0x12800 ; E3A04B4A

0xF200 =0xF2 循环右移( 2*C )0x110000 =0x11 循环右移( 2*8 )0x12800 =0x4A 循环右移( 2*B )

Page 12: 第四章   ARM 指令集

只有能够通过此构造方法得到的才是合法的立即数。 合法立即数:

0xFF ; 0x104 ; 0xFF0 ; 0xFF00

非法立即数: 0x101 ; 0x102 ; 0xFF1

一个合法的立即数可能有多种编码方法,将使某些指令的执行产生不同的结果。

0x3F0 immed_8=0x3F , rot=0xE

immed_8=0xFC , rot=0xF

ARM汇编编译器生成立即数的规则为:当立即数数值在 0到 0xFF范围时,令 immed_8=<immediate> , rot=0 。其它情况下,汇编编译器选择使 rot 数值最小的编码方式。

Page 13: 第四章   ARM 指令集

2.2 寄存器寻址

寄存器寻址:

—— 利用寄存器中的数值作为操作数。这种寻址方式是各类微处理器经常采用的一种

方式,也是一种执行效率较高的寻址方式。

如指令:

ADD R0 , R1 , R2 ; R0←R1 + R2

Page 14: 第四章   ARM 指令集

寄存器移位寻址 —— 当第二操作数为寄存器型时,在执行寄存器寻址操作时,可以选择是否对第二操作数进行移位,即第二操作数形如:

MOV Rd, Rn, Rm , {<shift>}其中: Rm 称为第二操作数寄存器<shift> 用来指定移位类型和移位位数。移位 位数可以用 5 位立即数 <#shift> 或寄存 器 (Rs)方式。

Page 15: 第四章   ARM 指令集

在指令执行时将寄存器移位后的内容作为第二操作数参与运算。例如指令:

ADD R3 , R2 , R1 , LSR #2 ; R3←R2+(R1右移2 位 )

ADD R3 , R2 , R1 , LSR R0 ; R3←R2+(R1右移 R0 位 )

Page 16: 第四章   ARM 指令集

第二操作数移位方式 LSL :逻辑左移,空出的最低有效位用 0 填充。

LSR :逻辑右移,空出的最高有效位用 0 填充。

0

31 0

0

31 0

Page 17: 第四章   ARM 指令集

ASL :算术左移,由于左移空出的有效位用 0填充,因此 它与 LSL同义。

ASR :算术右移 (Arithmetic Shift Right) 。算术移位的对象是带符号数,移位过程中必须保持操作数的符号不变。如果源操作数是正数,空出的最高有效位用 0 填充,如果是负数用 1填充。

30 0

Page 18: 第四章   ARM 指令集

ROR :循环右移 (Rotate Right) ,移出的字的最低有效位依次填入空出的最高有效位。

31 0

RRX :带扩展的循环右移 (Rotate Right Extended) 。将寄存器的内容循环右移 1 位,空位用原来 C 标志位填充。 31 0

C

Page 19: 第四章   ARM 指令集

第二操作数的移位位数 移位位数可以用立即数方式或者寄存器方式给出 ,

如下所示:

ADD R3 , R2 , R1 , LSR #2 ; R3R2+(R1右移 2位 )

ADD R3 , R2 , R1 , LSR R4 ; R3R2+(R1右移 R4 位 )

寄存器 R1 的内容分别逻辑右移 2 位、 R4 位 ,再与寄

存器 R2 的内容相加,结果放入 R3 中。

Page 20: 第四章   ARM 指令集

2.3 寄存器间接寻址寄存器间接寻址

—— 就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储单元中。例如以下指令:

LDR R0 , [R1] ;R0←[R1] STR R0 , [R1] ;[R1]←R0

第一条指令将以 R1 的值为地址的存储单元中的内容加载到寄存器 R0 中。

第二条指令将 R0 的内容存储到以 R1 的值为地址的存储单元中。 R1—— 基址寄存器 R1 的内容——基地址

Page 21: 第四章   ARM 指令集

2.4 基址加偏址寻址(变址寻址) 基址加偏址寻址 ——将基址寄存器的内容与指令中给出的地址偏移量相加,得到操作数所在的存储器的有效地址。

变址寻址方式常用于访问某基地址附近的地址单元。( 4K )

例如:LDR R0 , [R1 ,# 4] ; R0←mem32[R1

+ 4]

Page 22: 第四章   ARM 指令集

有三种加偏址的方式: 前变址模式 (不修改基址寄存器 ): ——先基址 + 偏址,生成操作数地址,做指令指定的操作。

0x5

r1

0x200基址

寄存器 0x200

r0

0x5源寄存器for STR

偏移量12 0x20c

Pre-indexed: STR r0,[r1,#12]

Page 23: 第四章   ARM 指令集

自动变址模式 ( 修改基址寄存器 ): ——①先基址 + 偏移,生成操作数地址,做指令指定的操作。②然后自动修改基址寄存器。

例如: LDR R0 , [R1 ,# 4] ! ; R0←mem32 [R

1 + 4] ; R1←R1 + 4

! ——表示更新基址寄存器。

Page 24: 第四章   ARM 指令集

后变址模式 (修改基址寄存器 ) : ——①基址寄存器不加偏移作为操作数地址。 ②完成指令操作后,用 ( 基址 +偏移 ) 的值修改基址寄存器。

0x5r1

0x200

原基址寄存器 0x200

r0

0x5源寄存器for STR

偏移量12 0x20c

r1

0x20c更新

基址寄存器

Post-indexed: STR r0,[r1],#12

Page 25: 第四章   ARM 指令集

偏移地址 —— 可以是一个立即数,也可以是另一个

寄存器,并且在加到基址寄存器前还可以经过移位操作,如下所示:

LDR r0 , [r1 , r2] ; r0<—mem32[r1+r2]

LDR r0 , [r1 , r2, LSL #2] ; r0<—mem32[r1+r2*4]

常用的是立即数偏移的形式。

Page 26: 第四章   ARM 指令集

2.5 堆栈寻址堆栈寻址 ——堆栈寻址是隐含的,它使用一个专门的寄存器 ( 堆栈指针 SP)指向一块存储区域 ( 堆栈 )。

堆栈可分为两种增长方式:◆ 向上生长:向高地址方向生长,称为递增堆栈。

◆ 向下生长:向低地址方向生长,称为递减堆栈。

Page 27: 第四章   ARM 指令集

根据堆栈指针指向的数据位置的不同,可分为: 满堆栈 ——堆栈指针指向最后压入堆栈的有效数据项,

称为满堆栈; 空堆栈 ——堆栈指针指向下一个待压入数据的空位

置,称为空堆栈。

这样就有 4 种类型的堆栈表示递增和递减的满和空堆栈的各种组合。

Page 28: 第四章   ARM 指令集

四种类型的堆栈工作方式 满递增堆栈 FA : —— 堆栈指针指向最后压入的数据,且由低

地址向高地址生长。 满递减堆栈 FD : ——堆栈指针指向最后压入的数据,且由高

地址向低地址生长。 空递增堆栈 EA : ——堆栈指针指向下一个将要放入数据的空

位置,且由低地址向高地址生长。 空递减堆栈 ED : ——堆栈指针指向下一个将要放入数据的空

位置,且由高地址向低地址生长。

Page 29: 第四章   ARM 指令集

LDMFA sp!,{r4-r7,pc}

满递增

SP 100FF

1234AOBE80341010123484209753

r4 1r5 14544r6 0r7 12

lr 9048pc 9020

r4 100100FF r5 FF

1234 r6 1234A0BE r7 A0BE8034

pc 8034

r4 100r5 FFr6 1234r7 A0BE

lr 8034

ABCD8765102E16FFFF1010123484209753

高地址

SP SP

100FF

1234A0BE8034

SP

Old SP

100FF

1234A0BE8034

STMFD sp!,{r4-r7,lr}

满递减

Page 30: 第四章   ARM 指令集

2.6 块拷贝寻址 块拷贝寻址 —— 把存储器中的一个数据块加载到多

个寄存器中,也可以把多个寄存器中的内容保存到存储器中。是多寄存器传送指令 LDM/STM 的寻址方式。

寻址操作中的寄存器可以是 R0-R15这16 个寄存器的子集或是所有寄存器。

Page 31: 第四章   ARM 指令集

4 中寻址操作 : LDMIA / STMIA Increment After (先传送,后地址加 4 ) LDMIB / STMIB Increment Before (先地址加 4 ,后传送) LDMDA / STMDA Decrement After (先传送,后地址减 4 ) LDMDB / STMDB Decrement Before (先地址减 4 ,后传送)

IA

r1 地址

增加

r4

r0

r1

r4

r0

r1

r4

r0 r1

r4

r0

r10

IB DA DB

STMxx r10, {r0,r1,r4}

基址寄存器 (Rb)

Page 32: 第四章   ARM 指令集

多寄存器多寄存器loadload和和storestore指令的堆栈和块拷贝对照指令的堆栈和块拷贝对照

递增 递减

满 空 满 空

增值

先增 STMI BSTMFA

LDMI BLDMED

后增 STMI ASTMEA

LDMI ALDMFD

减值

先减 LDMDBLDMEA

STMDBSTMFD

后减 LDMDALDMFA

STMDASTMED

Page 33: 第四章   ARM 指令集

2.7 相对寻址 相对寻址 —— 与基址变址寻址方式相类似,相对寻址

以程序计数器 PC 的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。

相对寻址指令举例如下: BL SUBRl ;调用到SUBRl 子程序 . . . SUBR1… MOV PC, LR ;返回

Page 34: 第四章   ARM 指令集

(三) ARM 指令详细介绍

数据处理指令; Load/Store 指令; 程序状态寄存器处理指令; 跳转指令; 异常中断产生指令; 协处理器指令。

Page 35: 第四章   ARM 指令集

3.1 数据处理指令 ARM 的数据处理指令主要完成寄存器中数据的算术

和逻辑运算操作。 ARM 数据处理指令的特点:

所有的操作数要么来自寄存器,要么来自立即数,不会来自存储器。

如果有结果,则结果一定是为 32 位宽,并且放在一个寄存器中,不会写入存储器。(有一个例外:长乘法指令产生 64 位结果)

每一个操作数寄存器和结果寄存器都在指令中独立指出,即: ARM 指令采用 3 地址模式:

<Operation> Rd, Rn, Rm

Page 36: 第四章   ARM 指令集

ARM 数据处理指令大致可分为 6 类: 算术运算指令: ADD ADC SUB SBC RSB RSC

逻辑运算指令: AND ORR EOR BIC 数据传送指令: MOV MVN 比较指令: CMP CMN 测试指令: TST TEQ 乘法指令: MUL MLA UMULL UMLAL SMULL SMLAL

上述指令只能对寄存器操作,不能针对存储器。

Page 37: 第四章   ARM 指令集

后缀 s 数据处理指令可以选择 s 后缀,以影响状态标志。但是比较

指令( cmp、 cmn、 tst 和 teq )不需要后缀 s ,它们总会直接影响 cpsr 中的状态标志。

在数据处理指令中,除了比较指令以外,其它的指令如果带有 s 后缀,同时又以 pc 为目标寄存器进行操作,则操作的同时从 spsr恢复 cpsr 。比如: movs pc, #0xff /* cpsr = spsr; pc = 0xff */

adds pc, r1, #0xffffff00 /* cpsr = spsr; pc = r1 + 0xffffff00 */

ands pc, r1, r2 /* cpsr = spsr; pc = r1 & r2; */

如果在 user 或者 system模式下使用带有 s 后缀的数据处理指令,同时以 pc 为目标寄存器,那么会产生不可预料的结果。因为 user 和 system模式下没有 spsr 。

Page 38: 第四章   ARM 指令集

当选择后缀S时: 如果结果为负,则N标志位置1;否则清0。 如果结果为0,则Z标志位置1;否则清0。 如果是算术运算指令或比较指令时,C标志位设

置为ALU的进位输出;否则设置为移位器的进位输出。如果不需要移位,则C保持不变。

在非算术操作中,V标志位保持原值。在算术操作中,如果有溢出,则置1;不发生溢出,则清0。

Page 39: 第四章   ARM 指令集

结果

操作数 1

BarrelShifter

操作数 2

ALU

Page 40: 第四章   ARM 指令集

数据处理指令的二进制编码如下:

add r0, r1, #0xff

add r0, r1, r1, LSL r2

add r0, r1, r1, LSL #31

Page 41: 第四章   ARM 指令集

数据处理指令的详细列表如下:操作码 [24 : 21] 助记符 意义 效果

0000 AND 逻辑位与 Rd = Rn AND Op2

0001 EOR 逻辑位异或 Rd = Rn EOR Op2

0010 SUB 减 Rd = Rn - Op2

0011 RSB 反向减 Rd = Op2 – Rn

0100 ADD 加 Rd = Rn + Op2

0101 ADC 带进位加 Rd = Rn + Op2 + C

0110 SBC 带进位减 Rd = Rn - Op2 + C -1

0111 RSC 反向带进位减 Rd = Op2 - Rn + C -1

1000 TST 测试 根据 Rn AND Op2 设置条件码

1001 TEQ 测试相等 根据 Rn EOR Op2 设置条件

1010 CMP 比较 根据 Rn - Op2 设置条件码

1011 CMN 负数比较 根据 Rn + Op2 设置条件码

1100 ORR 逻辑位或 Rd = Rn OR Op2

1101 MOV 传送 Rd = Op2

1110 BIC 位清零 Rd = Rn AND NOT Op2

1111 MVN 求反 Rd = NOT Op2

Page 42: 第四章   ARM 指令集

算术运算指令:

① ADD—— 加法运算指令    ADD 指令将 operand2 的数据与 Rn 的值相加,

结果保存到 Rd 寄存器。    指令格式如下:

  ADD{cond}{S} Rd , Rn , operand2

指令举例如下:ADDS R1 , R1 , #1       ; R1 = R1+1ADDS R3 , R1 , R2 , LSL #2  ; R3 = R1+R2<<2

Page 43: 第四章   ARM 指令集

② ADC——带进位加法指令   ADC 指令将 operand2 的数据与 Rn 的值相加,再加上 CPSR 中的 C 条件标志位,结果保存到 Rd 寄存器。指令格式如下:

ADC{cond}{S} Rd , Rn , operand2

指令举例如下: ADDS R4 , R0 , R2 ;使用 ADC 实现 64 位加法,ADC R5 , R1 , R3 ; (R5、 R4) = (R1、 R0)+(R3、R2)

Page 44: 第四章   ARM 指令集

③ SUB—— 减法运算指令 SUB 指令用寄存器 Rn 减去 operand2 ,

结果保存到 Rd 中。 指令格式如下:

SUB{cond}{S} Rd , Rn , operand2

指令举例如下:SUBS R0 , R0 , #l ; R0 = R0-1SUB R6 , R7 , #0x10 ; R6 = R7-0x10

Page 45: 第四章   ARM 指令集

④SBC——带进位减法指令 SBC 指令用寄存器 Rn 减去 operand2 ,再减去CPSR 中的 C 条件标志位的反码,结果保存到 Rd 中。

指令格式如下:SBC{cond}{S} Rd , Rn , operand2

指令举例如下:SUBS R4 , R0 , R2 ;使用 SBC 实现 64 位减法,SBC R5 , R1 , R3 ; (R5,R4) = (R1,R0)-(R3,R2)

Page 46: 第四章   ARM 指令集

⑤ RSB—— 反向减法指令 RSB 指令用寄存器 operand2 减去 Rn ,结果保存到 Rd 中。

指令格式如下:

RSB{cond}{S} Rd , Rn , operand2

指令举例如下:RSB R3 , R1 , #0xFF00 ; R3 = 0xFF00-R1RSBS R1 , R2 , R2 , LSL #2 ; R1R2<<2-R2

; (R1 =R2×3)

Page 47: 第四章   ARM 指令集

⑥ RSC——带进位反向减法指令 RSC 指令用寄存器 operand2 减去 Rn ,再

减去 CPSR 中的 C 条件标志位的反码,结果保存到Rd 中。

指令格式如下: RSC{cond}{S} Rd , Rn , operand2

指令举例如下: RSBS R2 , R0 , #0 RSC R3 , R1 , #0 ;使用 RSC 指令

实现 ;求 64 位数值的负数

Page 48: 第四章   ARM 指令集

逻辑运算指令:①AND—— 逻辑“与”操作指令

AND 指令将 operand2 的值与寄存器 Rn 的值按位逻辑“与”操作,结果保存到 Rd 中。

指令格式如下:AND{cond}{S} Rd , Rn , operand2

指令举例如下:ANDS R0 , R0 , #0x01 ; R0 = R0&0x01

;取出最低位数据AND R2 , R1 , R3 ; R2 = R1&R3

AND 指令可用于提取寄存器中某些位的值。

Page 49: 第四章   ARM 指令集

② ORR—— 逻辑“或”操作指令ORR 指令将 operand2 的值与寄存器 Rn 的值按位逻辑“或”操作,结果保存到 Rd 中。

指令格式如下: ORR{cond}{S} Rd , Rn , operand2

指令举例如下:

ORR R0 , R0 , #0x0F ;将 R0 的低 4 位置 1

ORR 指令用于将寄存器中某些位的值设置成 1 。

Page 50: 第四章   ARM 指令集

③ EOR—— 逻辑“异或”操作指令 EOR 指令将 operand2 的值与寄存器 Rn 的值按位逻辑“异或”操作,结果保存到 Rd 中。

指令格式如下:EOR{cond}{S} Rd , Rn , operand2

指令举例如下: EOR R1 , R1 , #0x0F ;将 Rl 的低 4 位取反 EORS R0 , R5 , #0x01 ;将 R0R5 异或 0x0

1 , ;并影响标志位 EOR 指令可用于将寄存器中某些位的值取反。将某一位与 0 异或,该位值不变;与 1 异或,该位值被求反。

Page 51: 第四章   ARM 指令集

④BIC—— 位清除指令BIC 指令将寄存器 Rn 的值与 operand2 的值的反码按位逻辑“与”操作,结果保存到 Rd 中。

指令格式如下:BIC{cond}{S} Rd , Rn , operand2

指令举例如下:BIC R1 , R1 , #0x0F ;将 R1 的低 4 位清 0 ,

;其它位不变 BIC 指令可用于将寄存器中某些位的值设置成 0 。将某

一位与 1做 BIC 操作,该位值被设置成 0 ;将某一位与 0做BIC 操作,该位值不变。

Page 52: 第四章   ARM 指令集

数据传送指令: ① MOV—— 数据传送指令MOV 指令将operand2 传送到目标寄存器 Rd中。

指令格式如下:MOV{cond}{S} Rd , operand2

指令举例如下:MOVS R3 , R1 , LSL #2 ; R3 = R1<<2

;影响标志位MOV PC, LR ; PCLR ,子程序返回

Page 53: 第四章   ARM 指令集

MOV 指令可以完成以下功能: 将数据从一个寄存器传送到另一个寄存器中。 将一个常数传送到一个寄存器中。 实现单纯的移位操作。 当 PC 寄存器作为目标寄存器时可以实现程序跳

转。这种跳转可以实现子程序调用以及从子程序中返回。

当 PC 寄存器作为目标寄存器且指令中 S 位被设置时,指令在执行跳转操作的同时,将当前处理器模式的 SPSR 寄存器内容复制到 CPSR 中。这样可以实现从某些异常中断中返回。

Page 54: 第四章   ARM 指令集

② MVN—— 求反指令MVN 指令将 operand2按位取反后传送到目标寄存器 Rd 中。

指令格式如下:MVN{cond}{S} Rd , operand2

指令举例如下:MVN R1 , #0xFF ; R10xFFFFFF00

MVN R1 , R2 ; Rl R2取反

Page 55: 第四章   ARM 指令集

比较指令: ① CMP——比较指令 CMP 指令将寄存器 Rn 的值减去 operand2 的值,根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

指令格式如下:CMP{cond} Rn , operand2

指令举例如下:CMP R1 , #10 ; R1与 10比较,设置相关标志位

CMP 指令与 SUBS 指令的区别?

Page 56: 第四章   ARM 指令集

②CMN——负数比较指令 CMN 指令将寄存器 Rn 的值加上 operand2 的值,根

据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

指令格式如下: CMN{cond} Rn , operand2 指令举例如下: CMN R0 , #1 ; R0+1 ,判断 R0 是否为 1 的补

码。 ;若是,则 Z 位置 1 。

CMN 指令与 ADDS 指令的区别在于 CMN 指令不保存运算结果。 CMN 指令可用于负数比较,比如“ CMN R0 ,#1” 指令则表示 R0与 -1比较。若 R0 为 -1( 即 1 的补码 ) ,则 Z 置位;否则 Z复位

Page 57: 第四章   ARM 指令集

测试指令: ① TST—— 位测试指令

TST 指令将寄存器 Rn 的值与 operand2 的值按位逻辑“与”操作,根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

指令格式如下:TST{cond} Rn , operand2

指令举例如下: TST R0 , #0x01 ;判断 R0 的最低位是否为 0 TST Rl , #0x0F ;判断 R1 的低 4 位是否为 0TST 指令与 ANDS 指令的区别在于 TST 指令不保存运算结果。 TST 指令通常与 EQ、 NE 条件码配合使用。当所有测试位均为 0 时, EQ 有效。而只要有一个测试位不为 0 ,则NE 有效。

Page 58: 第四章   ARM 指令集

② TEQ——测试相等指令 TEQ 指令将寄存器 Rn 的值与 operand2 的值按位逻辑“异或”操作,根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

指令格式如下:TEQ{cond} Rn , operand2

指令举例如下:TEQ R0 , R1 ;比较 R0与 R1 是否相等

; ( 不影响 V 位和 C 位 ) TEQ 指令与 EORS 指令的区别在于 TEQ 指令不保存运算结果。使用 TEQ 进行相等测试时,常与 EQ、 NE 条件码配合使用。当两个数据相等时, EQ 有效;否则 NE 有效。

Page 59: 第四章   ARM 指令集

乘法指令 ARM 有两类乘法指令:

32 位的乘法指令,即乘法操作的结果为 32 位; 64 位的乘法指令,即乘法操作的结果为 64 位。

Page 60: 第四章   ARM 指令集

① MUL——32 位乘法指令 MUL 指令将 Rm 和 Rs 中的值相乘,结果的低 32 位保存到 Rd 中。

指令格式如下:MUL{cond}{S} Rd , Rm , Rs ; RdRm*Rs

指令举例如下:MUL R1 , R2 , R3 ; R1=R2×R3MULS R0 , R3 , R7 ; R0=R3×R7 ,

;设置 CPSR 的 N 位和 Z 位

Page 61: 第四章   ARM 指令集

② MLA——32 位乘加指令 MLA 指令将 Rm 和 Rs 中的值相乘,再将乘积加上第 3 个操作数,结果的低 32 位保存到 Rd 中。

指令格式如下: MLA{cond}{S} Rd , Rm , Rs , Rn ; RdRm*Rs+

Rn

指令举例如下: MLA R1 , R2 , R3 , R0 ; R1=R2×R3+R0

Page 62: 第四章   ARM 指令集

③ UMULL—64 位无符号乘法指令 UMULL 指令将 Rm 和 Rs 中的值作无符号数相乘,结果的低 32 位保存到 RdLo 中,高 32 位保存到 RdHi 中。

指令格式如下: UMULL{cond}{S} RdLo , RdHi , Rm , Rs

; RdHi, RdLo Rm*Rs

指令举例如下: UMULL R0 , R1 , R5 , R8 ; (R1,R0)R5×

R8

Page 63: 第四章   ARM 指令集

④ UMLAL—64 位无符号乘加指令 UMLAL 指令将 Rm 和 Rs 中的值作无符号数相乘, 64 位乘积与 RdHi、 RdLo 相加,结果的低 32位保存到 RdLo 中,而高 32 位保存到 RdHi 中。 指令格式如下:

UMLAL{cond}{S} RdLo , RdHi , Rm , Rs

; RdHi, RdLo Rm*Rs+ RdHi, RdLo

指令举例如下: UMLAL R0 , R1 , R5 , R8

; (R1,R0)R5×R8+(R1,R0)

Page 64: 第四章   ARM 指令集

⑤ SMULL—64 位有符号乘法指令 SMULL 指令将 Rm 和 Rs 中的值作有符号数相乘,结果的低 32 位保存到 RdLo 中,而高 32 位保存到 RdHi 中。

指令格式如下:SMULL{cond}{S} RdLo , RdHi , Rm , Rs

; RdHi, RdLo Rm*Rs

指令举例如下: SMULL R2 , R3 , R7 , R6 ; (R3,R2)R7×

R6

Page 65: 第四章   ARM 指令集

⑥ SMLAL—64 位有符号乘加指令 SMLAL 指令将 Rm 和 Rs 中的值作有符号数相乘, 64 位乘积与 RdHi、 RdLo 相加,结果的低 32位保存到 RdLo 中,高 32 位保存到 RdHi 中。

指令格式如下:SMLAL{cond}{S} RdLo , RdHi , Rm , Rs

; RdHi, RdLo Rm*Rs+ RdHi, RdLo

指令举例如下:SMLAL R2 , R3 , R7 , R6 ; ; (R3,R2)R7×R6+(R3,R2)

Page 66: 第四章   ARM 指令集

乘法指令的特点: 不支持第 2 操作数为立即数。 结果寄存器不能与第一源寄存器相同。

Rd、 RdHi、 RdLo 不能与 Rm 为同一寄存器。RdHi 和 RdLo 不能为同一寄存器。

避免将 R15 定义为任一操作数或结果寄存器。 早期的 ARM 处理器仅支持 32 位乘法指令。 AR

M7版本和后续的在名字中有 M 的处理器才支持64 位乘法指令。

Page 67: 第四章   ARM 指令集

当在乘法指令中设置了位 S 时,则: 对于产生 32 位结果的指令形式,将标志位 N 设

置为 Rd 的第 31 位的值;对于产生长结果的指令形式,将其设置为 RdHi 的第 31 位的值。

如果 Rd 或 RdHi、 RdLo 为 0 ,则标志位 Z 置位。

乘法指令不影响 V 标志位。 ARM v5及以上的版本不影响 C 标志位; ARM

v5 以前的版本, C 标志位数值不确定。

Page 68: 第四章   ARM 指令集

3.2 Load/Store 指令 —— 加载 / 存储指令 对于存储器的读 /写只能用此类指令。 因为 ARM 处理器对外设寄存器、 I/O映射空间与存储器统一编址,对外围设备的 I/O操作也用此类指令。

共有三种加载 / 存储指令: 单寄存器的存取指令( LDR , STR ) 多寄存器存取指令( LDM , STM ) 单寄存器交换指令( SWP )

Page 69: 第四章   ARM 指令集

1. 单寄存器的存取指令

单寄存器加载 / 存储指令是 ARM 在寄存器和存储器间传送单个字节和字的最灵活方式。根据传送数据的类型不同,单个寄存器存取指令又可以分为以下两类:

单字和无符号字节的加载 / 存储指令 半字和有符号字节的加载 / 存储指令

Page 70: 第四章   ARM 指令集

( 1 )单字和无符号字节的加载/存储指令

LDR 指令从内存中取 32 位字或 8 位无符号字节数据放入寄存器;

STR 指令将寄存器中的 32 位字或 8 位无符号字节数据保存到存储器中。

注意: 字节传送时用 0将 8 位的操作数扩展到 32 位。

Page 71: 第四章   ARM 指令集

指令格式如下:

LDR{cond}{T} Rd , < 地址 > ;加载指定地址上的字数据,放入 Rd 中。

STR{cond}{T} Rd , < 地址 > ;存储 Rd 中字数据,到指定地址的存储单

元。

LDR{cond}B{T} Rd , < 地址 > ;加载字节数据到 Rd 中 , Rd 最低字节有效,

高 24 位为 0 。

STR{cond}B{T} Rd , < 地址 > ;存储 Rd 中字节数据, Rd 中最低字节为传

送数据。

Page 72: 第四章   ARM 指令集

T 后缀 T 为可选后缀,若指令有 T ,那么即使处理器是

在特权模式下,存储系统也将访问看成是处理器是在用户模式下。

用于存储器保护。 不能与前变址模式、自动变址模式一起使用。 T 在用户模式下无效。

Page 73: 第四章   ARM 指令集

指令寻址方式:

LDR/STR 指令寻址非常灵活,由两部分组成:一部分为一个基址寄存器,可以为任一个通用寄存

器;另一部分为一个地址偏移量。

地址偏移量有以下 3 种格式:立即数寄存器寄存器及移位常数。

Page 74: 第四章   ARM 指令集

①立即数 ——12 位立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。

指令举例如下: LDR R1 , [R0 , #0x12] ;将 R0+0x12 地址处的数据读出,保存到 R1 中 (R0 的值

不变 )

LDR R1 , [R0 , # -0x12]

;将 R0-0x12 地址处的数据读出,保存到 R1 中 (R0 的值不变 )

Page 75: 第四章   ARM 指令集

②寄存器 —— 寄存器中的数值可以加到基址寄存器,

也可以从基址寄存器中减去这个数值。指令举例如下:

LDR R1 , [R0 , R2]

;将 R0+R2 地址处的数据读出,保存到 R1 中

LDR R1 , [R0 , -R2]

;将 R0-R2 地址处的数据读出,保存到 R1 中

Page 76: 第四章   ARM 指令集

③寄存器及移位常数 —— 寄存器移位后的值可以加到基址寄存器,也

可以从基址寄存器中减去这个数值。

指令举例如下: LDR R1 , [R0 , R2 , LSL #2]

;将 R0+R2×4 地址处的数据读出,保存到 R1 中(R0、 R2 的值不变 )

LDR R1 , [R0 , -R2 , LSL #2]

;将 R0-R2×4 地址处的数据读出,保存到 R1 中 (R0、 R2 的值不变 )

注意:移位位数只能是 5 位的立即数,不能使用寄存器指定移位位数。

Page 77: 第四章   ARM 指令集

PC 的使用: 使用 PC 作为基址时,使用的数值是指令的地址

加 8 个字节。 PC 不能用做偏移寄存器,也不能用于任何变址

寻址模式。 把一个字加载到 PC将使程序转移到所加载的地

址,这是一个公认的实现跳转的方法。应当避免将一个字节加载到 PC 。

把 PC 存到存储器的操作在不同体系结构的处理器中产生不同的结果,应尽可能避免。

Page 78: 第四章   ARM 指令集

( 2 )半字和有符号字节的加载/存储指令

这类 LDR/STR 指令可实现半字(有符号和无符号)、有符号字节数据的传送。

特点: 偏移量格式、寻址方式与加载/存储字和无符号字节指

令基本相同。 立即数偏移量限定在 8 位,寄存器偏移量不可经过移位得到。

Page 79: 第四章   ARM 指令集

指令格式如下: LDR {cond}H Rd , < 地址 >

;加载无符号半字数据到 Rd 的低 16 位 , 高 16位清零。

LDR {cond}SB Rd , < 地址 > ;加载指定地址上有符号字节到 Rd 中,高 2

4 位用符号位扩展 LDR {cond}SH Rd , < 地址 >

;加载指定地址上的有符号半字到 Rd 中,高 16 位用符号位扩展。

STR{cond}H Rd , < 地址 > ;存储 Rd 中的低 16 位半字数据。 存储有符号数据和无符号数据之间没有差别。

Page 80: 第四章   ARM 指令集

说明: 有符号位字节或有符号半字的传送是用“符号

位”扩展到 32 位;无符号半字传送是用 0 扩展到 32 位。

地址对齐——对半字传送的地址必须为偶数。非半字对齐的半字加载将使 Rd 内容不可靠;非半字对齐的半字存储将使指定地址的 2 字节存储内容不可靠。

Page 81: 第四章   ARM 指令集

指令举例: LDRSB R1 , [R0 , R3]

;将 R0+R3 地址上的字节数据读到 R1, 高 24位用符号位扩展

LDRSH R1 , [R9] ;将 R9 地址上的半字数据读出到 R1 ,高 16位用符号位扩展

LDRH R6 , [R2] , #2 ;将 R2 地址上的半字数据读出到 R6 ,高 16

位用零扩展, R2=R2+2 STRH R1 , [Ro , #2]! ;将 R1 的数据保存到 R0+2 地址中,只存储低

2 字节数据, R0=R0+2

Page 82: 第四章   ARM 指令集

2. 多寄存器的存取指令 LDM 和 STM 指令可以实现在一组寄存器和

一块连续的内存单元之间存 /取数据。 LDM 为加载多个寄存器; STM 为存储多个寄存器。允许一条指令传送 16 个寄存器的任何子集或所有寄存器。

指令格式如下:

LDM{cond}< 模式 > Rn{!} , <reglist>{^}

STM{cond}< 模式 > Rn{!} , <reglist>{^}

Page 83: 第四章   ARM 指令集

指令格式中, 寄存器 Rn为基址寄存器,装有传送数据的初始

地址, Rn不允许为 R15 。 后缀“ !” 表示最后的地址写回到 Rn中。 寄存器列表 reglist 可包含多个寄存器或包含寄存

器的范围,使用“,”分开,如 {R1 , R2 , R6~R9} 。其中寄存器和存储器的对应关系满足规则:编号低的寄存器对应于存储器中低地址单元,编号高的寄存器对应于存储器中高地址单元。

Page 84: 第四章   ARM 指令集

后缀“ ^” 使用后缀“ ^” 进行数据传送且寄存器列表不包

含 PC时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。

后缀“ ^” 不允许在用户模式或系统模式下使用。 若在 LDM 指令中使用后缀“ ^”且寄存器列表

中包含有 PC时,除了正常的多寄存器传送外,将 SPSR 也拷贝到 CPSR 中,此用法可用于异常处理返回。

Page 85: 第四章   ARM 指令集

当 Rn 在寄存器列表中且使用后缀“ !” 时: 对于 STM 指令,若 Rn 为寄存器列表中的最低数

字的寄存器,则会将 Rn 的初值保存; 其它情况下 Rn 的加载值和存储值不可预知。

地址字对齐——这些指令忽略地址位 [1:0] 。

Page 86: 第四章   ARM 指令集

LDM/STM 的主要用途是现场保护、数据复制和参数传送等。其模式有如下 8 种 ( 前面 4种用于数据块的传输,后面 4 种是堆栈操作 ) : IA : 每次传送后地址加 4 ; IB : 每次传送前地址加 4 ; DA : 每次传送后地址减 4 ; DB : 每次传送前地址减 4 ; FD : 满递减堆栈; ED : 空递减堆栈; FA : 满递增堆栈; EA : 空递增堆栈。

Page 87: 第四章   ARM 指令集

举例如下: LDMIA R0! , {R3 - R9} ;加载 R0 指向地址上的多字数据,保存到 R3

~R9 中, R0 值更新 STMIA R1! , {R3 - R9} ;将 R3~ R9 的数据存储到 R1 指向的地址上,

R1 值更新 STMFD SP! , {R0 - R7 , LR} ;现场保存,将 R0~ R7、 LR入栈 LDMFD SP! , {R0 - R7 , PC} ;恢复现场,异常处理返回

Page 88: 第四章   ARM 指令集

3. 单寄存器交换指令( SWP ) SWP 指令用于将一个存储单元 (该单元地址放在寄存器 Rn 中 ) 的内容读取到一个寄存器 Rd 中,同时将另一个寄存器 Rm 的内容写入到该存储单元中。

指令格式如下: SWP{cond}{B} Rd , Rm , [Rn]

其中, B 为可选后缀,若有 B ,则交换字节,否则交换 32 位字;

Rd 为被加载的寄存器; Rm 的数据用于存储到 Rn 所指的地址中。若 Rm与 Rd 相同,则为寄存器与存储器内容进行交换; Rn 为要进行数据交换的存储器地址, Rn 不能与 Rd 和 Rm 相同。

Page 89: 第四章   ARM 指令集

指令举例如下: SWP R1 , R1 , [R0]

;将 R1 的内容与 R0 指向的存储单元的内容进行交换。

SWPB R1 , R2 , [R0]

;将 R0 指向的存储单元的内容读取 1 字节数据到 R1 中 ( 高 24 位清零 ) ,并将 R2的内容写入到该内存单元中 ( 最低字节有效 )

Page 90: 第四章   ARM 指令集

3.3 程序状态寄存器处理指令 ARM 指令中有两条指令,用于在状态寄

存器和通用寄存器之间传送数据。修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。 这两条指令分别是:

状态寄存器到通用寄存器的传送指令( MRS )

通用寄存器到状态寄存器的传送指令( MSR )

Page 91: 第四章   ARM 指令集
Page 92: 第四章   ARM 指令集

MRS

在 ARM 处理器中,只有 MRS 指令可以将状态寄存器 CPSR 或 SPSR读出到通用寄存器中。

指令格式如下:MRS{cond} Rd , psr ; Rd psr

其中: Rd —— 目标寄存器。 Rd 不允许为 R15 。 psr —— CPSR 或 SPSR 。指令举例如下:

MRS R1 , CPSR ; R1 CPSR

MRS R2 , SPSR ; R2 SPSR

Page 93: 第四章   ARM 指令集

MRS 指令读取 CPSR ,可用来判断 ALU的状态标志,或 IRQ、 FIQ 中断是否允许等。

在异常处理程序中,读 SPSR 可知道进行异常前的处理器状态等。

MRS与MSR配合使用,实现 CPSR 或SPSR 寄存器的读—修改—写操作,可用来进行处理器模式切换、允许/禁止 IRQ/FIQ中断等设置。

Page 94: 第四章   ARM 指令集

MSR

在 ARM 处理器中,只有 MSR 指令可以直接设置状态寄存器 CPSR 或 SPSR 。

指令格式如下:MSR{cond} psr_fields , #immed

MSR{cond} psr_fields , Rm

注:不可以使用 S 后缀。

Page 95: 第四章   ARM 指令集

其中: psr : CPSR 或 SPSR 。 immed : 要传送到状态寄存器指定域的立即数。 Rm : 要传送到状态寄存器指定域的数据的源寄

存器。 fields 指定传送的区域。 fields 可以是以下的一种

或多种 ( 字母必须为小写 ) : c 控制域 (psr[7…0]) ; x 扩展域 (psr[15…8]) ; (暂未用 ) s 状态域 (psr[23…16]) ; (暂未用 ) f 标志位域 (psr[31…24]) 。

Page 96: 第四章   ARM 指令集

程序状态寄存器

2731

N Z C V Q

28 67

I F T mode

1623 815 5 4 024

f s x c

U n d e f i n e dJ

Page 97: 第四章   ARM 指令集

指令举例如下: MSR CPSR_f , #0xF0000000 ; CPSR[31:28] = 0xF(0b1111) ,即 N,Z,C,V均被置 1 。

当使用立即数操作数时,只可选择更新标志位 [31 :24] 。

修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。

Page 98: 第四章   ARM 指令集

CPSR 的读—修改—写操作举例如下: 例 1 :设置进位位 C MRS R0, CPSR ;R0CPSR ORR R0,R0,#0X20000000 ; 置 1 进位位 C MSR CPSR_f, R0 ;CPSRR0

例 2 :从管理模式切换到 IRQ模式 MRS R0, CPSR ;R0CPSR BIC R0,R0,#0X1F ;低 5 位清零 ORR R0,R0,#0X12 ; 设置为 IRQ模式 MSR CPSR_c, R0 ; 传送回 CPSR

Page 99: 第四章   ARM 指令集

注意:只有在特权模式下才能修改状态寄存器的控制域 [7 : 0] ,以实现处理器模式转换,或设置开 /关异常中断 。程序中不能通过 MSR 指令直接修改 CPSR中的 T控制位来实现 ARM 状态/ Thumb 状态的切换,必须使用 BX 指令完成处理器状态的切换。用户模式下不能对 CPSR[23 : 0]做修改。

Page 100: 第四章   ARM 指令集

例 MRS R0 , CPSR BIC R0, R0, #0x1F ; R0 后 5 位清 0 ORR R0, R0, #0x1F ; R0 后 5 位赋值为 0b11111 MSR CPSR, R0 ; 根据模式位 [4 : 0]切换工作模式到系统模式 MOV R13 , #1 MOV R14 , #2

MRS R0 , CPSR BIC R0, R0, #0x1F ; R0 后 5 位清 0 ORR R0, R0, #0x11 ; R0 后 5 位赋值为 0b10001 MSR CPSR, R0 ; 根据模式位 [4 : 0]切换工作模式到 FIQ模

式 MOV R13 , #33 MOV R14 , #44

MRS R0 , CPSR BIC R0, R0, #0x1F ; R0 后 5 位清 0 ORR R0, R0, #0x10 ; R0 后 5 位赋值为 0b10000 MSR CPSR, R0 ; 根据模式位 [4 : 0]切换工作模式到用户模式

Page 101: 第四章   ARM 指令集

3.4 跳转指令 在 ARM 中有两种方式可以实现程序的跳转:

一种是使用转移指令直接跳转; 另一种则是直接向 PC 寄存器赋值来实现跳转。

ARM 的转移指令可以从当前指令向前或向后的32MB 的地址空间跳转,根据完成的功能它可以分为以下 4 种 : B 转移指令 BL 带链接的转移指令 BX 带状态切换的转移指令 BLX 带链接和状态切换的转移指令

Page 102: 第四章   ARM 指令集

① B—— 转移指令 B 指令跳转到指定的地址执行程序。 指令格式如下:

B{cond} label

指令举例如下: B WAITA ;跳转到WAITA 标号处 B 0x1234 ;跳转到绝对地址 0x1234处转移指令 B限制在当前指令的 ±32 MB 的范围内。

Page 103: 第四章   ARM 指令集

指令举例如下: 无条件跳转: B label

……

label …… 执行 10次循环:

MOV R0, #10

LOOP:

……

SUBS R0, #1

BNE LOOP

Page 104: 第四章   ARM 指令集

② BL—— 带链接的转移指令 BL 指令先将下一条指令的地址拷贝到 LR 链接寄存器中,然后跳转到指定地址运行程序。

指令格式如下: BL{cond} label

指令举例如下: BL SUB1 ; LR 下条指令地址

;转至子程序 SUB1 处 …

SUB1 … MOV PC, LR注意:转移地址限制在当前指令的 ±32 MB 的范围内。 BL 指

令用于子程序调用。

Page 105: 第四章   ARM 指令集

指令举例如下: CMP R1, #5

BLLT ADD11 ; <

BLGE SUB22 ; ≧ …

ADD11:

SUB22:

注:如果 R1<5 ,只有 ADD11 不改变条件码,本例才能正常工作。

Page 106: 第四章   ARM 指令集

BL SUB1

……

SUB1 ……

BL SUB2

……

SUB2 ……

注:在保存 R14 之前子程序不应再调用下一级的嵌套子程序。否则,新的返回地址将覆盖原来的返回地址,就无法返回到原来的调用位置。

STMFD R13! ,{R0-R3,R14}

Page 107: 第四章   ARM 指令集

③BX—— 带状态切换的转移指令 BX 指令跳转到 Rm 指定的地址执行程序。若 Rm

的位 [0] 为 1 ,则跳转时自动将 CPSR 中的标志 T 置位,即把目标地址的代码解释为 Thumb 代码;若 Rm的位 [0] 为 0 ,则跳转时自动将 CPSR 中的标志 T复位,即把目标地址的代码解释为 ARM 代码。

指令格式如下: BX{cond} Rm ;

Rm :该寄存器中为跳转的目标地址。当 Rm 寄存器的 bit[0] 为 0 时,目标地址处的指令为 ARM 指令;当bit[0] 为 1 时,目标地址处的指令为 Thumb 指令。

Page 108: 第四章   ARM 指令集

指令举例如下: ADRL R0 , ThumbFun+1

BX R0 ;跳转到 R0 指定的地址,并

根据 R0 的最低位来切换处 理器到 Thumb 状态。ThumbFun:

Page 109: 第四章   ARM 指令集

④ BLX —— 带链接和状态切换的转移指令 BLX 指令先将下一条指令的地址拷贝到 R14

( 即 LR)连接寄存器中,然后跳转到指定地址处执行程序。 ( 目前只有 V5T ARM 支持 BLX)

指令格式如下: BLX <target address>

转移地址限制在当前指令的 ±32 MB 的范围内。

Page 110: 第四章   ARM 指令集

3.5 异常中断产生指令 异常中断指令可以分为以下几种:

软件中断指令( SWI ) 断点指令( BKPT—仅用于 v5T 体系) 前导 0计数( CLZ—仅用于 v5T 体系)

Page 111: 第四章   ARM 指令集

① SWI——软件中断指令 软件中断指令 SWI 产生 SWI 异常中断,用来实现

用户模式到特权模式的切换。用于在用户模式下对操作系统中特权模式的程序的调用;它将处理器置于管理( _svc)模式,中断矢量地址为 0x08 。汇编格式如下:

SWI {<cond>} <24 位立即数 > 说明:

主要用于用户程序调用操作系统的 API 。 参数传递通常有两种方法:

指令中的 24bit 立即数指定 API号,其它参数通过寄存器传递。忽略指令中的 24bit 立即数, r0 指定 API号,其它参数通过其它

寄存器传递。

Page 112: 第四章   ARM 指令集

② BKPT—— 断点指令 断点中断指令 BKPT 用于产生软件断点,供调试程序用。仅用于 v5T 体系。

汇编格式如下: BKPT { immed_16}

immed_16 : 16 位的立即数。该立即数被调试软件用

来保存额外的断点信息。

断点指令用于软件调试;它使处理器停止执行正常指令而进入相应的调试程序。

Page 113: 第四章   ARM 指令集

③ CLZ—— 前导 0计数指令 前导 0计数指令 CLZ 对 Rm 中的前导 0 的个数

进行计数,结果放到 Rd 中。 (仅用于 v5T 体系。 )

汇编格式: CLZ{<cond>} Rd, Rm

举例如下: MOV R2 , #0X17F00; R2=0b0000 0000 0000 0001 0111 1111 0000 0000

CLZ R3 , R2 ; R3=15

Page 114: 第四章   ARM 指令集

3.6 协处理器指令 ARM支持 16 个协处理器,用于各种协处理器操

作,最常使用的协处理器是用于控制片上功能的系统协处理器,例如控制高速缓存和存储器的管理单元,浮点 ARM 协处理器等,还可以开发专用的协处理器。 ARM 协处理器指令根据其用途主要分为以下三类: 数据操作指令; 协处理器寄存器和内存单元之间数据存 / 取指令; ARM 寄存器与协处理器寄存器的数据传送指令。

Page 115: 第四章   ARM 指令集
Page 116: 第四章   ARM 指令集

① CDP—— 协处理器数据操作指令 ARM 处理器通过 CDP 指令通知 ARM 协处理

器执行特定的操作。协处理器数据操作完全是协处理器内部的操作,用于初始化 ARM 协处理器,完成协处理器寄存器的状态改变。

指令特点: 该操作由协处理器完成,即对命令参数的解释与协处理

器有关,指令的使用取决于协处理器。 若协处理器不能成功地执行该操作,将产生未定义指令

异常中断。

Page 117: 第四章   ARM 指令集

指令格式如下:

CDP{<cond>} <CP#> , <Cop1> , CRd , CRn , CRm{ , <Cop2>}

其中: CP# 指令操作的协处理器名。标准名为 pn , n 为 0~ 15 。 Cop1 协处理器的特定操作码。 CRd 作为目标寄存器的协处理器寄存器。 CRn 存放第 1 个操作数的协处理器寄存器。 CRm 存放第 2 个操作数的协处理器寄存器。 Cop2 可选的协处理器特定操作码。 指令举例如下: CDP p7 , 0 , c0 , c2 , c3 , 0 ;协处理器 7 执行操作码 1 为 0 和可选操作码 2 为 0 的操作。 CDP p6 , 1 , c3 , c4 , c5 ;协处理器 6 执行操作码为 1 的操作

Page 118: 第四章   ARM 指令集

② LDC/STC—— 协处理器数据存 / 取指令 协处理器数据存 / 取指令从存储器读取数据装入协处理器寄存器,或将协处理器寄存器的数据存入存储器。 LDC—— 协处理器数据读取指令

LDC 指令从某一连续的内存单元将数据读取到协处理器的寄存器中。进行协处理器数据的数据传送时,由协处理器来控制传送的字数。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。

Page 119: 第四章   ARM 指令集

指令格式如下: LDC{cond}{L} <CP#> , CRd , < 地址 >

其中: L 可选后缀,指明是长整数传送。 CP# 指令操作的协处理器名。标准名为 pn , n 为 0~1

5 。 CRd 作为目标寄存的协处理器寄存器。 < 地址 > 指定的内存地址。 指令举例如下: LDC p5 , c2 , [R2 , #4] ;读取 R2+4 指向

的内存单元的数据,传送到协处理器 p5 的 c2 寄存器中。 LDC p6 , c2 , [R1] ;读取 R1 指向的内

存单元的数据,传送到协处理器 p6 的 c2 寄存器中。

Page 120: 第四章   ARM 指令集

STC—— 协处理器数据存入指令。 将协处理器的寄存器数据存入到某一连续的内存单元中,由协处理器来控制写入的字数。 若协处理器不能成功地执行该操作,将产生未定义指令异常中断。

指令格式如下: STC{cond}{L} CP# , CRd , < 地址 >

其中格式说明同 LDC 指令。 指令举例如下: STC p5 , c1 , [R0] STC p5 , c1 , [R0 , #0x04]

Page 121: 第四章   ARM 指令集

③ MCR/MRC——ARM 寄存器与协处理器寄存器的数据传送指令 MCR ——ARM 寄存器到协处理器寄存器的数据传送指

令 MCR 指令将 ARM 处理器的寄存器中的数据传送到协处

理器的寄存器中。 若协处理器不能成功地执行该操作,将产生未定义指令异常中断。

指令格式如下: MCR{cond} CP# , Cop1, Rd, CRn, CRm{, <Cop2>} 其中格式说明同 CDP 指令。 指令举例如下:

MCR p14 , 3 , R7 , c7 , c11 , 6 ;从 ARM 寄存器中将数据传送到协处理器 p14 的寄存器中,其中

R7 为 ARM 寄存器,存放源操作数; c7 和 c11 位协处理器寄存器,为目标寄存器;操作码 1 为 3 ;操作码 2 为 6 。

Page 122: 第四章   ARM 指令集

MRC—— 协处理器寄存器到 ARM 寄存器的数据传送指令

MRC 指令将协处理器寄存器中的数据传送到 ARM 处理器的寄存器中。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。

指令格式如下: MRC{cond} CP# , Cop1, Rd , CRn , CRm{, <Cop2>}

其中格式说明同 CDP 指令。

指令举例如下: MRC p5 , 2 , R2 , c3 , c2

Page 123: 第四章   ARM 指令集

(四)一些基本的 ARM 指令功能段 4.1 算数逻辑运算指令的应用 例 1 : 实现乘法的指令段

MOV R0,R0,LSL #n ;R0=R0<<n ; R0= R0*2n

ADD R0,R0,R0,LSL #n ;R0=R0+R0*2n= R0*(2n+1)

RSB R0,R0,R0,LSL #n ;R0=R0*2n-R0= R0*(2n-1)

Page 124: 第四章   ARM 指令集

例 2 : 64 位数据运算 假设 R0 和 R1 存放一个 64 位数据, R0 中存放数据的低

32 位; R2 和 R3 中存放另一个 64 位数据, R2 中存放数据的低 32 位。

①两个 64 位数据的加法运算,结果保存到 R0 和 R1 中。 ADDS R0,R0,R2 ;低 32 位相加,设置 CPSR 的 C 标志位。 ADC R1,R1,R3 ; 高 32 位的带位相加 ②两个 64 位数据的减法运算,结果保存到 R0 和 R1 中。 SUBS R0,R0,R2 ;低 32 位相减,设置 CPSR 的 C 标志位。 SBC R1,R1,R3 ; 高 32 位的带位相减

Page 125: 第四章   ARM 指令集

③两个 64 位数据的比较操作,并设置 CPSR 中的条件标志位。

CMP R1,R3 ;比较高 32 位 CMPEQ R0,R2 ; 如果高 32 位相等,比较低 32

Page 126: 第四章   ARM 指令集

例 3 :转换内存中数据存储方式 将寄存器 R0 中的数据存储方式转换成另一种存储

方式。指令执行前 R0 中数据存储方式为: R0=A,B,C,D ;指令执行后 R0 中数据存储方式为: R0=D,C,B,A 。

EOR R1,R0,R0, ROR #16 ;R1=A^C,B^D,C^A,D^B BIC R1,R1,#OxFF0000 ;R1=A^C,0,C^A,D^B MOV R0,R0,ROR #8 ;R0=D,A,B,C EOR RO,RO,R1,LSR #8 ;R0=D,C,B,A

Page 127: 第四章   ARM 指令集

4.2 跳转指令的应用 例 1 :子程序的调用 BL 指令在执行跳转操作的同时保存下一条指令的地址,

用于从被调用的子程序中返回。 ……

BL function ;调用子程序 function

…… ;子程序结束后,程序将返回到这里执行 ……

function ;子程序的程序体 ……

MOV PC,LR ;子程序中的返回语句

Page 128: 第四章   ARM 指令集

例 2 :条件执行 实现类似于 C语言中的 if-else 功能的代码段。下例的功能

为求最大公约数。 C语言代码为:int gcb (int a,int b)

{

while (a!=b)

{ if (a>b) a=a-b;

else b=b-a;

}

return a;

}

对应的 ARM 代码段。(代码执行前R0 中存放 a , R1 中存放 b ;代码执行后 R0 中存放最大公约数。

gcb

CMP R0,R1 ;比较 a 和 b 的大小

SUBGT R0,R0,R1 ;if(a>b) a=a-b

SUBLT R1,R1,R0 ;if(b>a) b=b-a

BNE gcb ;if(a!=b) 跳转到 gcb继续执行

MOV PC,LR ;子程序结束,返回

Page 129: 第四章   ARM 指令集

例 3 :循环语句 下面代码段实现了程序循环执行。 MOV R0,#loopcount ;初始化循环次数 loop ; 循环体 …… SUBS R0,R0,#1 ; 循环计数器减 1 ,设置条件标志

BNE loop ; 循环计数器不为 0, 跳到 loop继续执行

…… ; 循环计数器为 0 ,程序继续执行

Page 130: 第四章   ARM 指令集

4.3 load/store 指令的应用 例:链表操作 下面代码段在链表中搜索与某一数据相等的元素。链表的每

个元素包括两个字,第 1 个字中包含一个字节数据;第 2 个字中包含指向下一个链表元素的指针,当这个指针为 0 时表示链表结束。代码执行前 R0 指向链表的头元素, R1 中存放将要搜索的数据;代码执行后 R0 指向第 1 个匹配的元素,或者当没有匹配元素时, R0 为 0 。

search CMP R0,#0 ;R0 指针是否为空 LDRNEB R2,[R0] ;读取当前元素中的字节数据 CMPNE R1,R2 ;判断数据是否为搜索的数据 LDRNE R0,[R0,#4] ; 如果不是 , 指针 R0 指向下一个元素

BNE search ; 跳转到 search 执行 MOV PC,LR ;搜索完成,程序返回