Presentation is loading. Please wait.

Presentation is loading. Please wait.

嵌入式系统讲义 第3章 ARM指令系统 周国运 2007.3.

Similar presentations


Presentation on theme: "嵌入式系统讲义 第3章 ARM指令系统 周国运 2007.3."— Presentation transcript:

1 嵌入式系统讲义 第3章 ARM指令系统 周国运 2007.3

2 第3章 ARM指令系统 主要内容 3.1 ARM指令结构 3.2 ARM寻址方式 3.3 ARM指令集 3.4 Thumb指令集

3 3.1 ARM指令系统概述 主要内容 一、指令系统概念 二、ARM指令的特点 三、ARM指令的格式 四、指令的条件码

4 3.1 ARM指令系统概述 一、指令系统概念 指令:是规定计算机进行某种操作的命令。 二、ARM指令的特点
指令系统:计算机能够执行的各种指令的集合。 二、ARM指令的特点 所有指令都是32位的。 大多数指令都在单周期内完成。 所有指令都可以条件执行。 ARM指令为load/store类型。 基本指令仅36条,分成五类。 有7种寻址方式。 指令集可以通过协处理器扩展。

5 ARM指令是加载/存储(Load/Store)型:
也即指令集仅能处理寄存器中的数据,而且处理结果都要放回寄存器中,而对系统存储器的访问则需要通过专门的加载/存储指令来完成。 ARM指令可以分为五大类: 数据处理指令、存储器访问指令、分支指令、协处理器指令、杂项指令。 ARM指令有7种寻址方式: 立即寻址、寄存器寻址、寄存器间接寻址、基址寻址、堆栈寻址 、块拷贝寻址、相对寻址。

6 三、ARM指令的格式 ARM指令基本的语法格式为: ARM指令典型的编码格式为:
<Opcode> {<cond>}{s} <Rd>, <Rn> {, <Operand2>} Opcode:指令操作码。 cond:指令的条件码。 S:决定指令的操作是否影响cpsr的值。 Rd:目标寄存器编码。 Rn:包含第一个操作数的寄存器编码。 Operand2:第2操作数。 ARM指令典型的编码格式为: (数据处理指令类) 例: ADDS R2,R1,#1 SUBNES R2,R1,#0x20 LDR R0,[R1] Cond Opcode S Rn Rd Operand2 11 12 15 16 19 20 21 24 25 27 28 31 7 8

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

8 指令条件码表 条件码 助记符 含 义 标 志 0000 EQ 相等 Z=1 0001 NE 不相等 Z=0 0010 CS/HS
含 义 标 志 0000 EQ 相等 Z=1 0001 NE 不相等 Z=0 0010 CS/HS 无符号数大于或等于 C=1 0011 CC/LO 无符号数小于 C=0 0100 MI 负数 N=1 0101 PI 非负数 N=0 0110 VS 溢出 V=1 0111 VC 没有溢出 V=0 1000 HI 无符号数大于 C=1且Z=0 1001 LS 无符号数小于或等于 C=0或Z=1 1010 GE 有符号数大于或等于 N=V 1011 LT 有符号数小于 N!=V 1100 GT 有符号数大于 Z=0且N=V 1101 LE 有符号数小于或等于 Z=1或N!=V 1110 AL 无条件执行 任意 1111 保留 v5以下版本总执行,v5及以上版本有用

9 3.2 ARM寻址方式 主要内容 一、立即寻址 二、寄存器寻址 三、寄存器间接寻址 四、基址寻址 五、堆栈寻址 六、块拷贝寻址 七、相对寻址

10 3.2 ARM寻址方式 寻址方式:处理器根据指令中给出的(地址)信息,寻找操作数(物理地址)的方式。

11 3.2.1 立即寻址 立即寻址也叫立即数寻址。 立即寻址概念:操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数,对应的寻址方式也就叫做立即寻址。 ADD R0,R0,#1 ;R0←R0+1 MOV R0 ,#0x3f ; R0←#0x3f 书写立即数时,要求以“#”为前缀。 十六进制数,#后加 0x或&,如 #0x3f,#&3f. 二进制数, #后加 0b, 如 #0b1011 十进制数, #后加 0d或缺省,如#0d678,#789 如何构造32位立即数?

12 因此有效立即数immediate可以表示成: <immediate>=immed_8 循环右移(2×rot)
在指令格式中,第二个操作数有12位: 因此有效立即数immediate可以表示成: <immediate>=immed_8 循环右移(2×rot) 4 bit 移位值 (0-15)乘于2,得到一个范围在0-30,步长为 2的移位值。 因此,将ARM中的立即数称为8位位图。 记住一条准则: “最后8位移动偶数位”得到立即数。 Immed_8 rot …… Shifter ROR immediate

13 下列命令中,汇编器把立即数转换为移位操作: MOV R0,#4096 ; uses 0x40 ror 26
例: 31 ror #0 ror #8 ror #30 7 下列命令中,汇编器把立即数转换为移位操作: MOV R0,#4096 ; uses 0x40 ror 26 ADD R1,R2,#0xFF0000 ; uses 0xFF ror 16 带有立即数的MOV 指令的二进制编码为: MOV R0,#0xF ;E3A00CF2. MOV R1,#0x ;E3A01811. MOV R4,#0x ;E3A04B4A. 0xF200 =0xF2循环右移(2*C) 0x =0x11循环右移(2*8) 0x12800 =0x4A循环右移(2*B)

14 当立即数数值在0到0xFF范围时,令immed_8=<immediate>,rot=0。
只有能够通过此构造方法得到的才是合法的立即数。 合法立即数: 0xFF;0x104(其8位图为0x41);0xFF0;0xFF00 非法立即数: 0x101;0x102;0xFF1 深入理解:一个合法的立即数可能有多种编码方法,将使某些指令的执行产生不同的结果。 如 0x3F0 ARM汇编编译器生成立即数的规则为: 当立即数数值在0到0xFF范围时,令immed_8=<immediate>,rot=0。 其它情况下,汇编编译器选择使rot数值最小的编码方式。 immed_8=0x3F,rot=0xE,对3F左移4位 immed_8=0xFC,rot=0xF,对FC左移2位

15 3.2.2 寄存器寻址 寄存器寻址: 这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。
寄存器寻址 寄存器寻址: ——利用寄存器中的数值作为操作数。 这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。 两种具体形式:寄存器寻址、寄存器移位寻址。 一、寄存器寻址 如指令: ADD R0,R1,R2 ;R0←R1+R2

16 当第二操作数为寄存器型时,在执行寄存器寻址操作时,也可以对第二操作数寄存器进行移位,此时第二操作数形式为:
二、寄存器移位寻址 1、寄存器移位寻址 当第二操作数为寄存器型时,在执行寄存器寻址操作时,也可以对第二操作数寄存器进行移位,此时第二操作数形式为: MOV Rd, Rn, Rm,{<shift>} 其中: Rm 称为第二操作数寄存器 <shift> 用来指定移位类型和移位位数,有两种形式: 5位立即数 (其值小于32) 寄存器(用Rs表示) (其值小于32) 在指令执行时将寄存器移位后的内容作为第二操作数参与运算。例如指令: ADD R3,R2,R1,LSR #2 ;R3←R2+(R1右移2位) ADD R3,R2,R1,LSR R0 ;R3←R2+(R1右移R0位)

17 — ROR 循环右移 — RRX 带扩展的循环右移 (1)LSL:逻辑左移,空出的最低有效位用0填充。
2、第二操作数移位方式 共有6种移位方式: — LSL 逻辑左移 — LSR 逻辑右移 — ASL 算术左移 — ASR 算术右移 — ROR 循环右移 — RRX 带扩展的循环右移 (1)LSL:逻辑左移,空出的最低有效位用0填充。 (2) LSR:逻辑右移,空出的最高有效位用0填充。 SUB R3,R2,R1,LSL #2 ;R3←R2-(R1左移2位) SUB R3,R2,R1,LSR R0 ;R3←R2-(R1右移R0位)

18 (3)ASL:算术左移,由于左移空出的有效位用0填充,因此它与LSL同义。
(4)ASR:算术右移 (Arithmetic Shift Right) 。算术移位的对象是带符号数,移位过程中必须保持操作数的符号不变。如果源操作数是正数,空出的最高有效位用0 填充,如果是负数用1填充。 ADD R3,R2,R1,ASL #2 ;R3←R2+(R1左移2位) SUB R3,R2,R1,ASR R3 ;R3←R2-(R1算术右移R3位)

19 31 0 SUB R3,R2,R1,ROR #2 ;R3←R2+(R1循环右移2位) SUB R3,R2,R1,RRX R0
(5)ROR:循环右移(Rotate Right),移出的字的最低有效位依次填入空出的最高有效位。 (6)RRX:带进位位的循环右移(Rotate Right Extended) 。将寄存器的内容循环右移1位,空位用原来C标志位填充。 C SUB R3,R2,R1,ROR #2 ;R3←R2+(R1循环右移2位) SUB R3,R2,R1,RRX R0 ;R3←R2-(R1带进位位循环右移R0位)

20 3、第二操作数的移位位数 移位位数可以用立即数方式或者寄存器方式给出,其值均小于32,应为0---31。 如下所示:
ADD R3,R2,R1,LSR #2 ;R3R2+(R1右移2位) ADD R3,R2,R1,LSR R4 ;R3R2+(R1右移R4位) 寄存器R1的内容分别逻辑右移2位、R4位,再与寄存器R2的内容相加,结果放入R3中。

21 3.2.3 寄存器间接寻址 寄存器间接寻址 ——就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储单元中。例如以下指令:
寄存器间接寻址 寄存器间接寻址 ——就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储单元中。例如以下指令: LDR R0,[R1] ;R0←[R1] STR R0,[R1] ;[R1]←R0 第一条指令将以R1的值为地址的存储单元中的内容加载到寄存器R0中。 第二条指令将R0的内容存储到以R1的值为地址的存储单元中。 R1—— 基址寄存器 R1的内容——基地址

