Presentation is loading. Please wait.

Presentation is loading. Please wait.

C H A P T E R 4 ARM7指令集.

Similar presentations


Presentation on theme: "C H A P T E R 4 ARM7指令集."— Presentation transcript:

1 C H A P T E R 4 ARM7指令集

2 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集

3 ARM指令长度概述 ARM指令长度 指令集可以是以下任一种 ARM7TDMI 支持3种数据类型
32 bits 长 (ARM状态) 16 bits 长 (Thumb 状态) ARM7TDMI 支持3种数据类型 字节 (8-bit) 半字 (16-bit) 字 (32-bit) 字必须被排成4个字节边界对齐,半字必须被排列成2个字节边界对齐

4 ARM指令长度概述 向后兼容:新版本增加指令,并保持指令向后兼容; Load-store 结构*
只对存放在寄存器的数据进行处理 对于存储器中的数据,只能使用load/store指令进行存取

5 第4章 目录 1.ARM处理器寻址方式 2. ARM指令集

6 第4章 ARM7TDMI(-S)指令系统 简介 ARM处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制较为简单。ARM7TDMI(-S)具有32位ARM指令集和16位Thumb指令集,ARM指令集效率高,但是代码密度低;而Thumb指令集具有较高的代码密度,却仍然保持ARM的大多数性能上的优势,它是ARM指令集的子集。所有的ARM指令都是可以有条件执行的,而Thumb指令仅有一条指令具备条件执行功能。ARM程序和Thumb程序可相互调用,相互之间的状态切换开销几乎为零。

7 第4章 ARM7TDMI(-S)指令系统 ARM指令集与Thumb指令集的关系 Thumb指令集具有灵活、小巧的特点
ARM指令集支持ARM核所有的特性,具有高效、快速的特点

8 4.1 ARM处理器寻址方式 寻址方式分类 寻址方式是根据指令中给出的地址码字段来实现寻找真实操作数地址的方式。ARM处理器具有9种基本寻址方式。 1.寄存器寻址; 2.立即寻址; 3.寄存器移位寻址; 4.寄存器间接寻址; 5.基址寻址; 6.多寄存器寻址; 7.堆栈寻址; 8.块拷贝寻址; 9.相对寻址。

9 4.1 ARM处理器寻址方式 寻址方式分类——寄存器寻址
操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值来操作。寄存器寻址指令举例如下: MOV R1,R2 ;将R2的值存入R1 SUB R0,R1,R2 ;将R1的值减去R2的值,结果保存到R0 0xAA 0x55 R2 R1 0xAA MOV R1,R2

10 4.1 ARM处理器寻址方式 寻址方式分类——立即寻址
立即寻址指令中的操作码字段后面的地址码部分即是操作数本身,也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(这样的数称为立即数)。立即寻址指令举例如下: SUBS R0,R0,#1 ;R0减1,结果放入R0,并且影响标志位 MOV R0,#0xFF000 ;将立即数0xFF000装入R0寄存器 0x55 R0 MOV R0,#0xFF00 程序存储 从代码中获得数据 0xFF00 MOV R0,#0xFF00

11 4.1 ARM处理器寻址方式 寻址方式分类——寄存器移位寻址
MOV R0,R2,LSL #3 ;R2的值左移3位,结果放入R0, ;即是R0=R2×8 ANDS R1,R1,R2,LSL R3 ;R2的值左移R3位,然后和R1相 ;“与”操作,结果放入R1 0x55 R0 R2 0x01 逻辑左移3位 0x08 0x08 MOV R0,R2,LSL #3

12 4.1 ARM处理器寻址方式 寻址方式分类——寄存器间接寻址
寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。寄存器间接寻址指令举例如下: LDR R1,[R2] ;将R2指向的存储单元的数据读出 ;保存在R1中 SWP R1,R1,[R2] ;将寄存器R1的值和R2指定的存储 ;单元的内容交换 0x55 R0 R2 0x 0xAA 0xAA LDR R0,[R2]