22 3.2.4 变址寻址 一、变址寻址 也叫基址加偏(变)址寻址
变址寻址 一、变址寻址 也叫基址加偏(变)址寻址 ——将基址寄存器的内容与指令中给出的地址偏移量相加,得到操作数所在的存储器的有效地址。 变址寻址方式常用于访问某基地址附近的地址单元。(4K) Cond Opcode Rn Rd Offset 11 12 15 16 19 20 27 28 31 例如: LDR R0,[R1,#4] ;R0←mem32[R1+4]

23 二、偏移地址方式 有三种加偏址的方式 也叫前索引偏移。 1、前变址模式(不修改基址寄存器):
——先基址+偏址,生成操作数地址,做指令指定的操作。 也叫前索引偏移。 0x05 R1 0x200 基址 寄存器 R0 源 寄存器 偏移量 12 0x20C Pre-indexed: STR r0,[r1,#12]

24 2、自动变址模式(修改基址寄存器): ——①先基址+偏移,生成操作数地址,做指令指定的操作。②然后自动修改基址寄存器。 例如: LDR R0,[R1,#4]! ;R0←mem32 [R1+4] ;R1←R1+4 ! ——表示更新基址寄存器。

25 例 Post-indexed: STR r0,[r1],#12
3、后变址模式(修改基址寄存器): ——①基址寄存器不加偏移作为操作数地址。 ②完成指令操作后,用(基址+偏移)的值修改基址寄存器。 即先用基地址传数,然后修改基地址(基址+偏移),也叫后索引偏移。 0x5 r1 0x200 原基址 寄存器 r0 源 寄存器 偏移量 12 0x20c 更新基 址寄存器 例 Post-indexed: STR r0,[r1],#12

26 三、偏移地址形式 常用的是立即数偏移的形式。 ——可以是一个立即数,也可以是另一个寄存器,并且还可以是寄存器移位操作。如下所示:
LDR r0,[r1,r2] ;r0<—mem32[r1+r2] LDR r0,[r1,r2,LSL #2];r0<—mem32[r1+r2*4] 常用的是立即数偏移的形式。

27 3.2.5 堆栈寻址 堆栈寻址 ——堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针SP)指向一块存储区域(堆栈)。
堆栈寻址 堆栈寻址 ——堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针SP)指向一块存储区域(堆栈)。 堆栈可分为两种增长方式: 向上生长:向高地址方向生长,称为递增堆栈。 向下生长:向低地址方向生长,称为递减堆栈。

28 根据堆栈指针指向的数据位置的不同,可分为:
满堆栈 ——堆栈指针指向最后压入堆栈的有效数据项,称为满堆栈; 空堆栈 ——堆栈指针指向下一个待压入数据的空位置,称为空堆栈。 这样就有4种类型的堆栈表示递增和递减的满和空堆栈的各种组合。

29 四种类型的堆栈工作方式 满递增堆栈FA( Full Ascending ): ——堆栈指针指向最后压入的数据,且由低地址向高地址生长。 满递减堆栈FD: ——堆栈指针指向最后压入的数据,且由高地址向低地址生长。 空递增堆栈EA: ——堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生长。 空递减堆栈ED( Empty Descending ): ——堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生长。

30 LDMFA sp!,{r4-r7,pc} STMFD sp!,{r4-r7,lr}
第5次到此 r4 100 r5 FF r6 1234 r7 A0BE lr 8034 ABCD 8765 102E 16 FFFF 1010 8420 9753 高地址 LDMFA sp!,{r4-r7,pc} 满递增 SP AOBE 1 14544 12 pc 9020 Old SP STMFD sp!,{r4-r7,lr} 满递减 ……

31 3.2.6 块拷贝寻址 一、块拷贝寻址 ——把存储器中的一个数据块加载到多个寄存器中,或者是把多个寄存器中的内容保存到存储器中。
应用指令:块拷贝寻址是多寄存器传送指令LDM/STM的寻址方式,因此也叫多寄存器寻址。 块拷贝寻址操作中的寄存器,可以是R0-R15这16个寄存器的子集(一部分),或是所有寄存器。

32 二、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 r10 IB DA DB STMxx r10, {r0,r1,r4} 基址寄存器 (Rn) 地址递增,指针最后位置 地址递减,指针最后位置

33 多寄存器load和stroe指令的堆栈和块拷贝对照
栈生长 地址 顶空满 增减次序 栈、块递增 栈、块递减 顶满 顶空 地址 增加 先增 STMIB STMFA LDMIB LDMED 后增 STMIA STMEA LDMIA LDMFD 减少 先减 LDMDB LDMEA STMDB STMFD 后减 LDMDA LDMFA STMDA STMED STMFA(Full、Add):栈满递增。F---栈顶满空;A---栈增减 LDMIB*(Inc、Befo):块先增地址、再传数。

34 3.2.7 相对寻址 相对寻址 BL SUBRl ;调用到SUBRl子程序
—— 与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。 相对寻址指令举例如下: BL SUBRl ;调用到SUBRl子程序 ; SUBRl应为24位有符号数 SUBR1 … MOV PC, LR ;返回

35 3.3 ARM指令集 主要内容 1、存储器访问指令 2、数据处理指令 3、分支指令 4、协处理器指令 5、杂项指令 6、ARM伪指令

36 3.3.1 存储器访问指令 ARM微处理器用加载/存储指令访问存储器,实现在寄存器和存储器之间传送数据。加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。 由于ARM处理器对外设寄存器、I/O映射空间与存储器统一编址,因此,对外围设备的I/O操作也用此类指令。 基本的加载/存储指令仅有5条,分为3种: — LDR和STR,单寄存器加载/存储指令 — LDM和STM,多寄存器加载/存储指令 — SWP,寄存器和存储器数据交换指令

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

38 1、单字和无符号字节的加载/存储指令 LDR: 指令从内存中取32位字或8位无符号字节数据放入寄存器; STR:
指令将寄存器中的32位字或8位无符号字节数据保存到存储器中。 注意: 无符号字节加载时,用0将8位的操作数扩展到32位。

39 (1)指令格式 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中最低字节为传送数据。

40 T后缀 T为可选后缀,若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是处理器是在用户模式下。 用于存储器保护。
不能与前变址模式、自动变址模式一起使用(即不能改变基址寄存器值)。 T在用户模式下无效。

41 (2)操作数寻址方式 LDR/STR指令为变址寻址,由两部分组成: 基地址部分:为一个基址寄存器,可以为任一个通用寄存器;
偏移地址部分:这一部分非常灵活,实际就是第二个操作数,可以有以下3种格式: 立即数 寄存器 寄存器及移位常数。

42 ① 立即数 指令举例如下: LDR R1,[R0,#0x12] LDR R1,[R0,# -0x12]
——12位立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 指令举例如下: LDR R1,[R0,#0x12] ;将R0+0x12地址处的数据读出,保存到R1中(R0的值不变) LDR R1,[R0,# -0x12] ;将R0-0x12地址处的数据读出,保存到R1中(R0的值不变)

43 ② 寄存器 ——寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 指令举例如下: LDR R1,[R0,R2]

44 ;将R0+R2×4地址处的数据读出,保存到R1中(R0、R2的值不变)
③ 寄存器及移位常数 ——寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 指令举例如下: 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位的立即数,不能使用寄存器指定移位位数。

45 ④ PC(即R15)使用的几个问题 使用PC作为基址时,使用的数值是指令的地址加8个字节(取指与执行相差8个字节)。
把一个字加载到PC,将使程序转移到所加载的地址,这是一个公认的实现跳转的方法。但是应当避免将一个字节加载到PC。 把PC存到存储器的操作在不同体系结构的处理器中产生不同的结果,应尽可能避免。

46 2、半字和有符号字节的加载/存储指令 这类LDR/STR指令可实现半字(有符号和无符号)、有符号字节数据的传送。 特点:
偏移量格式、寻址方式与加载/存储字和无符号字节指令基本相同。 立即数偏移量限定在8位,寄存器偏移量不可经过移位得到。

47 ;加载无符号半字数据到Rd的低16位,高16位清零。
(1)指令格式如下 LDR {cond}H Rd,<地址> ;加载无符号半字数据到Rd的低16位,高16位清零。 LDR {cond}SB Rd,<地址> ;加载指定地址上有符号字节到Rd中,高24位用符号位扩展 LDR {cond}SH Rd,<地址> ;加载指定地址上的有符号半字到Rd中,高16位用符号位扩展。 STR{cond}H Rd,<地址> ;存储Rd中的低16位半字数据。 存储有符号数据和无符号数据之间没有差别。

48 (2)两点说明: 符 号 位——有符号字节或有符号半字的加载,用“符号位”扩展到32位;无符号半字传送是用0扩展到32位。
地址对齐——对半字传送的地址必须为偶数。非半字对齐的半字加载将使Rd内容不可靠;非半字对齐的半字存储将使指定地址的2字节存储内容不可靠。

49 (3)指令举例 LDRSB R1,[R0,R3] ;将R0+R3地址上的字节数据读到R1,高24位用符号位扩展。 LDRSH R1,[R9]
LDRH R6,[R2],#2 ;将R2地址上的半字数据读出到R6,高16位用零扩展,然后修改R2=R2+2。 STRH R1,[R0,#2]! ;将R1的数据保存到R0+2地址中,只存储低2字节数据,并且修改R0=R0+2。

50 二、多寄存器的存取指令 LDM和STM指令可以实现在一组寄存器和一块连续的内存单元之间存/取数据。
这两条指令,允许传送16个寄存器R0---R15的任何子集或所有寄存器。 1、指令格式 LDM{cond}<模式> Rn{!},<reglist>{^} STM{cond} <模式> Rn{!},<reglist>{^}

51 (1)Rn:表示基址寄存器,装有传送数据的初始地址,Rn不允许为R15(即PC)。 (2)Rn后缀“!”:表示最后的地址写回到Rn中。
2、指令格式说明 (1)Rn:表示基址寄存器,装有传送数据的初始地址,Rn不允许为R15(即PC)。 (2)Rn后缀“!”:表示最后的地址写回到Rn中。 (3)Reglist:表示寄存器列表,可包含多个序号连续的或者分离的寄存器,用“,”分开。 格式例子:{R1,R2,R6~R9} 列表寄存器和存储器地址的关系规则: 编号低的寄存器对应于存储器中低地址单元,编号高的寄存器对应于存储器中高地址单元。

52 (4)后缀“^”说明 寄存器列表不包含PC:使用后缀“^”进行数据传送且时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。
寄存器列表包含有PC:除了正常的多寄存器传送外,还要将SPSR拷贝到CPSR中。 该用法可用于异常处理返回。 禁用情况:后缀“^”不允许在用户模式或系统模式下使用。 ,因为它们没有SPSR

53 ——这些指令寻址是字对齐的,即忽略地址位[1:0]。
(5)当Rn在寄存器列表中且使用后缀“!” 对于STM指令,若Rn为寄存器列表中的最低数字的寄存器,则会将Rn的初值保存; 其它情况下Rn的加载值和存储值不可预知。 (6)地址字对齐 ——这些指令寻址是字对齐的,即忽略地址位[1:0]。

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

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

56 3、应用举例 LDMIA R0!,{R3 - R9} ;加载R0指向地址上的多字数据,保存到R3~R9中,R0值更新。 STMIA R1!,{R3 - R9} ;将R3~R9的数据存储到R1指向的地址上,R1值更新 。 STMFD SP!,{R0 - R7,LR} ;现场保存,将R0~R7、LR入栈,SP值更新 。 LDMFD SP!,{R0 - R7,PC} ;恢复现场,包括CPSR,异常处理返回,SP值更新。

57 三、单寄存器交换指令(SWP) SWP指令用于将一个存储单元(该单元地址放在寄存器Rn中)的内容读取到一个寄存器Rd中,同时将另一个寄存器Rm的内容写入到该存储单元中。 1、指令格式 SWP{cond}{B} Rd,Rm,[Rn] B为可选后缀,若有B,则交换字节,否则交换32位字 Rd为被加载的寄存器 Rm的数据用于存储到Rn所指的地址中 若Rm与Rd相同,则为寄存器与存储器内容进行交换 Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同。

58 2、指令举例 SWP R1,R1,[R0] ;将R1的内容与R0指向的存储单元的内容进行交换。 SWPB R1,R2,[R0]

59 数据处理指令 主要内容 1、数据处理指令概述 2、算术运算指令 3、逻辑运算指令 4、数据传送指令 5、比较指令 6、测试指令

60 3.3.2.1 数据处理指令概述 1、ARM数据处理指令的功能 2、ARM数据处理指令的特点 主要完成寄存器中数据的算术和逻辑运算操作。
数据处理指令概述 1、ARM数据处理指令的功能 主要完成寄存器中数据的算术和逻辑运算操作。 2、ARM数据处理指令的特点 操作数来源:所有的操作数要么来自寄存器,要么来自立即数,不会来自存储器。 操作结果:如果有结果,则结果一定是为32位宽、或64位宽(长乘法指令),并且放在一个或两个寄存器中,不会写入存储器。 有第二个操作数(除了乘法指令) Operand2 :切记其三种形式:立即数、寄存器、寄存器移位。 乘法指令的操作数:全部是寄存器。

61 3、ARM数据处理指令分类 22条可分为5类: 算术运算指令: ADD ADC SUB SBC RSB RSC
MUL MLA UMULL UMLAL SMULL SMLAL 逻辑运算指令: AND ORR EOR BIC 数据传送指令: MOV MVN 比较指令: CMP CMN 测试指令: TST TEQ 上述指令只能对寄存器操作,不能针对存储器。

62 4、数据处理指令对程序状态寄存器CPSR的影响
指令中可以选择s后缀,以影响状态标志。但是比较指令(cmp、cmn、tst和teq)不需要后缀S,它们总会直接影响CPSR中的状态标志。 (2)对CPSR中标志位的影响: N标志位:如果结果为负,则N标志位置1;否则清0。 Z标志位:如果结果为0,则Z标志位置1;否则清0。 C标志位:如果是加、减运算指令或比较指令时,C标志位设置为ALU的进位输出;否则设置为移位器的移位输出。如果不需要移位,则C保持不变。 V标志位:在非加减操作中,V标志位保持原值。在加减操作中,如果有溢出,则置1;不发生溢出,则清0。

63 (3)关于恢复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模式:会产生不可预料的结果,因为在这两种模式下没有SPSR。

64 数据处理指令的二进制编码 add r0, r1, #0xff add r0, r1, r1, LSL #31
add r0, r1, r1, LSL r2

65 5、数据处理指令的详细列表(未含6条乘法指令)
操作码[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

66 3.3.2.2 算术运算指令 一、加减运算指令 1、 ADD——加法运算指令 指令格式
算术运算指令 一、加减运算指令 1、 ADD——加法运算指令 指令格式  ADD{cond}{S} Rd,Rn,operand2    ADD指令将operand2的数据与Rn的值相加,结果保存到Rd寄存器。 指令举例 ADDS R1,R1,#1       ;R1=R1+1 ADDS R3,R1,R2,LSL #2  ; R3=R1+R2<<2

67 ADC{cond}{S} Rd,Rn,operand2
指令格式 ADC{cond}{S} Rd,Rn,operand2   ADC指令将operand2的数据与Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器。 指令举例 ADDS R4,R0,R2 ;使用ADC实现64位加法 ADC R5,R1,R3 ;(R5、R4)=(R1、R0)+(R3、R2)

68 3、SUB——减法运算指令 指令格式 SUB{cond}{S} Rd,Rn,operand2
SUB指令用寄存器Rn减去operand2,结果保存到Rd中。 指令举例 SUBS R0,R0,#l ;R0=R0-1 SUB R6,R7,#0x10 ;R6=R7-0x10

69 4、SBC——带进位减法指令 指令格式 SBC{cond}{S} Rd,Rn,operand2
SBC指令用寄存器Rn减去operand2,再减去CPSR中的C条件标志位的反码,结果保存到Rd中。 指令举例 SUBS R4,R0,R2 ;使用SBC实现64位减法, SBC R5,R1,R3 ;(R5,R4)=(R1,R0)-(R3,R2)

70 RSB指令用寄存器operand2减去Rn,结果保存到Rd中。
指令格式如下: RSB{cond}{S} Rd,Rn,operand2 RSB指令用寄存器operand2减去Rn,结果保存到Rd中。 指令举例如下: RSB R3,R1,#0xFF ;R3=0xFF00-R1 RSBS R1,R2,R2,LSL #2 ;R1R2<<2-R ;(R1 =R2×3)

71 6、RSC——带进位反向减法指令 指令格式如下: RSC{cond}{S} Rd,Rn,operand2
RSC 指令用寄存器operand2减去Rn,再减去CPSR中的C条件标志位的反码,结果保存到Rd中。 指令举例如下: RSBS R2,R0,#0 ;求一个32位数的负数 RSC R3,R1,#0 ;使用RSC指令实现 ;求64位数值的负数

72 二、乘法指令 ARM有两类乘法指令: 32位的乘法指令,即乘法操作的结果为32位; 64位的乘法指令,即乘法操作的结果为64位。
MUL Rd,Rm,Rs 32位乘法指令 MUA Rd,Rm,Rs,Rn 32位乘加指令 UMULL RdL,RdH,Rm,Rs,Rn 64位无符号乘法 UMAL RdL,RdH,Rm,Rs,Rn 64位无符号乘加 SMULL RdL,RdH,Rm,Rs,Rn 64位有符号乘法 64位有符号乘加

73 二、乘法指令 ARM有两类乘法指令: 32位的乘法指令,即乘法操作的结果为32位; 64位的乘法指令,即乘法操作的结果为64位。 助记符
说 明 操 作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 RdRm*Rs(Rd≠Rm) MUA Rd,Rm,Rs,Rn 32位乘加指令 RdRm*Rs+Rn (Rd≠Rm) UMULL RdL,RdH,Rm,Rs,Rn 64位无符号乘法 (RdL,RdH)Rm*Rs UMAL RdL,RdH,Rm,Rs,Rn 64位无符号乘加 SMULL RdL,RdH,Rm,Rs,Rn 64位有符号乘法 64位有符号乘加

74 MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中。
指令格式如下: MUL{cond}{S} Rd,Rm,Rs ;RdRm*Rs MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中。 指令举例如下: MUL R1,R2,R3 ;R1=R2×R3 MULS R0,R3,R7 ;R0=R3×R7, ;设置CPSR的N位和Z位

75 MLA指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低32位保存到Rd中。
指令格式如下: MLA{cond}{S} Rd,Rm,Rs,Rn ; RdRm*Rs+Rn MLA指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低32位保存到Rd中。 指令举例如下: MLA R1,R2,R3,R0 ;R1=R2×R3+R0

76 UMULL{cond}{S} RdLo,RdHi,Rm,Rs
指令格式如下: UMULL{cond}{S} RdLo,RdHi,Rm,Rs ; RdHi, RdLo Rm*Rs UMULL指令将Rm和Rs中的值作无符号数相乘,结果的低32位保存到RdLo中,高32位保存到RdHi中。 指令举例如下: UMULL R0,R1,R5,R ;(R1,R0)R5×R8

77 第6次到此 4、 UMLAL—64位无符号乘加指令 指令格式如下: UMLAL{cond}{S} RdLo,RdHi,Rm,Rs ;RdHi, RdLo Rm*Rs+ RdHi, RdLo UMLAL指令将Rm和Rs中的值作无符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 指令举例如下: UMLAL R0,R1,R5,R ;(R1,R0)R5×R8+(R1,R0)

78 SMULL指令将Rm和Rs中的值作有符号数相乘,结果的低32位保存到RdLo中,而高32位保存到RdHi中。
指令格式如下: SMULL{cond}{S} RdLo,RdHi,Rm,Rs ; RdHi, RdLo Rm*Rs SMULL指令将Rm和Rs中的值作有符号数相乘,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 指令举例如下: SMULL R2,R3,R7,R6 ;(R3,R2)R7×R6

79 6、 SMLAL—64位有符号乘加指令 指令格式如下: SMLAL{cond}{S} RdLo,RdHi,Rm,Rs ; RdHi, RdLo Rm*Rs+ RdHi, RdLo SMLAL指令将Rm和Rs中的值作有符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,高32位保存到RdHi中。 指令举例如下: SMLAL R2,R3,R7,R6 ; ;(R3,R2)R7×R6+(R3,R2)

80 7、乘法指令的特点 不支持第2操作数为立即数。 结果寄存器不能与第一源寄存器相同。 Rd、RdHi、RdLo不能与Rm为同一寄存器。
早期的ARM处理器仅支持32位乘法指令。ARM7版本和后续的在名字中有M的处理器才支持64位乘法指令。

81 对标志位的影响 对N标志位:对有符号数乘法,若结果是32位指令形式,Rd的第31位是标志位N;对于产生长结果的指令形式,RdHi的第31位是标志位。 对Z标志位:如果Rd或RdHi、RdLo为0,则标志位Z置位。 对V标志位:乘法指令不影响V标志位。 对C标志位: ARM v5及以上的版本不影响C标志位; ARM v5以前的版本,C标志位数值不确定。

82 3.3.2.3 逻辑运算指令 1、AND——逻辑“与”操作指令 AND指令可用于提取寄存器中某些位的值。 指令格式如下:
逻辑运算指令 1、AND——逻辑“与”操作指令 指令格式如下: AND{cond}{S} Rd,Rn,operand2 AND指令将operand2的值与寄存器Rn的值按位逻辑“与”操作,结果保存到Rd中。 指令举例如下: ANDS R0,R0,#0x01 ;R0=R0&0x01 ;取出最低位数据 AND R2,R1,R ;R2=R1&R3 AND指令可用于提取寄存器中某些位的值。

83 ORR{cond}{S} Rd,Rn,operand2
指令格式如下: ORR{cond}{S} Rd,Rn,operand2 ORR指令将operand2的值与寄存器Rn的值按位逻辑“或”操作,结果保存到Rd中。 指令举例如下: ORR R0,R0,#0x0F ;将R0的低4位置1 ORR指令用于将寄存器中某些位的值设置成1。

84 EOR指令将operand2的值与寄存器Rn的值按位逻辑“异或”操作,结果保存到Rd中。
指令格式如下: EOR{cond}{S} Rd,Rn,operand2 EOR指令将operand2的值与寄存器Rn的值按位逻辑“异或”操作,结果保存到Rd中。 指令举例如下: EOR R1,R1,#0x0F ;将Rl的低4位取反 EORS R0,R5,#0x01 ;将R0R5异或0x01, ;并影响标志位 EOR指令可用于将寄存器中某些位的值取反。将某一位与0异或,该位值不变;与1异或,该位值被求反。

85 4、BIC——位清除指令 BIC指令将寄存器Rn的值与operand2的值的反码按位逻辑“与”操作,结果保存到Rd中。 指令格式如下:
BIC{cond}{S} Rd,Rn,operand2 BIC指令将寄存器Rn的值与operand2的值的反码按位逻辑“与”操作,结果保存到Rd中。 指令举例如下: BIC R1,R1,#0x0F ;将R1的低4位清0, ;其它位不变 BIC指令可用于将寄存器中某些位的值设置成0。将某一位与1做BIC操作,该位值被设置成0;将某一位与0做BIC操作,该位值不变。

86 3.3.2.4 数据传送指令 1、 MOV——数据传送指令 (1)指令格式如下: MOV{cond}{S} Rd,operand2
数据传送指令 1、 MOV——数据传送指令 (1)指令格式如下: MOV{cond}{S} Rd,operand2 MOV指令将operand2传送到目标寄存器Rd中。 (2)指令举例如下: MOVS R3,R1,LSL #2 ;R3=R1<<2 ;影响标志位 MOV PC,LR ;PCLR,子程序返回

87 (3)MOV指令的功能 寄存器之间传送。 立即数传送到寄存器中。(8位立即数位图) 实现单纯的移位操作。MOV Rd,Rd,LSL,#3
实现子程序调用、从子程序中返回。当PC寄存器作为目标寄存器时可以实现程序跳转。 实现把当前处理器模式的SPSR寄存器内容复制到CPSR中。 方法:当PC寄存器作为目标寄存器且指令中S位被设置时,指令在执行跳转操作的同时,将当前处理器模式的SPSR寄存器内容复制到CPSR中。这样可以实现从某些异常中断中返回。 例子:MOVS PC,LR

88 MVN指令将operand2按位取反后传送到目标寄存器Rd中。
指令格式如下: MVN{cond}{S} Rd,operand2 MVN指令将operand2按位取反后传送到目标寄存器Rd中。 指令举例如下: MVN R1,#0xFF ;R10xFFFFFF00 MVN R1,R ; Rl R2取反

89 3、比较指令 (1)CMP——比较指令 指令格式如下: CMP{cond} Rn,operand2
CMP指令将寄存器Rn的值减去operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。 指令举例如下: CMP R1,#10 ;R1与10比较,设置相关标志位 CMP指令与SUBS指令的区别?

90 (2)CMN——负数比较指令 指令格式如下: CMN{cond} Rn,operand2
CMN指令将寄存器Rn的值加上operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。 使用方法:一般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复位

91 4、测试指令 (1)TST——位测试指令 指令格式如下: TST{cond} Rn,operand2
TST指令将寄存器Rn的值与operand2的值按位逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。 指令举例如下: TST R0,#0x01 ;判断R0的最低位是否为0 TST Rl,#0x0F ;判断R1的低4位是否为0 TST指令与ANDS指令的区别在于TST指令不保存运算结果。TST指令通常与EQ、NE条件码配合使用。当所有测试位均为0时,EQ有效。而只要有一个测试位不为0,则NE有效。

92 (2)TEQ——测试相等指令 指令格式如下: TEQ{cond} Rn,operand2 TEQ指令将寄存器Rn的值与operand2的值按位逻辑“异或”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。 指令举例如下: TEQ R0,R ;比较R0与R1是否相等 ;(不影响V位和C位) TEQ指令与EORS指令的区别在于TEQ指令不保存运算结果。使用TEQ进行相等测试时,常与EQ、NE条件码配合使用。当两个数据相等时,EQ有效;否则NE有效。

93 3.3.3 分支指令 概述 在ARM中有两种方式可以实现程序的跳转:
分支指令 概述 在ARM中有两种方式可以实现程序的跳转: 一种是使用分支转移指令直接跳转; 另一种则是直接向PC寄存器赋值来实现跳转。 ARM的分支转移指令,可以从当前指令向前或向后的32MB的地址空间跳转,根据完成的功能它可以分为以下4种 : B 分支指令 BL 带链接的分支指令 BX 带状态切换的分支指令 BLX 带链接和状态切换的分支指令

94 1、B——转移指令 指令格式如下: B{cond} label B指令跳转到指定的地址执行程序。 指令举例如下: B WAITA ;跳转到WAITA标号处 B 0x ;跳转到绝对地址0x1234处 转移指令B限制在当前指令的±32 MB的范围内。

95 例子: 无条件跳转: B label …… label …… 执行10次循环: MOV R0, #10 LOOP
SUBS R0,R0, #1 BNE LOOP

96 BL指令先将下一条指令的地址拷贝到LR 链接寄存器中,然后跳转到指定地址运行程序。
指令格式如下: BL{cond} label BL指令先将下一条指令的地址拷贝到LR 链接寄存器中,然后跳转到指定地址运行程序。 指令举例如下: BL SUB ;LR下条指令地址 ;转至子程序SUB1处 SUB1 … MOV PC, LR ;子程序返回 注意:转移地址限制在当前指令的±32 MB的范围内。BL指令用于子程序调用。

97 例子:根据不同的条件,执行不同的子程序。
CMP R1, #5 BLLT ADD11 ;有符号数 < BLGE SUB22 ;有符号数 ≧ ADD11 SUB22 注:如果R1<5,只有ADD11不改变条件码,本例才能正常工作。

98 例子: BL SUB1 …… SUB1 STMFD R13!,{R0-R3,R14} BL SUB2 SUB2 ……

99 3、BX——带状态切换的转移指令 指令格式如下: BX{cond} Rm BX指令跳转到Rm指定的地址执行程序。
若Rm的位[0]为1,则跳转时自动将CPSR中的标志T置位,即把目标地址的代码解释为Thumb代码; 若Rm的位[0]为0,则跳转时自动将CPSR中的标志T复位,即把目标地址的代码解释为ARM代码。

100 指令举例如下: ADRL R0,ThumbFun+1 ;中等范围的地址读取伪指令 BX R0 ;跳转到R0指定的地址,并 ThumbFun
…….. ThumbFun

101 4、BLX —带链接和状态切换的转移指令 指令格式如下: BLX <target address>
BLX指令先将下一条指令的地址拷贝到R14 (即LR)连接寄存器中,然后跳转到指定地址处执行程序。(只有V5T及以上体系 支持BLX) 转移地址限制在当前指令的±32MB的范围内。

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

103 ARM的协处理器指令功能:(1)ARM处理器初始化ARM协处理器的数据处理操作;(2)在ARM处理器的寄存器和协处理器的寄存器之间传送数据;(3)在ARM协处理器的寄存器和存储器之间传送数据。
— CDP 协处理器数操作指令 coprocessor — LDC 协处理器数据加载指令 — STC 协处理器数据存储指令 — MCR ARM处理器寄存器到协处理器寄存器的数据传送指令 — MRC 协处理器寄存器到ARM处理器寄存器的数据传送指令

104 一、 CDP——协处理器数据操作指令 ARM处理器通过CDP指令通知ARM协处理器执行特定的操作。协处理器数据操作完全是协处理器内部的操作,用于初始化ARM协处理器,完成协处理器寄存器的状态改变。 指令格式如下: CDP{<cond>} <CP#>,<Cop1>,CRd,CRn,CRm {,<Cop2>} 其中: CP# 指令操作的协处理器名。标准名为pn,n为0~15。 Cop1 协处理器的特定操作码。 CRd 作为目标寄存器的协处理器寄存器。 CRn 存放第1个操作数的协处理器寄存器。 CRm 存放第2个操作数的协处理器寄存器。 Cop2 可选的协处理器特定操作码。

105 指令举例如下: CDP p7,0,c0,c2,c3,0 指令特点: ;协处理器7执行操作码1为0和 ;可选操作码2为0的操作。
;协处理器7执行操作码1为0和 ;可选操作码2为0的操作。 CDP p6,1,c3,c4,c5 ;协处理器6执行 ;操作码为1的操作 指令特点: 该操作由协处理器完成,即对命令参数的解释与协处理器有关,指令的使用取决于协处理器。 若协处理器不能成功地执行该操作,将产生未定义指令异常中断。

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

107 指令格式如下: LDC{cond}{L} <CP#>,CRd, <地址> 其中: L 可选后缀,指明是长整数传送。 CP# 指令操作的协处理器名。标准名为pn,n为0~15。 CRd 作为目标寄存的协处理器寄存器。 <地址> 指定的内存地址。 指令举例如下: LDC p5,c2,[R2,#4] ;读取R2+4指向的内存单元的数据,传送到协处理器p5的c2寄存器中。 LDC p6,c2,[R1] ;读取R1指向的内存单元的数据,传送到协处理器p6的c2寄存器中。

108 2、STC——协处理器数据存入指令 将协处理器的寄存器数据存入到某一连续的内存单元中,由协处理器来控制写入的字数。
若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 指令格式如下: STC{cond}{L} CP#,CRd,<地址> 其中格式说明同 LDC 指令。 指令举例如下: STC p5,c1,[R0] STC p5,c1,[R0,#0x04]

109 MCR{cond} CP# , Cop1, Rd, CRn, CRm{, <Cop2>}
三、MCR/MRC——ARM寄存器与 协处理器寄存器的数据传送指令 1、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。

110 2、MRC——协处理器寄存器 到ARM寄存器的数据传送指令
指令格式如下: MRC{cond} CP# , Cop1, Rd,CRn,CRm{, <Cop2>} 其中格式说明同 CDP 指令。 指令举例如下: MRC p5,2,R2,c3,c2

111 3.3.5 杂项指令 主要由两种类型指令组成,程序状态寄存器操作指令、中断操作指令,一共有5条指令。 状态寄存器操作指令:
杂项指令 主要由两种类型指令组成,程序状态寄存器操作指令、中断操作指令,一共有5条指令。 状态寄存器操作指令: MRS:读程序状态寄存器指令 MSR:写程序状态寄存器指令 异常中断操作指令: SWI: 软件中断指令 BKPT:断点指令(v5T体系) CLZ: 前导0计数(v5T体系)

112 一、程序状态寄存器处理指令 1、MRS——读状态寄存器指令
ARM指令中有两条指令,用于在状态寄存器和通用寄存器之间传送数据。修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。 1、MRS——读状态寄存器指令 指令格式如下: MRS{cond} Rd,psr ; Rd  psr 把状态寄存器psr(CPSR或SPSR)的内容传送到目标寄存器中。 其中: Rd —— 目标寄存器。Rd不允许为R15。 psr —— CPSR或SPSR。 注意:在ARM处理器中,只有MRS指令可以将状态寄存器CPSR或SPSR读出到通用寄存器中。

113 ARM状态寄存器的格式 1、条件码标志位(保存ALU中的当前操作信息) N:正负号/大小 标志位 Z:零标志位 C:进位/借位/移出位
0表示:正数/大于;1表示:负数/小于 Z:零标志位 0表示:结果不为零;1表示:结果为零 C:进位/借位/移出位 0表示:未进位/借位/移出0;1表示:进位/未借位/移出1 V:溢出标志位 0表示:结果未溢出;1表示:结果溢出 Q:DSP指令溢出标志位(用于v5以上E系列) 31 30 29 28 27 26…8 7 6 5 4 3 2 1 N Z C V Q (保留) I F T M4 M3 M2 M1 M0

114 MRS与MSR指令的应用目的: 指令举例如下: MRS R1,CPSR ; R1 CPSR MRS R2,SPSR ; R2  SPSR
获得CPSR或SPSR的状态: 用MRS指令读取CPSR,可用来判断ALU的状态标志,或IRQ、FIQ中断是否允许等。 用MRS指令在异常处理程序中,读SPSR可知道进行异常前的处理器状态等。 CPSR或SPSR进行修改: MRS与MSR配合使用,实现CPSR或SPSR寄存器的读—修改—写操作,可用来进行处理器模式切换、允许/禁止IRQ/FIQ中断等设置。

115 在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR。 指令格式如下: MSR{cond} psr_fields,Rm
MSR{cond} psr_fields,#immed MSR{cond} psr_fields,Rm 其中: psr: CPSR或SPSR。 immed: 要传送到状态寄存器指定域的8位立即数。 Rm: 要传送到状态寄存器指定域的数据的源寄 存器。

116 程序状态寄存器分域图 N Z C V Q 保留 f(标志位域) s(状态域) 保留 I F T mode x(扩展域) c(控制域)
fields 指定传送的区域。fields可以是以下的一种或多种(字母必须为小写): c 控制域 (psr[7…0]); x 扩展域(psr[15…8]);(暂未用) s 状态域 (psr[23…16]);(暂未用) f 标志位域 (psr[31…24])。 程序状态寄存器分域图 N Z C V Q 保留 f(标志位域) s(状态域) 保留 I F T mode x(扩展域) c(控制域)

117 指令举例如下: CPSR的读—修改—写操作举例如下:
MSR CPSR_f,#0xf0 ;CPSR[31:28]=0xf(0b1111) ;即N,Z,C,V均被置1。 修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。 CPSR的读—修改—写操作举例如下: 例1:设置进位位C MRS R0, CPSR ;R0CPSR ORR R0,R0,#0x ;置1进位位C MSR CPSR_f, R0 ;CPSR_fR0[31:24] 例2:从管理模式切换到IRQ模式 MRS R0, CPSR ;R0CPSR BIC R0,R0,#0x1f ;低5位清零 ORR R0,R0,#0x ;设置为IRQ模式 MSR CPSR_c, R0 ;传送回CPSR

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

119 第7次到此 例:堆栈初始化 INITSTACK ;堆栈初始化子程序 MOV R0,LR ;保存返回地址 MRS R1,CPSR ;保存CPSR原值 MSR CPSR_c,#0xD3 ;切换到管理模式 …… ;设置堆栈大小等 LDR SP,StackSvc ;设置堆栈指针 MSR CPSR_c,#0xD2 ;切换到中断模式 LDR SP,StackIrq ;设置堆栈指针 …… ;对其它模式设置 MSR CPSR_c,R1 ;恢复CPU原模式 MOV PC,R0 ;子程序返回

120 二、异常中断产生指令 异常中断指令可以分为以下几种: SWI: 软件中断指令 BKPT:断点指令(v5T及以上体系)
CLZ: 前导0计数(v5T及以上体系)

121 SWI {<cond>} <24位立即数> 说明:
软件中断指令SWI产生软件异常中断,用来实现用户模式到特权模式的切换。用于在用户模式下对操作系统中特权模式的程序的调用;它将处理器置于管理(_svc)模式,中断矢量地址为0x08。 指令格式如下: SWI {<cond>} <24位立即数> 说明: 主要用于用户程序调用操作系统的API。 参数传递通常有两种方法: 指令中的24bit立即数指定API号,其它参数通过寄存器传递。 忽略指令中的24bit立即数,r0指定API号,其它参数通过其它寄存器传递。

122 SWI指令举例: 软中断号在指令中,不传递其它参数 SWI ;中断号为10 SWI 0x ;中断号为0x123456 软中断号在指令中,其它参数在寄存器中传递 MOV R0,#34 ;准备参数 SWI ;调用12号软中断 不用指令中的立即数,软中断号和其它参数都在寄存器中传递 MOV R0,#12 ;准备中断号 MOV R1,#34 ;准备参数 SWI 0 ;进入软中断

123 SWI程序举例: T_bit EQU 0x20 ;用于测试Thumb标志位(第5位) SWI_handler STMFD SP!,{R0-R3,R12,LR} MRS R0,SPSR ;保存中断前的CPSR值 STMFD SP!,{R0} ;到堆栈中 TST R0,#T_bit ;测试T位标志 LDRNEH R0,[LR,# -2] ;读取16位的SWI指令码 BICNE R0,R0,#0xFF00 ;获取SWI中的中断号 LDREQ R0,[LR,# -4] ;读取32的SWI指令码 BICEQ R0,R0,#0xFF000000;获取SWI中的中断号 …… ;转去处理相应的软中断 LDMFD SP!,{R0-R3,R12,PC} ;中断返回,包括恢复原CPSR值

124 断点中断指令BKPT用于产生软件断点,供调试程序用。v5T及以上体系使用。 指令格式如下: BKPT { immed_16}
断点指令用于软件调试;它使处理器停止执行正常指令而进入相应的调试程序。

125 CLZ{<cond>} Rd, Rm
前导0计数指令CLZ 对Rm中的前导0的个数进行计数,结果放到Rd中。 v5T及以上体系使用。 指令格式: CLZ{<cond>} Rd, Rm 举例如下: MOV R2, #0X17C00 ;R2=0b CLZ R3, R ;R3=15

126 3.3.6 例 题 一、算数逻辑运算指令的应用 例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)

127 例2:64位数据运算 假设R0和R1存放一个64位数据,R0中存放数据的低32位;R2和R3中存放另一个64位数据,R2中存放数据的低32位。对这两个64位数进行加、减和比较运算。(R1,R0)、(R3,R2) ①两个64位数据的加法运算,结果保存到R0和R1中。 ADDS R0,R0,R2 ;低32位相加,设置CPSR的C标志位。 ADC R1,R1,R ;高32位的带位相加

128 ②两个64位数据的减法运算,结果保存到R0和R1中。
SUBS R0,R0,R2 ;低32位相减,设置CPSR的C标志位。 SBC R1,R1,R3 ;高32位的带位相减 ③两个64位数据的比较操作,并设置CPSR中的条件标志位。 CMP R1,R3 ;比较高32位 CMPEQ R0,R2 ;如果高32位相等,比较低32位

129 例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,#OxFF ;R1=A^C,0,C^A,D^B MOV R0,R0,ROR # ;R0=D,A,B,C EOR RO,RO,R1,LSR # ;R0=D,C,B,A ;R0=D,A,B,C异或R1=0,A^C,0,C^A

130 二、跳转指令的应用 例1:子程序的调用 BL指令在执行跳转操作的同时保存下一条指令的地址,用于从被调用的子程序中返回。 ……
BL function ;调用子程序function …… ;子程序结束后,程序将返回到这里执行 function ;子程序的程序体 MOV PC,LR ;子程序中的返回语句

131 例2:条件执行 实现类似于C语言中的if-else功能的代码段。下例的功能为求最大公约数。 C语言代码为:
int gcd (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中存放最大公约数。 gcd CMP R0,R ;比较a和b的大小 SUBGT R0,R0,R1 ;if(a>b) a=a-b SUBLT R1,R1,R0 ;if(b>a) b=b-a BNE gcd ;if(a!=b)跳转到gcd继续执行 MOV PC,LR ;子程序结束,返回

132 循环结构 MOV R1,#10 LOOP …… ;循环体 SUB R1,R1,#1 BNE LOOP ……

133 例3:循环语句 将内存中从0x400800开始的100个字数据相加,其结果存于R3、R2中(R3中为高32位)。
LDR R0,=0x400800 MOV R1,# ;初始化循环次数 MOV R2,#0 MOV R3,#0 loop ;循环体 LDR R4,[R0],#4 ADDS R2,R2,R4 ADC R3,R3,#0或者ADDCS R3,R3,#1 SUBS R1,R1,#1 ;循环计数器减1,设置条件标志 BNE loop ;循环计数器不为0,跳到loop继续执行 …… ;循环计数器为0,程序继续执行

134 例4:链表操作中的条件码应用 在链表中搜索与某一数据相等的元素。
链表的每个元素包括两个字,第1个字中包含一个字节数据;第2个字中包含指向下一个链表元素的指针,当这个指针为0时表示链表结束。 代码执行前R0指向链表的头元素,R1中存放将要搜索的数据;代码执行后R0指向第1个匹配的元素,或者当没有匹配元素时,R0为0。 SEARCH CMP R0,# ;R0指针是否为空 LDRNEB R2,[R0] ;读取当前元素中的字节数据 CMPNE R1,R ;判断数据是否为搜索的数据 LDRNE R0,[R0,#4] ;如果不是,指针R0指向下一个元素 BNE SEARCH ;跳转到search执行 MOV PC,LR ;搜索完成,程序返回

135 SEARCH CMP R0,# ;R0指针是否为空 LDRNEB R2,[R0] ;读取当前元素中的字节数据 CMPNE R1,R ;判断数据是否为搜索的数据 LDRNE R0,[R0,#4] ;如果不是,指针R0指向下一 ;个元素 BNE SEARCH ;跳转到search执行 MOV PC,LR ;搜索完成,程序返回

136 3.4 Thumb指令集 (在本章最后)

137 3.5 ARM汇编伪指令和伪操作 主要内容 3.5.1 概念 3.5.2 ARM汇编伪指令 3.5.3 ARM汇编伪操作
概念 ARM汇编伪指令 ARM汇编伪操作 一、符号定义伪操作 二、 数据定义伪操作 三、汇编控制伪操作 四、其他伪操作 ARM汇编宏指令 ADS编译环境下的伪操作

138 3.5.1 伪指令、伪操作和宏指令概念 伪指令——是汇编语言程序里的特殊指令助记符,在汇编时被合适的机器指令替代。
伪指令、伪操作和宏指令概念 伪指令——是汇编语言程序里的特殊指令助记符,在汇编时被合适的机器指令替代。 伪操作——为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编过程起作用,不参与程序运行。 宏指令——通过伪操作定义的一段独立的代码。在调用它时将宏体插入到源程序中。也就是常说的宏。 说明:所有的伪指令、伪操作和宏指令,均与具体的开发工具中的编译器有关,当前主要采用ARM公司的“ADS/SDT IDE”开发工具,所以后面的讨论,均是基于ARM公司的开发工具。

139 ARM汇编伪指令 ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替。ARM伪指令有四条,分别是: ADR:小范围的地址读取伪指令。 ADRL:中等范围的地址读取伪指令。 LDR:大范围的地址读取伪指令。 NOP:空操作伪指令。

140 一、ADR——小范围的地址读取 ADR伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。
ADR伪指令功能的实现方法:在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现此ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 语法格式: ADR{cond} register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围是参考P212

141 …… 例1: …… ADD R1,PC,#0x3C (0x20) ADR R1,Delay Delay MOV R0,R14
编译后的反汇编代码: …… ADD R1,PC,#0x3C MOV R0,R14 例1: …… (0x20) ADR R1,Delay Delay (0x64) MOV R0,R14 使用ADR将程序标号Delay所表示的地址存入R1。 PC+0x3C =0x20+0x08+0x3C =0x64

142 例2:查表 ADR R0,D_TAB ;加载转换表地址 LDRB R1,[R0,R2] ;使用R2作为参数,进行查表 …… D_TAB DCB 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92

143 二、ADRL——中等范围的地址读取 ADRL伪指令功能:将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址。 ADRL伪指令功能实现方法:在汇编编译器编译源程序时,ADRL被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 语法格式: ADRL{cond} register,expr 其中: register:加载的目标寄存器。 expr:地址表达式。取值范围参考P212

144 …… 例3: …… ADD R1,PC,#0x3C (0x20) ADRL R1,Delay ADD R1,R1,#0 Delay
编译后的反汇编代码: …… ADD R1,PC,#0x3C ADD R1,R1,#0 MOV R0,R14 例3: …… (0x20) ADRL R1,Delay Delay (0x64) MOV R0,R14 使用ADRL将程序标号Delay所表示的地址存入R1。 ADRL伪指令被汇编成两条指令,尽管第2条指令并没有意义。

145 三、LDR ——大范围的地址读取 LDR伪指令功能:用于加载32位立即数或一个地址值到指定的寄存器。
若加载的常数未超过MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令; 否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 语法格式: LDR{cond} register,=expr 其中: Register:加载的目标寄存器。 expr:32位常量或地址表达式。

146 例4: …… (0x060) LDR R1,=Delay Delay (0x102) MOV R0,R14 编译后的反汇编代码: ……
LDR R1,stack Delay MOV R0,R14 LTORG stack DCD 0x102 使用LDR将程序标号Delay所表示的地址存入R1。 LDR伪指令被汇编成一条LDR指令,并在文字池中定义一个常量,该常量为标号Delay的地址。

147 注意: 从指令位置到文字池的偏移量必须小于4KB。 与ARM指令的LDR的区别:伪指令LDR的参数有“=”号。

148 四、NOP——空操作伪指令 NOP伪指令功能实现方法:在汇编时将被替代成ARM中的空操作,比如可能是“MOV R0,R0”指令等。
第8次到此 四、NOP——空操作伪指令 NOP伪指令功能实现方法:在汇编时将被替代成ARM中的空操作,比如可能是“MOV R0,R0”指令等。 用途:NOP可用于延时操作。 语法格式: NOP 例:延时子程序 Delay NOP ;空操作 NOP SUBS R1,R1,#1 ;循环次数减1 BNE Delay MOV PC,LR

149 3.5.3 ARM汇编伪操作 ADS编译环境下的伪操作可分为以下几类: 符号定义(Symbol Definition)伪操作
数据定义(Data Definition)伪操作 汇编控制(Assembly Control)伪操作 其它(Miscellaneous)伪操作

150 一、符号定义伪操作 GBLA,GBLL,GBLS:声明全局变量。 LCLA,LCLL,LCLS:声明局部变量。
SETA,SETL,SETS:给变量赋值。 RLIST:为通用寄存器列表定义名称。 Test3 SETA 0xaa ;将该变量赋值为0xaa

151 二、数据定义伪操作 LTORG:声明一个数据缓冲池的开始 SPACE:分配一块字节内存单元,并用0初始化
DCB:分配一段字节内存单元,并初始化 DCD、DCDU:分配一段字内存单元,并初始化 MAP:定义一个结构化的内存表的首地址 FIELD:定义结构化内存表中的一个数据域 MAP 0x100, R0 ;定义结构化内存表首地址的值为0x100+R0 A FIELD 16 ;定义A的长度为16字节,位置为0x110+R0 LTORG ;定义数据缓冲池&0x8000 Data SPACE ;从当前位置开始分配4200字节的内存单元, ;并初始化为0。

152 用于声明一个数据缓冲池(文字池)的开始。 语法格式:
1、 LTORG 用于声明一个数据缓冲池(文字池)的开始。 语法格式: LTORG 例:start BL func ;(146页) …… func LDR R1,=0x ;子程序 MOV PC,LR ;子程序返回 LTORG ;定义数据缓冲池&0x8000 Data SPACE ;从当前位置开始分配4200字节的内 存单元,并初始化为0。 END 默认数据缓冲池为空

153 注意: LTORG伪操作通常放在无条件跳转指令之后,或者子程序返回指令之后,这样处理器不会错误地将数据缓冲池中的数据当作指令来执行。
通常ARM汇编编译器把数据缓冲池放在代码段的最后面,即下一个代码段开始之前,或者END伪操作之前。

154 用于定义并且初始化一个或者多个字节的内存区域。 语法格式:
3、DCB——也可以用符号”=”表示 用于定义并且初始化一个或者多个字节的内存区域。 语法格式: {label} DCB expr{,expr}…… 或 {label} = expr{,expr} 其中expr表示: -128到255之间的一个数值常量或者表达式。 一个字符串。 注意:当DCB后面紧跟一个指令时,可能需要使用ALIGN确保指令是字对齐的。

155 short DCB 1 ;为short分配了一个 ;字节,并初始化为1。 string DCB “string”,0 ;构造一个以0
例: short DCB ;为short分配了一个 ;字节,并初始化为1。 string DCB “string”,0 ;构造一个以0 ;结尾的字符串

156 用于分配一段字对齐的内存单元,并初始化。 DCD也可以用符号”&”表示 语法格式:
4、DCD、DCDU分配一段字内存单元 (1)DCD ——分配一段字对齐的内存单元 用于分配一段字对齐的内存单元,并初始化。 DCD也可以用符号”&”表示 语法格式: {label} DCD expr{,expr}…… 或 {label} & expr{,expr}…… expression 其中: expr :数字表达式或程序中的标号。 注意:DCD伪操作可能在分配的第一个内存单元前插入填补字节以保证分配的内存是字对齐的。

157 例: data1 DCD 2,4,6 ;为data1分配三个字,内容初始化为2,4,6 data2 DCD label+4 ;初始化data2为label+4对应的地址 (2)DCDU ——分配一段字非严格对齐的内存单元 DCDU与DCD的不同之处在于DCDU分配的内存单元并不严格字对齐。

158 三、汇编控制伪操作 IF,ELSE及ENDIF:有条件选择汇编 WHILE及WEND:有条件循环(重复)汇编
MACRO,MEND及MEXIT:宏定义汇编

159 四、其它伪操作 1、AREA:定义一个代码段或数据段 2、CODE16、CODE32:告诉编译器后面的指令序列位数
3、ENTRY:指定程序的入口点 4、ALIGN:将当前的位置以某种形式对齐 ALIGN或 5、END:源程序结尾 ALIGN n:以字或n字节对齐 6、EQU:为数字常量、基于寄存器的值和程序中的标号定义一个字符名称。 7、EXPORT、GLOBAL:声明源文件中的符号可以被其他源文件引用 8、IMPORT、EXTERN:声明某符号是在其他源文件中定义的 9、GET、INCLUDE:将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 10、INCBIN:将一个文件包含到当前源文件中,而被包含的文件不进行汇编处理

160 AREA sectionname{,attr} {,attr}…attribute 其中:
用于定义一个代码段或是数据段。 语法格式: AREA sectionname{,attr} {,attr}…attribute 其中: sectionname:为所定义的段的名称。 attr:该段的属性。具有的属性为: CODE:定义代码段。 DATA:定义数据段。 READONLY:指定本段为只读,代码段的默认属性。 READWRITE:指定本段为可读可写,数据段的默认属性。

161 注意:一个大的程序可包含多个代码段和数据段。一个汇编程序至少包含一个代码段。
ALIGN:指定段的对齐方式为2expression。expression的取值为0~31。 COMMON:指定一个通用段。该段不包含任何用户代码和数据。 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0。 注意:一个大的程序可包含多个代码段和数据段。一个汇编程序至少包含一个代码段。

162 2、CODE16和CODE32 CODE16告诉汇编编译器后面的指令序列为16位的Thumb指令。
CODE32告诉汇编编译器后面的指令序列为32位的ARM指令。 语法格式: CODE16 CODE32 注意:CODE16和CODE32只是告诉编译器后面指令的类型,该伪操作本身不进行程序状态的切换。

163 AREA ChangeState, CODE, READONLY ENTRY CODE32 ;下面为32位ARM指令
例: AREA ChangeState, CODE, READONLY ENTRY CODE ;下面为32位ARM指令 LDR R0,=start+1 BX R0 …… CODE ;下面为16位Thumb指令 start MOV R1,#10 ……. END ;切换到Thumb状态,并跳转到start处执行

164 3、ENTRY 指定程序的入口点。 语法格式: ENTRY 注意: 一个程序(可包含多个源文件)中至少要有一个ENTRY(可以有多个ENTRY),但一个源文件中最多只能有一个ENTRY(可以没有ENTRY)

165 ALIGN伪操作通过填充0将当前的位置以某种形式对齐。 语法格式: ALIGN {expr{,offset}} 其中:
Offset:偏移量,可以为常数或数值表达式。不指定offset表示将当前位置对齐到以expr为单位的起始位置。

166 例1: short DCB ;本操作使字对齐被破坏 ALIGN ;重新使其为字对齐 MOV R0,1 例2: ALIGN ;当前位置以2个字的方式对齐

167 5、END END伪操作告诉编译器已经到了源程序结尾。 语法格式: END 注意:    每一个汇编源程序都必须包含END伪操作,以表明本源程序的结束。

168 EQU伪操作为数字常量、基于寄存器的值和程序中的标号定义一个字符名称。 语法格式: name EQU expr{,type} 其中:
name:为expr定义的字符名称。 expr:基于寄存器的地址值、程序中的标号、32位的地址常量或者32位的常量。表达式,为常量。 type:当expr为32位常量时,可以使用type指示expr的数据的类型。取值为: CODE32 CODE16 DATA

169 ;定义abcd符号的值为(label+16) abcd EQU 0x1c,CODE32
例: abcd EQU ;定义abcd符号的值为2 abcd EQU label+16 ;定义abcd符号的值为(label+16) abcd EQU 0x1c,CODE32 ;定义abcd符号的值为绝对地址 ;值0x1c,而且此处为ARM指令

170 7、EXPORT及GLOBAL 声明一个源文件中的符号,使此符号可以被其他源文件引用。 语法格式:
EXPORT/GLOBAL symbol {[weak]} 其中: symbol:声明的符号的名称。(区分大小写) [weak]:声明其他同名符号优先于本符号被引用。 例: AREA example,CODE,READONLY EXPORT DoAdd DoAdd ADD R0,R0,R1

171 IMPORT symbol{[weak]} EXTERN symbol{[weak]} 其中:
8、IMPORT及EXTERN 声明一个符号是在其他源文件中定义的。 语法格式: IMPORT symbol{[weak]} EXTERN symbol{[weak]} 其中: symbol:声明的符号的名称。

172 [weak]: 当没有指定此项时,如果symbol在所有的源文件中都没有被定义,则连接器会报告错误。
如果该符号被B或者BL指令引用,则该符号被设置成下一条指令的地址,该B或BL指令相当于一条NOP指令。 其他情况下此符号被设置成0。

173 9、GET及INCLUDE 将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。 指令格式: GET filename
INCLUDE filename 其中: filename:包含的源文件名,可以使用路径信息(可包含空格)。 例:GET d:\arm\file.s

174 10、INCBIN 将一个文件包含到当前源文件中,而被包含的文件不进行汇编处理 指令格式: INCBIN filename 其中:
适用情况:通常使用此伪操作将一个可执行文件或者任意数据包含到当前文件中。 例:INCBIN d:\arm\file.txt

175 例:编写一具有完整汇编格式的程序,实现冒泡法排序功能。设无符号字数据存放在从0x400004开始的区域,字数据的数目字存放在0x400000中。
AREA SORT,CODE,READONLY ENTRY START MOV R1,#0x400000 LP SUBS R1,R1,#1 BEQ EXIT MOV R7,R1 LDR R0,=0x400004 LP1 LDR R2,[R0],#4 LDR R3,[R0] CMP R2,R3 STRLO R3,[R0, # -4] STRLO R2,[R0] SUBS R7,R7,#1 BNE LP1 B LP EXIT END

176 用ARM汇编语言编写的ARM程序或Thumb程序。
源程序文件 文件名 说 明 汇编程序文件 *.S 用ARM汇编语言编写的ARM程序或Thumb程序。 C程序文件 *.C 用C语言编写的程序代码。 头文件 *.H 为了简化源程序,把程序中常用到的常量命名、宏定义、数据结构定义等等单独放在一个文件中,一般称为头文件。

177 ARM汇编与C的混合编程 内嵌汇编 语法: _asm { _inline void enable_IRQ(viod) { int tmp;
指令[;指令] /*注释*/ [;指令] } _inline void enable_IRQ(viod) { int tmp; _asm MRS tmp,CPSR BIC tmp,tmp,#0x80 MSR CPSR_c,tmp }

178 习 题 1 ARM指令中的第二操作数“operand2”有哪些具体形式?
习 题 1 ARM指令中的第二操作数“operand2”有哪些具体形式? 2 对于ARM的变址寻址方式,有基地址和偏移地址两部分组成。(1)基地址可以是哪些寄存器?(2)偏移地址可以有哪些形式?(3)总地址的计算方法有哪些?怎么表示?(4)变址寻址应用于哪些指令? 3 存储器从0x400000开始的100个单元中存放着ASCII码,编写程序,将其所有的小写字母转换成大写字母,对其它的ASCII码不做变换。

179 4 编写程序,比较存储器中0x400000和0x400004两无符号字数据的大小,并且将比较结果存于0x4008的字中,若两数相等其结果记为0,若前者大于后者其结果记为1,若前者小于后者其结果记为-1。 5 将存储器中0x400000开始的200字节的数据,传送到0x400800开始的区域。 6 编写一程序,查找存储器从0x400000开始的100个字中为0的数目,将其结果存到0x400190中。 7 编写一程序,存储器中从0x400200开始有一个64位数。(1)将取反,再存回原处;(2)求其补码,存放到0x400208处 。

180 作 业: 1、2、3、4、7、8 8 编写一简单ARM汇编程序段,实现1+2+…+100的运算。
9 编写一具有完整汇编格式的程序,实现32位二进制数转换成11位压缩的BCD码的十进制数。 设原数据存放在从0x400000处,转换后存放在0x400004开始的地方。 10 假定有一个25字的数组,编译器分别用R0、R1分配变量x和y,若数组的基地址放在R2中,使用后变址形式翻译:x=array[5]+y。 11 使用汇编完成系列C的数组赋值: For(i=0;i<=10;i++) a[i]=b[j]+c; 作 业: 1、2、3、4、7、8

181

182 3.4 Thumb指令集 (一)Thumb指令集特点 由于16位的限制,移位操作变成单独指令。
Thumb指令集是ARM指令集压缩形式的子集,所有Thumb指令均有对应的ARM指令。 采用16位二进制编码,代码密度小。 执行Thumb指令时,先动态解压缩,然后作为标准的ARM指令执行。 如何区分指令流取决于CPSR的第5位(位T)。 大多数Thumb数据处理指令采用2个操作数格式。 由于16位的限制,移位操作变成单独指令。

183 Thumb指令集没有协处理器指令、单寄存器交换指令、乘加指令、64位乘法指令以及程序状态寄存器处理指令,而且指令的第2操作数受到限制。
Thumb是一个不完整的体系结构,不能指望处理器只执行Thumb代码而不支持ARM指令集。

184 (二)状态切换 1、ARM状态进入Thumb状态的方法
执行带状态切换的转移指令BX。若BX指令指定的寄存器的最低位为1,则将T置位,并将程序计数器切换为寄存器其他位给出的地址。 BX R0 ;若R0最低位为1,则转入Thumb状态

185 异常返回也可以将微处理器从ARM状态转换为Thumb状态。通常这种指令用于返回到进入异常前所执行的指令流,而不是特地用于转换到Thumb模式。
MOV PC,LR ;当返回地址保存在LR时 STMFD SP!,{<registers>,LR} ;当返回地址保存在堆栈时, …… ;进入异常后将R14入栈, …… ;假设异常前执行的是Thumb指令,PC保存于LR中 LDMFD SP!,{<registers>,PC} ;返回指令

186 2、 Thumb状态进入ARM状态的方法 执行Thumb指令中的交换转移BX指令可以显式地返回到ARM指令流。 利用异常进入ARM指令流。

187 (三)Thumb指令寄存器的使用 对低(Lo)8个通用寄存器R0~R7具有全部访问权限,可以被任意指令访问。
SP(r13) LR(r14) PC(r15) 对低(Lo)8个通用寄存器R0~R7具有全部访问权限,可以被任意指令访问。 寄存器R8~R12的访问受到限制,这些寄存器只能通过MOV、ADD和CMP访问。 对寄存器R13~R15进行扩展以作特殊应用。 CPSR 间接访问 ( CMP 和数据处理指令影响)。 SPSR 不能访问。 CPSR的条件标志位由算术和逻辑操作设置并控制条件转移。 Lo寄存器 Hi寄存器 CPSR 有阴影的寄存器访问时受到限制

188 Thumb-ARM相似处: Thumb-ARM差异处: Load/Store结构。
支持8位字节、16位半字和32位字数据类型,半字以两字节边界对准,字以4字节边界对准。 Thumb-ARM差异处: 大多数Thumb指令是无条件执行的,所有ARM指令都是条件执行的。 许多Thumb数据处理指令采用2个操作数格式(目的寄存器与一个源寄存器相同),ARM数据处理指令大多采用3个操作数格式。如 ADD R0,R1 由于采用高密度编码,Thumb指令格式没有ARM指令格式规则。

189 (四)Thumb转移指令 Thumb转移指令用于: 向后转移形成循环; 条件结构向前转移; 转向子程序;
处理器从Thumb状态切换到ARM状态。 程序相对转移,特别是条件转移与在ARM状态下相比,在范围上有更多的限制,转向子程序只能是无条件转移。 Thumb转移指令包括:B;BL;BX;BLX

190 格式1:B <条件码> <Label> <Lable>:程序相对偏移表达式,多为同一代码块中的地址标号。
①B指令——目标为Thumb代码 格式1:B <条件码> <Label> <Lable>:程序相对偏移表达式,多为同一代码块中的地址标号。 编码结构:-256~+256 格式2:B <Label> 编码结构:±2KB Thumb指令集中唯一可以条件执行的指令。

191 ②BL指令——目标为Thumb代码 格式:BL <Label> 编码结构: ±4M Why ±4M ?
(H=0) LR< PC+(偏移量左移12位后符号扩展至32位); (H=1) PC< LR+(偏移量左移1位); 同时把下一条指令的地址写入LR中。

192 ③BX指令——目标为Thumb代码或ARM代码 格式: BX Rm 编码结构:
15 8 0 0 0 3 Rm 5 2 6 7 H 其中:Rm装有目的地址的ARM寄存器。Rm的位[0]不用于地址部分。 若Rm的位[0]清零,则: — 位[1]也必须清零; — 指令清零CPSR中的标志T,目的地址的代码被解释为ARM代码。 若Rm的位[0]置1,则: —目标地址的代码仍为Thumb代码。

193 格式1:BLX <Label> ——目标为ARM代码
15 11 10 10位偏移量 12 H 1 格式2:BLX Rm——目标为ARM代码或Thumb代码 BLX指令执行时: 拷贝下一条指令的地址到LR寄存器。 引起处理器转移到label或Rm存储的地址。 如果Rm的位[0]清0,或使用格式1,则指令集切换到ARM状态。

194 (五)堆栈指令 功能:低寄存器和可选的LR进栈。低寄存器和可选的PC出栈。
格式: POP { <Reglist> { , PC}} PUSH { <Reglist> { , LR}} 其中:Reglist 低寄存器范围的、用逗号隔开的列表。 注释: 1.Thumb堆栈是满递减堆栈,向下增长,且SP指向堆栈的最后入口。 2.寄存器以数字顺序存储在堆栈中。最低数字的寄存器其地址最低。 3.POP{reglist,PC}这条指令引起处理器转移到从堆栈弹出给PC的地址。这通常是从子程序返回,其中LR在子程序开头压进堆栈。 4.指令采用基址回写,因此基址寄存器不应出现在 寄存器列表中。

195 条件码标志 这些指令不影响条件码标志 例: PUSH {R0,R4-R7} ;R0、R4~R7进栈 PUSH {R0,LR}
POP {R2,R5} POP {R0-R7,PC} ;出栈并从子程序返回

196 (六)寄存器读取和存储指令 单寄存器读取和存储 多寄存器读取和存储指令
Thumb单寄存器传送类指令是ARM单寄存器传送类指令的一个子集,和ARM有相同的指令格式。 多寄存器读取和存储指令 Thumb多寄存器传送类指令和ARM有相同的指令格式。

197 (七)移位和循环移位操作 ASR、LSL、LSR和ROR运算 功能:移位和循环移位操作。这些指令可使用寄存器中的值或立即数来表示偏移量。
格式1:<操作码> Rd , Rn , < #immed> <操作码>: ASR、LSL、LSR Rd: 立即数移位的目的寄存器。Rd必须在R0~R7范围内。 Rn: 立即数移位的源寄存器。Rn必须在R0~R7范围内。 < #immed>:立即数移位量。它是一个取值为整数的表达式。整数的范围如下: — <操作码>若是LSL,则为0~31; — 其它则为1~32。

198 格式2:<操作码> Rd , Rs 编码结构: 其中: <操作码>:ASR、LSL、LSR 、ROR。
15 Rd 3 Rs 5 2 6 9 Op 10 其中: <操作码>:ASR、LSL、LSR 、ROR。 Rd: 目的寄存器,它也是第1操作数寄存器。Rd必须在 R0~R7范围内。 Rs: 在寄存器控制移位中包含移位量的寄存器。Rs必须 在R0~R7范围内,只有Rs的最低有效字节可用作偏 移量。

199 条件标志位: 对于除ROR以外的所有指令,若移位量为32,则Rd清0,最后移出的位保留在标志C中,并根据结果影响N、Z标志位。若移位量大于32,则Rd和标志C均被清0,并根据结果影响N、Z标志位。 对于ROR指令,若移位量为32,则Rd不变且不影响标志位;若移位量大于或小于32时,则最后移出的位将存入到C中,并根据结果影响N、Z标志位。 任何情况都不影响标志V。

200 例: ASR R3,R5 LSR R0,R2,#6 LSR R5,R5,zyb LSL R0,R4,#0 ROR R2,R3
;将R4的内容放到R0中,除不影响标志位C和V外,同MOV R0,R4 ;R2中的值循环右移R3次后放入R2中。

201 (八)数据处理指令 除移位操作之外的数据处理指令,和ARM类似。

202

203

204

205

206

207


Download ppt "嵌入式系统讲义 第3章 ARM指令系统 周国运 2007.3."

Similar presentations


Ads by Google