13 4.1 ARM处理器寻址方式 寻址方式分类——基址寻址
基址寻址就是将基址寄存器的内容与指令中给出的偏移量(<4K)相加/减,形成操作数的有效地址。基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能部件寄存器访问等。寄存器间接寻址是偏移量为0的基址加偏移寻址。 基址寻址指令举例如下(前索引寻址): LDR R2,[R3,#0x0C] ;读取R3+0x0C地址上的存储单元 ;的内容,放入R2 STR R1,[R0,#-4]! ;先R0=R0-4,然后把R0的值寄存 ;到保存到R1指定的存储单元 0x55 R2 R3 0x 0xAA 0x C 将R3+0x0C作为地址装载数据 0xAA LDR R2,[R3,#0x0C]

14 4.1 ARM处理器寻址方式 寻址方式分类——基址寻址 基址寻址指令举例如下:
LDR R0,[R1] ,#4 ;R0=[R1],R1=R1+ ;后索引基址寻址 ;ARM这种自动索引机制不消耗额外的时间 LDR R0,[R1,R2] ;R0=[R1+R2]

15 4.1 ARM处理器寻址方式 寻址方式分类——多寄存器寻址
多寄存器寻址一次可传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器。多寄存器寻址指令举例如下: LDMIA R1!,{R2-R7,R12} ;将R1指向的单元中的数据读出到 ;R2~R7、R12中(R1自动加4) STMIA R0!,{R2-R7,R12} ;将寄存器R2~R7、R12的值保 ;存到R0指向的存储; 单元中 ;(R0自动加4) 0x R1 R2 0x?? 0x01 R3 R4 R6 0x02 0x03 0x04 0x 0x 0x C 存储器 0x01 0x02 0x03 0x04 0x LDR R1!,{R2-R4,R6}

16 4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址
堆栈是一个按特定顺序进行存取的存储区,操作顺序为“后进先出” 。堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。存储器堆栈可分为两种: 向上生长:向高地址方向生长,称为递增堆栈 向下生长:向低地址方向生长,称为递减堆栈

17 4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 0x12345678 堆栈压栈 向下增长 向上增长 栈底 栈顶 栈区 SP
堆栈存储区 栈顶 栈底 栈区 SP 堆栈压栈 0x

18 4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址
堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个待压入数据的空位置,称为空堆栈。 栈顶 SP 栈底 空堆栈 满堆栈 压栈 0x 压栈 0x 栈顶 SP 0x 栈顶 SP

19 4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 所以可以组合出四种类型的堆栈方式:
满递增:堆栈向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA、STMFA等; 空递增:堆栈向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA、STMEA等; 满递减:堆栈向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD、STMFD等; 空递减:堆栈向下增长,堆栈指针向堆栈下的第一个空位置。指令如LDMED、STMED等。

20 4.1 ARM处理器寻址方式 寻址方式分类——块拷贝寻址 多寄存器传送指令用于将一块数据从存储器的某一位置拷贝到另一位置。 如:
STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。 ;存储指针R0在保存第一个值之后增加, ;增长方向为向上增长。 STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。 ;存储指针R0在保存第一个值之前增加,

21 4.1 ARM处理器寻址方式 寻址方式分类——相对寻址
相对寻址是基址寻址的一种变通。由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。相对寻址指令举例如下: BL SUBR1 ;调用到SUBR1子程序 BEQ LOOP ;条件跳转到LOOP标号处 ... LOOP MOV R6,#1 SUBR1 ...

22 第4章 目录 1.ARM处理器寻址方式 2. ARM指令集

23 简单的ARM程序 使用“;”进行注释 实际代码段 标号顶格写 声明文件结束 ;文件名:TEST1.S ;功能:实现两个寄存器相加
;说明:使用ARMulate软件仿真调试 AREA Example1,CODE,READONLY ;声明代码段Example1 ENTRY ;标识程序入口 CODE ;声明32位ARM指令 START MOV R0,#0 ;设置参数 MOV R1,#10 LOOP BL ADD_SUB ;调用子程序ADD_SUB B LOOP ;跳转到LOOP ADD_SUB ADDS R0,R0,R1 ;R0 = R0 + R1 MOV PC,LR ;子程序返回 END ;文件结束 使用“;”进行注释 实际代码段 标号顶格写 声明文件结束

24 简单的ARM程序 ;文件名:TEST1.S ;功能:实现两个寄存器相加 ;说明:使用ARMulate软件仿真调试
AREA Example1,CODE,READONLY ;声明代码段Example1 ENTRY ;标识程序入口 CODE ;声明32位ARM指令 START MOV R0,#0 ;设置参数 MOV R1,#10 LOOP BL ADD_SUB ;调用子程序ADD_SUB B LOOP ;跳转到LOOP ADD_SUB ADDS R0,R0,R1 ;R0 = R0 + R1 MOV PC,LR ;子程序返回 END ;文件结束

25 ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令
8.伪指令

26 ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令
8.伪指令

27 4.2 指令集介绍 ARM指令集——指令格式

28 4.2 指令集介绍 ARM指令集——基本指令格式 ARM是三地址指令格式,指令的基本格式如下:
4.2 指令集介绍 ARM指令集——基本指令格式 ARM是三地址指令格式,指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 其中<>号内的项是必须的,{}号内的项是可选的。各项的说明如下: opcode:指令助记符; cond:执行条件; S:是否影响CPSR寄存器的值; Rd:目标寄存器; Rn:第1个操作数的寄存器; operand2:第2个操作数; 例: 指令语法 目标寄存器(Rd) 源寄存器1(Rn) 源寄存器2(Rm) ADD r3,r1,r2 r3 r1 r2

29 4.2 指令集介绍 ARM指令集——第2个操作数 ARM指令的基本格式如下:
4.2 指令集介绍 ARM指令集——第2个操作数 ARM指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 灵活的使用第2个操作数“operand2”能够提高代码效率。它有如下的形式: #immed_8r——常数表达式; Rm——寄存器方式; Rm,shift——寄存器移位方式;

30 4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式
4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式 该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到。 循环右移10位 0x00 0x12 1 8位常数 0x00 0x80 1 0x04

31 4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式
4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式 该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到。 例如: AND R1,R2,#0x0F

32 4.2 指令集介绍 ARM指令集——第2个操作数 Rm——寄存器方式 在寄存器方式下,操作数即为寄存器的数值。 例如:
4.2 指令集介绍 ARM指令集——第2个操作数 Rm——寄存器方式 在寄存器方式下,操作数即为寄存器的数值。 例如: SUB R1,R1,R2

33 4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式
4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式 将寄存器的移位结果作为操作数(移位操作不消耗额外的时间),但Rm值保持不变,移位方法如下: 操作码 说明 ASR #n 算术右移n位 ROR #n 循环右移n位 LSL #n 逻辑左移n位 RRX 带扩展的循环右移1位 LSR #n 逻辑右移n位 Type Rs Type为移位的一种类型,Rs为偏移量寄存器,低8位有效。

34 4.2 指令集介绍 桶形移位器 ALU 桶形移位器 Rd 结果N 预处理 未预处理 Rm Rn

35 4.2 指令集介绍 桶形移位器操作 助记符 说明 移位操作 结果 Y值 LSL 逻辑左移 x LSL y x<<y
4.2 指令集介绍 桶形移位器操作 助记符 说明 移位操作 结果 Y值 LSL 逻辑左移 x LSL y x<<y #0-31 or Rs LSR 逻辑右移 x LSR y (unsigned)x>>y #1-32 or Rs ASR 算术右移 x ASR y (signed)x>>Y ROR 算术左移 x ROR y ((unsigned)x>>y|(x<<32-y)) RRX 扩展的循环右移 x RRX y (c flag<<31)|((unsigned)x>>1) none

36 4.2 指令集介绍 ARM指令集——第2个操作数 LSL移位操作: LSR移位操作: ASR移位操作: ROR移位操作: RRX移位操作:
4.2 指令集介绍 ARM指令集——第2个操作数 LSL移位操作: LSR移位操作: ASR移位操作: ROR移位操作: RRX移位操作: C

37 4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式 例如:
4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式 例如: ADD R1,R1,R1,LSL #3 ;R1=R1+R1<<3 SUB R1,R1,R2,LSR R3 ;R1=R1-R2>>R3

38 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令 8.伪指令

39 4.2 指令集介绍 ARM指令集——条件码 ARM指令的基本格式如下:
4.2 指令集介绍 ARM指令集——条件码 ARM指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 使用条件码“cond”可以实现高效的逻辑操作(节省跳转和条件语句),提高代码效率。 所有的ARM指令都可以条件执行,而Thumb指令只有B(跳转)指令具有条件执行 功能。如果指令不标明条件代码,将默认为无条件(AL)执行。

40 指令条件码表 操作码 条件助记符 标志 含义 0000 EQ Z=1 相等 0001 NE Z=0 不相等 0010 CS/HS C=1
无符号数大于或等于 0011 CC/LO C=0 无符号数小于 0100 MI N=1 负数 0101 PL 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 NV 从不执行(不要使用)

41 4.2 指令集介绍 ARM指令集——条件码 示例: C代码: If(a > b) a++; Else b++; 对应的汇编代码:
4.2 指令集介绍 ARM指令集——条件码 示例: C代码: If(a > b) a++; Else b++; 对应的汇编代码: CMP R0,R1 ;R0(a)与R1(b)比较 ADDHI R0,R0,#1 ;若R0>R1,则R0=R0+1 ADDLS R1,R1,#1 ;若R0≤1,则R1=R1+1

42 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令 8.伪指令

43 4.2 指令集介绍 ARM指令集——存储器访问指令
4.2 指令集介绍 ARM指令集——存储器访问指令 ARM处理器是典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM7处理器是冯•诺依曼存储结构,RAM存储空间及I/O映射空间统一编址,除对RAM操作以外,对外围IO、程序数据的访问均要通过加载/存储指令进行。 存储器访问指令分为单寄存器操作指令和多寄存器操作指令。

44 ARM存储器访问指令——单寄存器加载 助记符 说明 操作 条件码位置 LDR Rd,addressing 加载字数据
Rd←[addressing],addressing索引 LDR{cond} LDRB Rd,addressing 加载无符号字节数据 LDR{cond}B LDRT Rd,addressing 以用户模式加载字数据 LDR{cond}T LDRBT Rd, addressing 以用户模式加载无符号字节数据 LDR{cond}BT LDRH Rd, addressing 加载无符号半字数据 LDR{cond}H LDRSB Rd, addressing 加载有符号字节数据 LDR{cond}SB LDRSH Rd, addressing 加载有符号半字数据 LDR{cond}SH

45 ARM存储器访问指令——单寄存器存储 助记符 说明 操作 条件码位置 STR Rd, addressing 存储字数据 [addressing]←Rd, addressing索引 STR{cond} STRB Rd,addressing 存储字节数据 STR{cond}B STRT Rd,addressing 以用户模式存储字数据 STR{cond}T STRBT Rd,addressing 以用户模式存储字节数据 STR{cond}BT STRH Rd,addressing 存储半字数据 [addressing] ←Rd, STR{cond}H 散转程序是分支程序的一种, 它可根据运算结果或用户输入数据将程序转入不同的分支. LDR/STR指令用于对内存变量的访问、内存缓冲区数据的访问、查表、外围部件的控制操作等。若使用LDR指令加载数据到PC寄存器,则实现程序跳转功能,这样也就实现了程序散转。 所有单寄存器加载/存储指令可分为“字和无符号字节加载存储指令”和“半字和有符号字节加载存储指令。

46 ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令
LDR{cond}{T} Rd,<地址> ;将指定地址上的字数据读入Rd STR{cond}{T} Rd,<地址> ;将Rd中的字数据存入指定地址 LDR{cond}B{T} Rd,<地址> ;将指定地址上的字节数据读入Rd STR{cond}B{T} Rd,<地址> ;将Rd中的字节数据存入指定地址 前索引偏移指令:LDR R0,[R1,#4] 其中,T为可选后缀。若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是在用户模式下进行的。T在用户模式下无效,不能与前索引偏移一起使用T。

47 ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令编码 B为1表示字节访问,为0表示字访问
P表示前/后变址 L用于区别加载(L为1)或存储(L为0) 指令执行的条件码 I为0时,偏移量为12位立即数,为1时,偏移量为寄存器移位 为指令的寻址方式 Rd为源/目标寄存器 Rn为基址寄存器 U表示加/减 W表示回写

48 ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令
立即数。立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,#0x12] ;R1<-[R0+0x12] 寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2] ; R1<-[R0+R2] LDR R1,[R0,-R2] ; R1<-[R0-R2] 寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2,LSL #2] ;R1<-[R0+R2*4]

49 ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令
从寻址方式的地址计算方法分,加载/存储指令有以下4种格式: 零偏移。 如:LDR Rd,[Rn] 前索引偏移。 如:LDR Rd,[Rn,#0x04]! 程序相对偏移。 如:LDR Rd,labe1 后索引偏移。 如:LDR Rd,[Rn],#-0x04 注意:必须保证字数据操作的地址是32位对齐的。 若Rn是R15则不能使用!

50 ARM存储器访问指令——单寄存器存储 LDR和STR——半字和有符号字节加载/存储指令
LDR{cond}SB Rd,<地址> ;将指定地址上的有符号字节读入Rd LDR{cond}SH Rd,<地址> ;将指定地址上的有符号半字读入Rd LDR{cond}H Rd,<地址> ;将指定地址上的半字数据读入Rd STR{cond}H Rd,<地址> ;将Rd中的半字数据存入指定地址 注意: 1.有符号位半字/字节加载是指用符号位加载扩展到32位,无符号半字加载是指用零扩展到32位; 2.半字读写的指定地址必须为偶数,否则将产生不可靠的结果;

51 ARM存储器访问指令——单寄存器存储 LDR和STR——半字和有符号字节加载/存储指令编码 S为1表示有符号访问,为0表示无符号访问
W表示回写 P表示前/后变址 H为1表示半字访问,为0表示字节访问 指令执行的条件码 U表示加/减 为指令的寻址方式 I为0时,偏移量为12位立即数,为1时,偏移量为寄存器移位 Rd为源/目标寄存器 Rn为基址寄存器 L用于区别加载(L为1)或存储(L为0)

52 ARM存储器访问指令——单寄存器存储 LDR和STR指令应用示例: 1.加载/存储字和无符号字节指令 2.加载/存储半字和有符号字节指令
LDR R2,[R5] ;将R5指向地址的字数据存入R2 STR R1,[R0,#0x04] ;将R1的数据存储到R0+0x04地址 LDRB R3,[R2],#-1 ;将R2指向地址的字节数据存入R3,R2=R2-1 STRB R0,[R3,-R8 ASR #2] ;R0->[R3-R8/4],存储R0的最低有效字节 2.加载/存储半字和有符号字节指令 LDRSB R1,[R0,R3] ;将R0+R3地址上的字节数据存入R1, ;高24位用符号扩展 LDRH R6,[R2],#2 ;将R2指向地址的半字数据存入R6,高16位用0扩展 ;读出后,R2=R2+2 STRH R1,[R0,#2]! ;将R1的半字数据保存到R0+2地址, ;只修改低2字节数据,然后R0=R0+2

53 ARM存储器访问指令——单寄存器存储 (3)LDR和STR ----双字:加载/存储两个相邻的寄存器,64位双字。其句法有4种:
Op {cond} D Rd,[Rn] 零偏移 Op {cond} D Rd,[Rn,offset] {!} 前索引偏移 Op {cond} D Rd,label 程序相对偏移 Op {cond} D {T} Rd,[Rn],offset 后索引偏移

54 ARM存储器访问指令——单寄存器存储 Rn 除非指令为零偏移,或不带写回的前索引,否则,Rn不允许与Rd和R(d+1)相同。
其中: Rd 加载/存储寄存器中的一个,另一个是R(d+1)。Rd必须是偶数寄存器,且不是R14。 Rn 除非指令为零偏移,或不带写回的前索引,否则,Rn不允许与Rd和R(d+1)相同。 label label必须是在当前指令的上下252字节范围内。 例如: LDRD R6,[R11] ;R6←[R11],R7←[R11+4] STRD R4,[R9,#24] ;R4→[R9+24],R5→[R9+28]

55 ARM存储器访问指令——多寄存器存取 助记符 说明 操作 条件码位置 LDM{mode} Rn{!},reglist 多寄存器加载 reglist←[Rn...],Rn回写等 LDM{cond} {mode} STM{mode} Rn{!},reglist 多寄存器存储 [Rn...]←reglist,Rn回写等 STM{cond} 多寄存器加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。它们主要用于现场保护、数据复制、常数传递等。

56 ARM存储器访问指令——多寄存器存取 多寄存器加载/存储指令格式如下:
LDM{cond}<模式> Rn{!},reglist{^} STM{cond}<模式> Rn{!},reglist{^} cond:指令执行的条件; 模式:控制地址的增长方式,一共有8种模式; !:表示在操作结束后,将最后的地址写回Rn中; reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列; ^:可选后缀。允许在用户模式或系统模式下使用。它有以下两个功能: 1)若op是LDM且寄存器列表包含R15时,那么除了正常的多寄存器传送外,还将SPSR也复制到CPSR中。这用于异常处理返回,仅在异常模式下使用。 2)数据传入或传出的是用户模式下的寄存器,而不是当前模式的寄存器。

57 ARM存储器访问指令——多寄存器存取 LDM和STM——多寄存器加载/存储指令编码 指令执行的条件码 P表示前/后变址 寄存器列表
U表示加/减 Rn为基址寄存器 S对应于指令中的”^”符号 L用于区别加载(L为1)或存储(L为0) W表示回写

58 ARM存储器访问指令——多寄存器存取 多寄存器加载/存储指令的8种模式如下表所示,右边四种为堆栈操作、左边四种为数据传送操作。
说明 IA 每次传送后地址加4 FD 满递减堆栈 IB 每次传送前地址加4 ED 空递减堆栈 DA 每次传送后地址减4 FA 满递增堆栈 DB 每次传送前地址减4 EA 空递增堆栈 数据块传送操作 堆栈操作 进行数据复制时,先设置好源数据指针和目标指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储 。 进行堆栈操作操作时,要先设置堆栈指针(SP),然后使用堆栈寻址指令STMFD/LDMFD 、STMED/LDMED、STMFA/LDMFA和STMEA/LDMEA实现堆栈操作。

59 ARM存储器访问指令——多寄存器存取 数据块传送指令操作过程如右图所示,其中R1为指令执行前的基址寄存器,R1’则为指令执行后的基址寄存器。
指令STMIA R1!,{R5-R7} 4008H 4004H 4000H 4014H 4010H 400CH 指令STMDA R1!,{R5-R7} 指令STMIB R1!,{R5-R7} R1’  R1  指令STMDB R1!,{R5-R7} 数据块传送指令操作过程如右图所示,其中R1为指令执行前的基址寄存器,R1’则为指令执行后的基址寄存器。

60 ARM存储器访问指令——多寄存器存取 堆栈操作(详见“4.1 寻址方式堆栈寻址”)和数据块传送指令类似,也有4种模式,它们之间的关系如下表所示: 数据块传送 存储 堆栈操作 压栈 说明 加载 出栈 STMDA STMED 空递减 LDMDA LDMFA 满递减 STMIA STMEA 空递增 LDMIA LDMFD 满递增 STMDB STMFD LDMDB LDMEA STMIB STMFA LDMIB LDMED ;使用数据块传送指令进行堆栈操作 STMDA R0!,{R5-R6} . . . LDMIB R0!,{R5-R6} ;使用堆栈指令进行堆栈操作 STMED R13!,{R5-R6} . . . LDMED R13!,{R5-R6} 两段代码的执行结果是一样的,但是使用堆栈指令的压栈和出栈操作编程很简单(只要前后一致即可),而使用数据块指令进行压栈和出栈操作则需要考虑空与满、加与减对应的问题。

61 ARM存储器访问指令——寄存器和存储器交换指令
助记符 说明 操作 条件码位置 SWP Rd,Rm,Rn 寄存器和存储器字数据交换 Rd←[Rn],[Rn]←Rm (Rn≠Rd或Rm) SWP{cond} SWPB Rd,Rm,Rn 寄存器和存储器字节数据交换 SWP{cond}B SWP指令用于将一个内存单元(该单元地址放在寄存器Rn中)的内容读取到一个寄存器Rd中,同时将另一个寄存器Rm的内容写入到该内存单元中。使用SWP可实现信号量操作。 指令格式如下: SWP{cond}{B} Rd,Rm,[Rn] 其中,B为可选后缀,若有B,则交换字节,否则交换32位字;Rd用于保存从存储器中读入的数据;Rm的数据用于存储到存储器中,若Rm与Rd相同,则为寄存器与存储器内容进行互换;Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同。

62 ARM存储器访问指令——寄存器和存储器交换指令
SWP和SWPB——寄存器和存储器交换指令编码 指令执行的条件码 Rm源寄存器 B用于区别无符号字节(B为1)或字(B为0) Rd目标寄存器 Rn为基址寄存器 SWP指令应用示例: SWP R1,R1,[R0] ;将R1的内容与R0指向的存储单元的内容进行互换 SWPB R1,R2,[R0] ;将R0指向的存储单元低字节数据读取到R1中 ;(高24位清零),并将R2的内容写入到该内存单元中 ;(最低字节有效)

63 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令 8.伪指令

64 4.2 指令集介绍 ARM指令集——ARM数据处理指令 数据处理指令大致可分为3类: 数据传送指令; 算术逻辑运算指令; 比较指令。
4.2 指令集介绍 ARM指令集——ARM数据处理指令 数据处理指令大致可分为3类: 数据传送指令; 算术逻辑运算指令; 比较指令。 数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作。所有ARM数据处理指令均可选择使用S后缀,以使指令影响状态标志。

65 ARM数据处理指令——指令编码 opcode操作码功能表 指令执行的条件码 第二操作数 I用于区别立即数(I为1)和寄存器移位(I为0)
带进位加法 ADC 0101 带进位减法指令 SBC 0110 带进位逆向减法指令 RSC 0111 位测试指令 TST 1000 相等测试指令 TEQ 1001 比较指令 CMP 1010 负数比较指令 CMN 1011 逻辑或操作指令 ORR 1100 数据传送 MOV 1101 位清除指令 BIC 1110 数据非传送 MVN 1111 加法运算指令 ADD 0100 逆向减法指令 RSB 0011 减法运算指令 SUB 0010 逻辑异或操作指令 EOR 0001 逻辑与操作指令 AND 0000 说明 指令助记符 操作码 opcode操作码功能表 指令执行的条件码 第二操作数 I用于区别立即数(I为1)和寄存器移位(I为0) Rd目标寄存器 Rn第一操作数寄存器 S设置条件码,与指令中的S位对应 opcode数据处理指令操作码

66 ARM数据处理指令——数据传送 注:当后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。 助记符
说明 操作 条件码位置 MOV Rd,operand2 数据传送 Rd←operand2 MOV{cond}{S} MVN Rd,operand2 数据非传送 Rd←(~operand2) MVN{cond}{S} 注:当后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。

67 MOV{cond}{S} Rd,operand2
ARM数据处理指令——数据传送 助记符 说明 操作 条件码位置 MOV Rd,operand2 数据传送 Rd←operand2 MOV{cond}{S} MVN Rd,operand2 数据非传送 Rd←(~operand2) MVN{cond}{S} MOV指令将8位图立即数(参看“第2操作数:#immed_8r——常数表达式 ”)或寄存器传送到目标寄存器(Rd),可用于移位运算等操作。指令格式如下: MOV{cond}{S} Rd,operand2 MOV指令举例如下: MOV R11,#0xF000000B ;R1= 0xF000000B MOV R0,R1 ;R0=R1 MOVS R3,R1,LSL #2 ;R3=R1<<2,并影响标志位 MOV PC,LR ;PC=LR,子程序返回

68 MVN{cond}{S} Rd,operand2
ARM数据处理指令——数据传送 助记符 说明 操作 条件码位置 MOV Rd,operand2 数据传送 Rd←operand2 MOV{cond}{S} MVN Rd,operand2 数据非传送 Rd←(~operand2) MVN{cond}{S} MVN指令将8位图立即数(参看“第2操作数:#immed_8r——常数表达式 ”)或寄存器(operand2)按位取反后传送到目标寄存器(Rd),因为其具有取反功能,所以可以装载范围更广的立即数。指令格式如下: MVN{cond}{S} Rd,operand2 MVN指令举例如下: MVN R1,#0xFF ;R1=0xFFFFFF00 MVN R1,R2 ;将R2按位取反,结果存到R1

69 ARM数据处理指令——算术运算 注:这些指令影响N,Z,C和V标志位。 助记符 说明 操作 条件码位置
ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 注:这些指令影响N,Z,C和V标志位。

70 ADD{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 加法运算指令——ADD指令将operand2的值与Rn的值相加,结果保存到Rd寄存器。指令格式如下: ADD{cond}{S} Rd,Rn,operand2 应用示例: ADDS R1,R1,#1020 ;R1=R1+1020,并影响标志位 ADD R1,R1,R2,LSL #2 ;R1=R1+R2<<2

71 SUB{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 减法运算指令——SUB指令用寄存器Rn减去operand2,结果保存到Rd中。指令格式如下: SUB{cond}{S} Rd,Rn,operand2 应用示例: SUBS R0,R0,#240 ;R0=R0-240 ,并影响标志位 SUBS R2,R1,R2 ;R2=R1-R2 ,并影响标志位

72 RSB{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 逆向减法运算指令——RSB指令将operand2的值减去Rn,结果保存到Rd中。指令格式如下: RSB{cond}{S} Rd,Rn,operand2 应用示例: RSB R3,R1,#0xFF00 ;R3=0xFF00-R1 RSBS R1,R2,R2,LSL #2 ;R1=(R2<<2)-R2=R2×3 影响标志位

73 ADC{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 带进位加法指令——ADC将operand2的值与Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器。指令格式如下: ADC{cond}{S} Rd,Rn,operand2 应用示例(使用ADC实现64位加法,结果存于R1(高32位)、R0中): ADDS R0,R0,R2 ;R0等于低32位相加,并影响标志位 ADC R1,R1,R3 ;R1等于高32位相加,并加上低位进位

74 SBC{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 带进位减法指令——SBC用寄存器Rn减去operand2,再减去CPSR中的C条件标志位的非(即若C标志清零,则结果减去1),结果保存到Rd中。指令格式如下: SBC{cond}{S} Rd,Rn,operand2 应用示例(使用SBC实现64位减法,结果存于R1、R0中): SUBS R0,R0,R2 ; 低32位相减,并影响标志位 SBC R1,R1,R3 ;高32位相减,并减去低位借位

75 RSC{cond}{S} Rd,Rn,operand2
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD Rd, Rn, operand2 加法运算指令 Rd←Rn+operand2 ADD{cond}{S} SUB Rd, Rn, operand2 减法运算指令 Rd←Rn-operand2 SUB{cond}{S} RSB Rd, Rn, operand2 逆向减法指令 Rd←operand2-Rn RSB{cond}{S} ADC Rd, Rn, operand2 带进位加法 Rd←Rn+operand2+Carry ADC{cond}{S} SBC Rd, Rn, operand2 带进位减法指令 Rd←Rn-operand2-(NOT)Carry SBC{cond}{S} RSC Rd, Rn, operand2 带进位逆向减法指令 Rd←operand2-Rn-(NOT)Carry RSC{cond}{S} 带进位逆向减法指令——RSC指令用寄存器operand2减去Rn,再减去CPSR中的C条件标志位,结果保存到Rd中。指令格式如下: RSC{cond}{S} Rd,Rn,operand2 应用示例(使用RSC指令实现求64位数值的负数 ): RSBS R2,R0,#0 ;R2=-R0 RSC R3,R1,#0 ;R3=-R1- !Carry

76 ARM数据处理指令——逻辑运算指令 注:当后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。
助记符 说明 操作 条件码位置 AND Rd, Rn, operand2 逻辑与操作指令 Rd←Rn & operand2 AND{cond}{S} ORR Rd, Rn, operand2 逻辑或操作指令 Rd←Rn | operand2 ORR{cond}{S} EOR Rd, Rn, operand2 逻辑异或操作指令 Rd←Rn ^ operand2 EOR{cond}{S} BIC Rd, Rn, operand2 位清除指令 Rd←Rn & (~operand2) BIC{cond}{S} 注:当后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。

77 AND{cond}{S} Rd,Rn,operand2
ARM数据处理指令——逻辑运算指令 助记符 说明 操作 条件码位置 AND Rd, Rn, operand2 逻辑与操作指令 Rd←Rn & operand2 AND{cond}{S} ORR Rd, Rn, operand2 逻辑或操作指令 Rd←Rn | operand2 ORR{cond}{S} EOR Rd, Rn, operand2 逻辑异或操作指令 Rd←Rn ^ operand2 EOR{cond}{S} BIC Rd, Rn, operand2 位清除指令 Rd←Rn & (~operand2) BIC{cond}{S} 逻辑与操作指令——AND指令将operand2的值与寄存器Rn的值按位作逻辑“与”操作,结果保存到Rd中。指令格式如下: AND{cond}{S} Rd,Rn,operand2 应用示例: ANDS R0,R0,#0x01 ;R0=R0&0x01,取出最低位数据 ANDEQ R2,R1,R3 ;R2=R1&R3

78 ORR{cond}{S} Rd,Rn, operand2
ARM数据处理指令——逻辑运算指令 助记符 说明 操作 条件码位置 AND Rd, Rn, operand2 逻辑与操作指令 Rd←Rn & operand2 AND{cond}{S} ORR Rd, Rn, operand2 逻辑或操作指令 Rd←Rn | operand2 ORR{cond}{S} EOR Rd, Rn, operand2 逻辑异或操作指令 Rd←Rn ^ operand2 EOR{cond}{S} BIC Rd, Rn, operand2 位清除指令 Rd←Rn & (~operand2) BIC{cond}{S} 逻辑或操作指令——ORR指令将operand2的值与寄存器Rn的值按位作逻辑“或”操作,结果保存到Rd中。指令格式如下: ORR{cond}{S} Rd,Rn, operand2 应用示例: ORR R0,R0,#0x0F ;将R0的低4位置1 MOV R1,R2,LSR #24 ;使用ORR指令将R2的高8位 ORR R3,R1,R3,LSL #8 ;数据移入到R3低8位中

79 EOR{cond}{S} Rd,Rn, operand2
ARM数据处理指令——逻辑运算指令 助记符 说明 操作 条件码位置 AND Rd, Rn, operand2 逻辑与操作指令 Rd←Rn & operand2 AND{cond}{S} ORR Rd, Rn, operand2 逻辑或操作指令 Rd←Rn | operand2 ORR{cond}{S} EOR Rd, Rn, operand2 逻辑异或操作指令 Rd←Rn ^ operand2 EOR{cond}{S} BIC Rd, Rn, operand2 位清除指令 Rd←Rn & (~operand2) BIC{cond}{S} 逻辑异或操作指令——EOR指令将operand2的值与寄存器Rn的值按位作逻辑“异或”操作,结果保存到Rd中。指令格式如下: EOR{cond}{S} Rd,Rn, operand2 应用示例: EOR R1,R1,#0x0F ;将R1的低4位取反 EOR R2,R1,R0 ;R2=R1^R0 EORS R0,R5,#0x01 ; 将R5和0x01进行逻辑异或, ;结果保存到R0,并影响标志位

80 BIC{cond}{S} Rd,Rn, operand2
ARM数据处理指令——逻辑运算指令 助记符 说明 操作 条件码位置 AND Rd, Rn, operand2 逻辑与操作指令 Rd←Rn & operand2 AND{cond}{S} ORR Rd, Rn, operand2 逻辑或操作指令 Rd←Rn | operand2 ORR{cond}{S} EOR Rd, Rn, operand2 逻辑异或操作指令 Rd←Rn ^ operand2 EOR{cond}{S} BIC Rd, Rn, operand2 位清除指令 Rd←Rn & (~operand2) BIC{cond}{S} 位清除指令——BIC指令将寄存器Rn的值与operand2的值的反码按位作逻辑“与”操作,结果保存到Rd中。指令格式如下: BIC{cond}{S} Rd,Rn, operand2 应用示例: BIC R1,R1,#0x0F ;将R1的低4位清零,其它位不变 BIC R1,R2,R3 ;将R3的反码和R2相逻辑“与”, ;结果保存到R1中

81 ARM数据处理指令——比较指令 注:这些指令影响N,Z,C和V标志位。 助记符 说明 操作 条件码位置 CMP Rn, operand2
标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 注:这些指令影响N,Z,C和V标志位。

82 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 比较指令——CMP指令将寄存器Rn的值减去operand2的值,根据操作的结果更新CPSR中的相应条件标志位(N/Z/C/V),以便后面的指令根据相应的条件标志来判断是否执行。 CMP指令与SUBS指令的区别在于CMP指令不保存运算结果。指令格式如下: CMP{cond} Rn, operand2 应用示例: CMP R1,#10 ; R1与10比较,设置相关标志位 CMPGT R1,R2 ; R1与R2比较,设置相关标志位 ;若R1>10, 则执行本指令 若相等,Z=1;否则,z=0。若产生借位,C=0;否则C=1。

83 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 负数比较指令——CMN指令使用寄存器Rn的值加上operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMN{cond} Rn, operand2 应用示例: CMN R0,#1 ; R0+1,判断R0是否为1的补码 ;如果是,则设置Z标志位 若产生进位,C=1;否则C=0。 对于加法和减法指令,当发生带符号溢出时,V置1;对于其它费加法和减法指令,V通常不变。

84 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 负数比较指令——CMN指令使用寄存器Rn的值加上operand2的值,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMN{cond} Rn, operand2 注意:CMN指令与ADDS指令的区别在于CMN指令不保存运算结果。CMN指令可用于负数比较,比如CMN R0,#1指令则表示R0与-1比较,若R0为-1(即1的补码),则Z置位;否则Z复位。

85 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 位测试指令——TST指令将寄存器Rn的值与operand2的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: TST{cond} Rn, operand2 应用示例: TST R0,#0x01 ; 判断R0的最低位是否为0 TST R1,#0x0F ; 判断R1的低4位是否为0

86 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 位测试指令——TST指令将寄存器Rn的值与operand2的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: TST{cond} Rn, operand2 注意:TST指令与ANDS指令的区别在于TST指令不保存运算结果。TST指令通常与EQ、NE条件码配合使用,当所有测试位均为0时,EQ有效(Z=1),而只要有一个测试位不为0,则NE有效(Z=0) 。

87 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 相等测试指令——TEQ指令将寄存器Rn的值与operand2的值按位作逻辑“异或”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: TEQ{cond} Rn, operand2 应用示例: TEQ R0,R1 ; 比较R0与R1是否相等 (不影响V位和C位)

88 ARM数据处理指令——比较指令 助记符 说明 操作 条件码位置 CMP Rn, operand2 比较指令 标志N、Z、C、V←Rn-operand2 CMP{cond} CMN Rn, operand2 负数比较指令 标志N、Z、C、V←Rn+operand2 CMN{cond} TST Rn, operand2 位测试指令 标志N、Z、C、V←Rn & operand2 TST{cond} TEQ Rn, operand2 相等测试指令 标志N、Z、C、V←Rn ^ operand2 TEQ{cond} 相等测试指令——TEQ指令将寄存器Rn的值与operand2的值按位作逻辑“异或”操作,根据操作的结果更新CPSR中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: TEQ{cond} Rn, operand2 注意:TEQ指令与EORS指令的区别在于TEQ指令不保存运算结果。使用TEQ进行相等测试时,常与EQ、NE条件码配合使用。当两个数据相等时,EQ有效;否则NE有效。

89 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.杂项指令 8.伪指令

90 4.2 指令集介绍 ARM指令集——乘法指令 ARM7TDMI具有三种乘法指令,分别为: 32×32位乘法指令; 32× 32位乘加指令;
4.2 指令集介绍 ARM指令集——乘法指令 ARM7TDMI具有三种乘法指令,分别为: 32×32位乘法指令; 32× 32位乘加指令; 32× 32位结果为64位的乘/乘加指令。

91 ARM指令——乘法指令 乘法指令编码 Opcode乘法指令操作码 Rm为被乘数寄存器 opcode操作码功能表 指令执行的条件码
64位有符号乘加指令 SMLAL 111 64位有符号乘法指令 SMULL 110 64位无符号乘加指令 UMLAL 101 64位无符号乘法指令 UMULL 100 32位乘加指令 MLA 001 32位乘法指令 MUL 000 说明 指令助记符 操作码 opcode操作码功能表 指令执行的条件码 Rs为乘数寄存器 S设置条件码,与指令中的S位对应 Rn/RdLo为MLA指令相加的寄存器或64位乘法指令的目标寄存器(低32位) Rd/RdHi为目标寄存器或64位乘法指令的目标寄存器(高32位)

92 ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm)
MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S}

93 ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 32位乘法指令——MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中。 Rd,Rm,Rs不能为R15。只影响CPSR中的N位和Z位,不影响V,C不确定。指令格式如下: MUL{cond}{S} Rd,Rm,Rs 应用示例: MUL R1,R2,R3 ;R1=R2×R3 MULS R0,R3,R7 ;R0=R3×R7,影响CPSR中的N位和Z位

94 MLA{cond}{S} Rd,Rm,Rs,Rn
ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 32位乘加指令——MLA指令将Rm和Rs中的值相乘,再将乘积加上第3个操作数,结果的低32位保存到Rd中。 Rd,Rm,Rs,Rn不能为R15。只影响CPSR中的N位和Z位,不影响V,C不确定。指令格式如下: MLA{cond}{S} Rd,Rm,Rs,Rn 应用示例: MLA R1,R2,R3,R0 ; R1=R2×R3+R0

95 UMULL{cond}{S} RdLo,RdHi,Rm,Rs
ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 64位无符号乘法指令——UMULL指令将Rm和Rs中的值作无符号数相乘,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 RdLo/Hi,Rm,Rs不能为R15。 RdLo/Hi,Rm必须是不同的寄存器。只影响CPSR中的N位和Z位,标志C和V不确定。指令格式如下: UMULL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: UMULL R0,R1,R5,R8 ; (R1、R0)=R5×R8

96 ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 64位无符号乘加指令——UMLAL指令将Rm和Rs中的值作无符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 RdLo/Hi,Rm,Rs不能为R15。 RdLo/Hi,Rm必须是不同的寄存器。只影响CPSR中的N位和Z位,标志C和V不确定。指令格式如下: UMLAL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: UMLAL R0,R1,R5,R8 ;(R1、R0)=R5×R8+(R1、R0)

97 SMULL{cond}{S} RdLo,RdHi,Rm,Rs
ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 64位有符号乘法指令——SMULL指令将Rm和Rs中的值作有符号数相乘,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 RdLo/Hi,Rm,Rs不能为R15。 RdLo/Hi,Rm必须是不同的寄存器。只影响CPSR中的N位和Z位,标志C和V不确定。指令格式如下: SMULL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: SMULL R2,R3,R7,R6 ; (R3、R2)=R7×R6

98 SMLAL{cond}{S} RdLo,RdHi,Rm,Rs
ARM指令——乘法指令 助记符 说明 操作 条件码位置 MUL Rd,Rm,Rs 32位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S} MLA Rd,Rm,Rs,Rn 32位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S} UMULL RdLo,RdHi,Rm,Rs 64位无符号乘法指令 (RdLo,RdHi) ←Rm*Rs UMULL{cond}{S} UMLAL RdLo,RdHi,Rm,Rs 64位无符号乘加指令 (RdLo,RdHi) ←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S} SMULL RdLo,RdHi,Rm,Rs 64位有符号乘法指令 SMULL{cond}{S} SMLAL RdLo,RdHi,Rm,Rs 64位有符号乘加指令 SMLAL{cond}{S} 64位有符号乘加指令——SMLAL指令将Rm和Rs中的值作有符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中。 RdLo/Hi,Rm,Rs不能为R15。 RdLo/Hi,Rm必须是不同的寄存器。只影响CPSR中的N位和Z位,标志C和V不确定。指令格式如下: SMLAL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: SMLAL R2,R3,R7,R6 ; (R3、R2)=R7×R6+(R3、R2)

99 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7. 杂项指令 8.伪指令

100 4.2 指令集介绍 ARM指令集——分支指令 在ARM中有两种方式可以实现程序的跳转,一种是使用分支指令直接跳转,另一种则是直接向PC寄存器赋值实现跳转。 分支指令有以下三种: 分支指令B; 带链接的分支指令BL; 带状态切换的分支指令BX。

101 ARM分支指令——指令编码 分支指令B/BL指令编码格式 分支指令BX指令编码格式 指令执行的条件码
L区别B指令(L为0)和BL指令(L为1) 24位有符号立即数(偏移量) 分支指令BX指令编码格式 指令执行的条件码 Rm目标地址寄存器,该寄存器装载跳转地址

102 ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label
带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←Rm,切换处理器状态 BX{cond}

103 ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←Rm,切换处理器状态 BX{cond} 分支指令——B指令,该指令跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下: B{cond} Label 应用示例: B WAITA ; 跳转到WAITA标号处 B 0x1234 ; 跳转到绝对地址0x1234处

104 ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←Rm,切换处理器状态 BX{cond} 带链接的分支指令——BL指令适用于子程序调用,使用该指令后,下一条指令的地址被拷贝到R14(即LR) 连接寄存器中,然后跳转到指定地址运行程序。跳转范围限制在当前指令的±32M字节地址内。指令格式如下: BL{cond} Label 1.当程序执行到BL跳转指令时,硬件将下一条指令的地址Addr2装入LR寄存器,并把跳转地址装入程序计数器(PC) 2. 程序跳转到目标地址Label继续执行,当子程序执行结束后,将LR寄存器内容存入PC,返回调用函数继续执行 BL Label xxx Label MOV PC,LR Addr1 Addr2 LR PC Addr1 Addr2 Label Addr2 应用示例(调用子程序): BL Label

105 ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←Rm,切换处理器状态 BX{cond} 带状态切换的分支指令——BX指令,该指令可以根据跳转地址(Rm)的最低位来切换处理器状态。其跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下: BX{cond} Rm 跳转地址Rm[0] 跳转后 CPSR标志T位 处理器状态 ARM 1 Thumb

106 ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←Rm,切换处理器状态 BX{cond} 带状态切换的分支指令——BX指令,该指令可以根据跳转地址(Rm)的最低位来切换处理器状态。其跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。 Rm的位[0]不用作地址的一部分。若Rm的位[0]为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为Thumb代码;若Rm的位[0]为0,则Rm的位[1]就不能为1 。指令格式如下: BX{cond} Rm 应用示例: ADRL R0,ThumbFun+1 ;将Thumb程序的入口地址加1存入R0 BX R ; 跳转到R0指定的地址, ;并根据R0的最低位来切换处理器状态

107 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7. 杂项指令 8.伪指令

108 4.2 指令集介绍 ARM指令集——杂项指令 ARM指令集中有三条指令作为杂项指令,在实际应用中这三条指令非常重要。它们如下所示: 助记符
4.2 指令集介绍 ARM指令集——杂项指令 ARM指令集中有三条指令作为杂项指令,在实际应用中这三条指令非常重要。它们如下所示: 助记符 说明 操作 条件码位置 SWI immed_24 软中断指令 产生软中断,处理器进入管理模式 SWI{cond} MRS Rd,psr 读状态寄存器指令 Rd←psr,psr为CPSR或SPSR MRS{cond} MSR psr_fields, Rd/#immed_8r 写状态寄存器指令 psr_fields←Rd/#immed_8r,psr为 CPSR或SPSR MSR{cond}

109 ARM杂项指令——软中断指令 SWI指令用于产生SWI异常,使得CPU模式变换到管理模式,并且将CPSR保存到管理模式的SPSR中,然后程序跳转到SWI异常入口。不影响条件码标志。 该指令主要用于用户程序调用操作系统的系统服务,操作系统在SWI异常处理程序中进行相应的系统服务。 SWI指令格式 SWI{cond} immed_24 SWI:0x SWI指令编码 指令执行的条件码 指令传递的参数(24位立即数,其值为0~224-1),执行时CPU忽略该参数。

110 ARM杂项指令——软中断指令 根据SWI指令传递的参数SWI异常处理程序可以作出相应的处理。SWI指令传递参数有以下两种方法,
指令中的24位立即数指定了用户请求的服务类型,参数通过通用寄存器传递。 MOV R0,#34 ;设置子功能号为34 SWI ;调用12号软中断 指令中的24位立即数被忽略,用户请求的服务类型由寄存器R0的值决定,参数通过其它的通用寄存器传递。 MOV R0,#12 ;调用12号软中断 MOV R1,#34 ;设置子功能号为34 SWI 0

111 ARM杂项指令——软中断指令 在SWI异常中断处理程序中,取出SWI指令中立即数的步骤为:
首先确定引起软中断的SWI指令是ARM指令还是Thumb指令,这可通过对SPSR访问得到; 然后取得该SWI指令的地址,这可通过访问LR寄存器得到; 接着读出该SWI指令,分解出立即数。 SWI_Handler STMFD SP!, {R0-R3, R12, LR} ; 现场保护 MRS R0, SPSR ; 读取SPSR STMFD SP!, {R0} ; 保存SPSR TST R0, #0x ; 测试T标志位 LDRNEH R0, [LR,#-2] ; 若是Thumb指令,读取指令码(16位) BICNE R0, R0, #0xFF00 ; 取得Thumb指令的8位立即数(低8位) LDREQ R0, [LR,#-4] ; 若是ARM指令,读取指令码(32位) BICEQ R0, R0, #0xFF ; 取得ARM指令的24位立即数(低23位) ... LDMFD SP!, {R0-R3, R12, PC}^ ; SWI异常中断返回 NE:Z=0 EQ:Z=1 TST指令:如果指令的结果为0,则Z=1;不等于0,则Z=0 EQ:Z=1;NE:Z=0

112 ARM杂项指令——状态寄存器读指令 在ARM处理器中,只有MRS指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以了解当前处理器的工作状态。读SPSR寄存器可以了解到进入异常前的处理器状态。该指令不影响条件码。 MRS指令格式 MRS{cond} Rd,psr 指令对应编码 指令执行的条件码 区别CPSR(为0)和SPSR(为1)寄存器 目标寄存器,不能为R15

113 ARM杂项指令——状态寄存器读指令 在ARM处理器中,只有MRS指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以了解当前处理器的工作状态。读SPSR寄存器可以了解到进入异常前的处理器状态。 MRS指令格式 MRS{cond} Rd,psr 应用示例: MRS R1,CPSR ; 将CPSR状态寄存器读取,保存到R1中 MRS R2,SPSR ; 将SPSR状态寄存器读取,保存到R2中 R13:SP R14:LR R15:PC R16:CPSR R17:SPSR

114 ARM杂项指令——状态寄存器写指令 在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。 MSR指令格式1 MSR{cond} psr_fields,#immed_8r MSR指令格式2 MSR{cond} psr_fields,Rm 指令执行的条件码 CPSR或SPSR 指定传送的区域,可以为以下字母(必须小写)的一个或者组合: c 控制域屏蔽字节(psr[7..0]) x 扩展域屏蔽字节(psr[15..8]) s 状态域屏蔽字节(psr[23..16]) f 标志域屏蔽字节(psr[31..24]) 保存要传送到状态寄存器指定域数据的源寄存器 要传送到状态寄存器指定域的立即数

115 ARM杂项指令——状态寄存器写指令 在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。 MSR指令1编码 MSR指令2编码 指令执行的条件码 CPSR或SPSR 指定传送的区域,可以为以下字母(必须小写)的一个或者组合: c 控制域屏蔽字节(psr[7..0]) x 扩展域屏蔽字节(psr[15..8]) s 状态域屏蔽字节(psr[23..16]) f 标志域屏蔽字节(psr[31..24]) 8_bit_immediate:8位位图立即数 要传送到状态寄存器指定域的立即数

116 ARM杂项指令——状态寄存器写指令 在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。 应用示例1: ;子程序:使能IRQ中断 ENABLE_IRQ MRS R0, CPSR BIC R0, R0,#0x80 MSR CPSR_c,R0 MOV PC,LR 应用示例2: ;子程序:禁能IRQ中断 DISABLE_IRQ MRS R0, CPSR ORR R0, R0,#0x80 MSR CPSR_c,R0 MOV PC,LR (1) (2) (3) (4) 1.将CPSR寄存器内容读出到R0; 3.将修改后的值写回 CPSR寄存器的对应控制域; 2.修改对应于CPSR中的I控制位; 4.返回上一层函数;

117 ARM指令目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7. 杂项指令 8.伪指令

118 4.2 指令集介绍 ARM伪指令 ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的一条或多条ARM指令所代替。ARM伪指令有四条,分别为ADR伪指令、ADRL伪指令、LDR伪指令、NOP伪指令。 Load ADdRess Load ADdRess long

119 ADR{cond} register,expr
ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 ADR伪指令格式 ADR{cond} register,expr 指令执行的条件码 加载的目标寄存器 地址表达式 地址表达式expr的取指范围: 当地址值是字节对齐时,其取指范围为-255~255; 当地址值是字对齐时,其取指范围为-1020~1020;

120 ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): ... ADR R0,Delay Delay MOV R0,r14 使用伪指令将程序标号Delay的地址存入R0

121 ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R1,Delay Delay MOV R0,r14 ... 0x20 ADD r1,pc,#0x3c 0x64 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 地址 程序代码

122 ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r1,pc,#0x3c 0x64 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 ADR伪指令被汇编成一条指令

123 ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例2(查表): ADR R0,DISP_TAB ; 加载转换表地址 LDRB R1,[R0,R2] ; 使用R2作为参数,进行查表 DISP_TAB DCB 0xC0,0xF9,0xA4,0xB0,0x99, 0x92,0x82,0xF8

124 ADRL{cond} register,expr
ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 ADRL伪指令格式 ADRL{cond} register,expr 指令执行的条件码 加载的目标寄存器 地址表达式 地址表达式expr的取指范围: 当地址值是字节对齐时,其取指范围为-64K~64K; 当地址值是字对齐时,其取指范围为-256K~256K;

125 ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): ... ADRL R0,Delay Delay MOV R0,r14 使用伪指令将程序标号Delay的地址存入R0

126 ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r1,pc,#40 0x24 ADD r1,r1,#FF00 0xFF68 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 地址 程序代码

127 ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r1,pc,#40 0x24 ADD r1,r1,#FF00 0xFF68 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 ADRL伪指令被汇编成两条指令

128 LDR{cond} register,=[expr | label_expr
ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 LDR伪指令格式 LDR{cond} register,=[expr | label_expr 指令执行的条件码 加载的目标寄存器 基于PC的地址表达式或外部表达式 注意: 1.从指令位置到文字池的偏移量必须小于4KB; 2.与ARM指令的LDR相比,伪指令的LDR的参数有“=”号。

129 ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 应用示例(加载常量): LDR R2, =0xFF ;MOV R2, #0xFF0 LDR R0, =0xFF ;MOV R0, #0xFF000000 LDR R1, =0xFFFFFFFE ;MVN R1, #0x1

130 ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 应用示例(加载地址): ... LDR R1,=InitStack InitStack MOV R0, LR 使用伪指令将程序标号InitStack的地址存入R1

131 ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 应用示例(加载地址): 编译后的反汇编代码: ... LDR R1,=InitStack InitStack MOV R0, LR ... 0x60 LDR R1,0xb4 0x64 MOV R0, LR 0xb4 DCD 0x64 使用伪指令将程序标号InitStack的地址存入R1 地址 程序代码

132 ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 应用示例(加载地址): 编译后的反汇编代码: ... LDR R1,=InitStack InitStack MOV R0, LR ... 0x60 LDR R1,0xb4 0x64 MOV R0, LR 0xb4 DCD 0x64 使用伪指令将程序标号InitStack的地址存入R1 LDR伪指令被汇编成一条LDR指令,并在文字池中定义了一个常量,该常量为InitStack标号的地址

133 ARM伪指令——空操作伪指令 NOP伪指令在汇编时将会被代替成ARM中的空操作,比如可能是“MOV R0,R0”指令等。NOP可用于延时操作。 NOP伪指令格式 NOP 应用示例(延时子程序): mov R1,#0x1234 Delay NOP ;空操作 NOP SUBS R1,R1,#1 ;循环次数减一 BNE Delay ;如果循环没有结束,跳转Delay继续 MOV PC,LR ;子程序返回

134 ARM汇编程序设计 由于高级编程语言隐藏了CPU执行指令的许多细节,因此在只关心系统所具有功能的系统中,采用高级语言编写程序更为合适。但是,CPU执行指令的细节差异会反应在系统的非功能特性上,例如系统程序的规模和运行速度。因此,掌握汇编语言程序设计对于嵌入式系统的设计者来说是非常必要的。

135 ARM汇编程序设计 ARM汇编程序中每一行的通用格式为: {标号} {指令|指示符|伪指令} {;注解}。
标号代表一个地址,段内标号的地址值在汇编时确定,段外标号的地址值在链接时确定。

136 ARM汇编程序设计 AREA Word, CODE, READONLY ; name this block of code
num EQU ; Set number of words to be copied ENTRY ; mark the first instruction to call start LDR r0, =src ; r0 = pointer to source block LDR r1, =dst ; r1 = pointer to destination block MOV r2, #num ; r2 = number of words to copy wordcopy LDR r3, [r0], #4 ; a word from the source STR r3, [r1], #4 ; store a word to the destination SUBS r2, r2, # ; decrement the counter BNE wordcopy ; ... copy more stop MOV r0, #0x ; angel_SWIreason_ReportException LDR r1, =0x ; ADP_Stopped_ApplicationExit SWI 0x ; ARM semihosting SWI AREA BlockData, DATA, READWRITE src DCD 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4 dst DCD 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 END

137 ARM汇编程序设计 符号类型 指示符 功能 符号定义指示符 GBLA 声明和初始化一个全局算术变量,初始值为0 GBLL
符号定义指示符 GBLA 声明和初始化一个全局算术变量,初始值为0 GBLL 声明和初始化一个全局逻辑变量,初始值为{FALSE} GBLS 声明和初始化一个全局字符串变量,初始值为空 LCLA 声明和初始化一个局部算术变量,初始值为0。局部算术变量只能在宏中进行声明。 LCLL 声明和初始化一个局部逻辑变量,初始值为{FALSE}。局部逻辑变量只能在宏中进行声明。 LCLS 声明和初始化一个局部字符串变量,初始值为空。局部字符串变量只能在宏中进行声明。 SETA 给一个局部或全局算术变量置值 SETL 给一个局部或全局逻辑变量置值 SETS 给一个局部或全局字符串变量置值 RLIST 给寄存器集命名 CN 给一个协处理器寄存器命名 CP 给一个特定协处理器命名,协处理器号为0~15 DN 给一个双精度VFP寄存器命名 SN 给一个单精度VFP寄存器命名 FN 给一个特定的浮点寄存器命名

138 ARM汇编程序设计 数据定义指示符 LTORG 指示汇编器汇编当前文字池 ^ 或MAP 置存储映射的起点到一个特定的地址 # 或FIELD
数据定义指示符 LTORG 指示汇编器汇编当前文字池 ^ 或MAP 置存储映射的起点到一个特定的地址 # 或FIELD 描述指示符所定义的存储映射中的空间 % 或SPACE 定义一块值为0的存储器区域 = 或DBC 分配一个或多个字节 & 或DCD 分配一个或多个字,从4字节边界开始 DCDU 分配一个或多个字,但不一定从4字节边界开始 DCDO 分配以字边界开始的存储区域,并指定初始值为到静态基址寄存器的偏移 DCFD 分配给双精度浮点数一段以字边界开始的内存区域 DCFDU 分配给双精度浮点数一段以任意边界开始的内存区域 DCFS 分配给单精度浮点数一段以字边界开始的内存区域 DCFSU 分配给单精度浮点数一段以任意边界开始的内存区域 DCI 分配以字边界开始的存储区域,并指定初始值。标记此地址存储的是代码而不是数据 DCQ 分配给双精度浮点数一段以4字节边界开始的内存区域 DCQU DCW 分配给一个或多个半字以半字边界开始的内存区域 DCWU 分配给一个或多个半字以任意边界开始的内存区域 DATA 标识一个标号是代码段中数据的标号,该符号后是DCB或DCD

139 ARM汇编程序设计 报告指示符 ASSERT 对于声明错误,在第二次汇编时产生错误信息 ! 或INFO 在汇编时显示信息 OPT
报告指示符 ASSERT 对于声明错误,在第二次汇编时产生错误信息 ! 或INFO 在汇编时显示信息 OPT 可在源代码中设置列表选项 TTL 在一个列表文件每页的开始插入一个标题,每一页的标题在下一个TTL之前都有效 SUBT 在一个列表文件的页中设置一个子标题,每一页的子标题在下一个SUBT之前都有效

140 ARM汇编程序设计 汇编控制指示符 [ 或IF 这三个符号连用,进行条件汇编 | 或ELSE ] 或ENDIF MACRO
汇编控制指示符 [ 或IF 这三个符号连用,进行条件汇编 | 或ELSE ] 或ENDIF MACRO 这二个符号连用,定义一个宏定义 MEND MEXIT 用来在结束前退出宏定义 WHILE 这二个符号连用,进行重复汇编 WEND

141 ARM汇编程序设计 杂项指示符 ALIGN 从一个字边界开始 AREA 指示汇编器汇编一段新的代码或数据部分 CODE16
杂项指示符 ALIGN 从一个字边界开始 AREA 指示汇编器汇编一段新的代码或数据部分 CODE16 指示汇编器将随后的指令作为16位Thumb指令 CODE32 指示汇编器将随后的指令作为32位ARM指令 END 表示源程序的结束 ENTRY 指向程序的入口,一个源文件中只能有一个ENTRY * 或EQU 对一个常量赋予一个符号名 EXPORT或 GLOBAL 说明了由链接器在目标和库文件中使用的符号 IMPORT或 EXTERN 提供汇编器在当前汇编中未曾定义的符号名 GET或 INCLUDE 包含一个文件,在GET处汇编包含的文件 INCBIN 包含一个未被汇编过的文件 KEEP 指示汇编器保留符号表中的局部符号 NOFP 在汇编语言程序中禁止浮点指令 REQUIRE 指示两段之间的依赖关系 REQUIRE8 指示当前文件请求堆栈为8字节对准 PRESERVE8 指示当前文件保持堆栈为8字节对准 RN 给特定的寄存器命名 ROUT 标记局部标号使用范围的界面

142 ARM汇编程序设计 预定义变量1 ARM汇编器对ARM的寄存器进行了预定义,所有的寄存器和协处理器名都是大小写敏感的。预定义的寄存器如下:
·R0~R15和r0~r15; ·a1~a4(参数、结果或临时寄存器,与r0~r3同义); ·v1~v8(变量寄存器,与r4~r11同义); ·sb和SB(静态基址寄存器,与r9同义); ·sl和SL(堆栈限制寄存器,与r10同义); ·fp和FP(帧指针,与r11同义);

143 ARM汇编程序设计 预定义变量2 ·ip和IP(过程调用中间临时寄存器,与r12同义); ·sp和SP(堆栈指针,与r13同义);
·lr和LR(链接寄存器,与r14同义); ·pc和PC(程序计数器,与r15同义); ·cpsr和CPSR(程序状态寄存器); ·spsr和SPSR(程序状态寄存器); ·f0~f7和F0~F7(FPA寄存器); ·s0~s31和S0~S31(VFP单精度寄存器); ·d0~d15和D0~D15(VFP双精度寄存器); ·p0~p15(协处理器0~15); ·c0~c15(协处理器寄存器0~15)。

144 ARM汇编程序设计 内置变量1 ARM汇编器所定义的内置变量如表4-1所示。值得注意的是内置变量的设置不能用SETA、SETL或SETS等指示符来设置,只能用于表达式或条件语句。例如: IF {ARCHITECTURE} = “4T”

145 ARM汇编程序设计 表4-1 内置变量 变量 含义 {PC}或. 当前指令的地址 {VAR}或@ 存储区位置计数器的当前值 {TRUE}
逻辑常量真 {FALSE} 逻辑常量假 {OPT} 当前设置列表选项值,OPT用来保存当前列表选项,改变选项值,恢复它的原始值 {CONFIG} 如果汇编器汇编ARM代码,则值为32;如果汇编器汇编Thumb代码,则值为16 {ENDIAN} 如果汇编器在大端模式下,则值为big;如果汇编器在小端模式下,则值为little

146 ARM汇编程序设计 表4-1 内置变量(续) {CODESIZE}
如果汇编器汇编ARM代码,则值为32;如果汇编器汇编Thumb代码,则值为16,与{CONFIG}同义 {CPU} 选定的CPU名,缺省时为ARM7TDMI {FPU} 选定的FPU名,缺省时为SoftVFP {ARCHITECTURE} 选定的ARM体系结构的值;3,3M,4,4T和4TxM {PCSTOREOFFSET} STR pc,[…]或STM Rb,[…PC]指令的地址和PC存储值之间的偏移量 {ARMASM_VERSION} 或| ads $ version | ARM汇编器的版本号,为整数

147 ARM汇编程序设计 常量 十进制,如:123,1,0 十六进制,如:0x123,0xab,0x7b
n_XXX,n表示n进制,从2~9:XXX是具体的数 字符串:由一对双引号及双引号之间字符串组成,并包含C中的转义字符。 逻辑常量为{TRUE}和{FALSE}。

148 ARM汇编程序设计 宏定义及使用 与C语言中的#define相似,仅在源程序中做字符替换 以MACRO指示符开始,以MEND结束,例:
$label TestAndBranch $dest, $reg, $cc $label CMP $reg, #0 B$cc $dest MEND Test CMP R0, #0 BNE NonZero NonZero Test TestAndBranch NonZero, R0, NE NonZero

149 ARM汇编程序设计 内嵌汇编 __asm __ (“instruction ...
在C和C++语言中嵌入汇编语言可以实现一些高级语言中没有的功能。 语法 __asm __ (“instruction ... instruction”); //Linux gcc中支持 __asm{ instruction }; //ADS中支持 asm(“instruction [; instruction]”); //ARM C++中使用 armv4l-unknown-linux-gcc

150 ARM汇编程序设计 C语言中内嵌汇编示例 (ADS可编译通过) #include <stdio.h>
void my_strcpy(char* src, const char* dst){ int ch; __asm{ loop: LDRB ch, [src], #1 STRB ch, [dst], #1 CMP ch, #0 BNE loop }; } int main(void){ const char* a = "Hello World!"; char b[20]; MOV R0, a MOV R1, b BL my_strcpy, {R0, R1} printf("Original String: %s\n",a); printf(“Copied String: %s\n",b); return 0; C语言中内嵌汇编示例 (ADS可编译通过) armv4l-unknown-linux-gcc a. 不能直接向PC寄存器赋值,程序跳转要使用B或者BL指令 b. 在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突 c. R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能将R0到R3、R12及R14用于子程序调用,因此要避免直接使用这些物理寄存器 d. 一般不要直接指定物理寄存器,而让编译器进行分配

151 ARM汇编程序设计 C语言中调用汇编程序 根据ATPCS标准,函数前4个参数通过 R0-R3来传递,其它参数通过堆栈(FD)传递
#include <stdio.h> extern void strcopy(char *d, const char *s); int main() { const char *srcstr = "First string - source"; char dststr[] = "Second string - destination"; /* dststr is an array since we're going to change it */ printf("Before copying:\n"); printf(" '%s'\n '%s'\n",srcstr,dststr); strcopy(dststr,srcstr); printf("After copying:\n"); return 0; } AREA SCopy, CODE, READONLY EXPORT strcopy strcopy ; r0 points to destination string ; r1 points to source string LDRB r2, [r1],#1 ; load byte and update address STRB r2, [r0],#1 ; store byte and update address; CMP r2, # ; check for zero terminator BNE strcopy ; keep going if not MOV pc,lr ; Return END 通过满递减堆栈实现C和ARM汇编程序中第4个以后参数的传递。LDR R4,[SP],#4

152 ARM汇编程序设计 在c程序中声明的全局变量可以被汇编程序通过地址间接访问。具体访问方法如下: 使用IMPORT伪操作声明该全局变量。
使用LDR伪指令读取该全局变量的内存地址,通常该全局变量的内存地址值存放在程序的数据缓冲池中(literal pool)。 根据该数据的类型,使用相应的LDR伪指令读取该全局变量的值;使用相应的STR指令;修改该全局变量的值。 各数据类型及对应的LDR/STR指令如下: 对于无符号的char类型的变量通过指令LDRB/STRB来读/写。 对于无符号的short类型的变量通过指令LDRH/STRH来读/写。 对于int类型的变量通过指令LDR/STR来读/写

153 ARM汇编程序设计 对于有符号的char类型的变量通过指令LDRSB来读取。 对于有符号的char类型的变量通过指令STRB来写入。
对于有符号的short类型的变量通过指令LDRSH来读取。 对于有符号的short类型的变量通过指令STRH来写入。 对于小于8个字的结构型变量,可以通过一条LDM/STM指令来读/写整个变量。 对于结构型变量的数据成员,可以使用相应的LDR/STR指令来访问,这时必须知道该数据成员相对于结构型变量开始地址的偏移量。

154 ARM汇编程序设计 在汇编程序中访问c程序全局变量的例子。程序中变量globvl是在c程序中声明的全局变量。在汇编程序中首先用IMPORT伪操作声明该变量;再将其内存地址读入到寄存器R1中;再将其值读入到寄存器R0中;修改后再将寄存器R0的值赋于变量globvl。程序如下。 AREA globals, CODE, READONLY EXPORT asmsub IMPORT globvl asmsub LDR r1, =globvl LDR r0, [r1] ADD r0, r0, #2 STR r0, [r1] MOV pc, lr END

155 ARM汇编程序设计 汇编语言中调用C语言中定义的函数
汇编程序的设计要遵循ATPCS,保证程序调用时参数的正确传递。在汇编程序中使用IMPORT伪操作声明将要调用c程序。下面是一个汇编程序调用c程序的例子。其中在汇编程序中设置好各参数的值。本例中有5个参数,分别使用寄存器R0存放第一个参数,R1存放第2个参数,R2存放第3个参数,R3存放第4个参数,第5个参数利用数据栈传送。由于利用数据栈传递参数,在程序调用结束后要调用数据栈指针。 注:详细内容参加《ARM体系结构与编程》一书

156 ARM汇编程序设计 //c程序g()返回5个整数的和 int g(int a, int b, int c, int d, int e) {
return a + b + c + d + e; } ;汇编程序调用c程序g()计算5个整数i, 2*i, 3*i, 4*i, 5*i的和 EXPORT f AREA f, CODE, READONLY IMPORT g ;使用伪操作数IMPORT声明c程序g() STR lr, [sp,#-4]! ;保存返回地址 ADD r1, r0, r ;假设进入程序f时,r0中的值为i,r1值设为2*i ADD r2, r1, r ;r2的值设为3*i ADD r3, r1, r ;r3的值设为5*i STR r3, [sp, #-4]! ;第五个参数5*i通过数据栈传递 ADD r3, r1, r ;r4值设为4*i BL g ;调用c程序g() ADD sp, sp, # ;调整数据栈指针,准备返回 LDR pc, [sp], # ;返回 END


Download ppt "C H A P T E R 4 ARM7指令集."

Similar presentations


Ads by Google