第4章 ARM7TDMI(-S)指令系统
第4章 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集
第4章 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集
第4章 ARM7TDMI(-S)指令系统 简介 ARM处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制较为简单。ARM7TDMI(-S)具有32位ARM指令集和16位Thumb指令集,ARM指令集效率高,但是代码密度低;而Thumb指令集具有较高的代码密度,却仍然保持ARM的大多数性能上的优势,它是ARM指令集的子集。所有的ARM指令都是可以有条件执行的,而Thumb指令仅有一条指令具备条件执行功能。ARM程序和Thumb程序可相互调用,相互之间的状态切换开销几乎为零。
第4章 ARM7TDMI(-S)指令系统 ARM指令集与Thumb指令集的关系 Thumb指令集具有灵活、小巧的特点 ARM指令集支持ARM核所有的特性,具有高效、快速的特点
4.1 ARM处理器寻址方式 寻址方式分类 寻址方式是根据指令中给出的地址码字段来实现寻找真实操作数地址的方式。ARM处理器具有9种基本寻址方式。 1.寄存器寻址; 2.立即寻址; 3.寄存器移位寻址; 4.寄存器间接寻址; 5.基址寻址; 6.多寄存器寻址; 7.堆栈寻址; 8.块拷贝寻址; 9.相对寻址。
4.1 ARM处理器寻址方式 寻址方式分类——寄存器寻址 操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值来操作。寄存器寻址指令举例如下: MOV R1,R2 ;将R2的值存入R1 SUB R0,R1,R2 ;将R1的值减去R2的值,结果保存到R0 0xAA 0x55 R2 R1 0xAA MOV R1,R2
4.1 ARM处理器寻址方式 寻址方式分类——立即寻址 立即寻址指令中的操作码字段后面的地址码部分即是操作数本身,也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(这样的数称为立即数)。立即寻址指令举例如下: SUBS R0,R0,#1 ;R0减1,结果放入R0,并且影响标志位 MOV R0,#0xFF000 ;将立即数0xFF000装入R0寄存器 0x55 R0 MOV R0,#0xFF00 程序存储 指令后有S标志,表示影响状态寄存器 从代码中获得数据 0xFF00 MOV R0,#0xFF00
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
4.1 ARM处理器寻址方式 寻址方式分类——寄存器间接寻址 寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。寄存器间接寻址指令举例如下: LDR R1,[R2] ;将R2指向的存储单元的数据读出 ;保存在R1中 SWP R1,R1,[R2] ;将寄存器R1的值和R2指定的存储 ;单元的内容交换 0x55 R0 R2 0x40000000 0xAA 那个SWP指令有点怪 0xAA LDR R0,[R2]
4.1 ARM处理器寻址方式 寻址方式分类——基址寻址 基址寻址就是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能部件寄存器访问等。基址寻址指令举例如下: LDR R2,[R3,#0x0C] ;读取R3+0x0C地址上的存储单元 ;的内容,放入R2 STR R1,[R0,#-4]! ;先R0=R0-4,然后把R1的值寄存 ;到保存到R0指定的存储单元 0x55 R2 R3 0x40000000 0xAA 0x4000000C 将R3+0x0C作为地址装载数据 0xAA LDR R2,[R3,#0x0C]
4.1 ARM处理器寻址方式 *寻址方式分类——多寄存器寻址 多寄存器寻址一次可传送几个寄存器值,允许一条指令传送16个寄存器的任何子集或所有寄存器。多寄存器寻址指令举例如下: LDMIA R1!,{R2-R7,R12} ;将R1指向的单元中的数据读出到 ;R2~R7、R12中(R1自动加1) STMIA R0!,{R2-R7,R12} ;将寄存器R2~R7、R12的值保 ;存到R0指向的存储; 单元中 ;(R0自动加1) 0x40000000 R1 R2 0x?? 0x01 R3 R4 R6 0x02 0x03 0x04 0x40000004 0x40000008 0x4000000C 存储器 0x01 0x02 0x03 0x04 注意传送方向,写法与LDR有区别。有感叹号,表示R1值要回写。 0x40000010 LDMIA R1!,{R2-R4,R6}
4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 堆栈是一个按特定顺序进行存取的存储区,操作顺序为“后进先出” 。堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。存储器堆栈可分为两种: 向上生长:向高地址方向生长,称为递增堆栈 向下生长:向低地址方向生长,称为递减堆栈
4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 0x12345678 堆栈压栈 向下增长 向上增长 栈底 栈顶 栈区 SP 堆栈存储区 栈顶 栈底 栈区 SP 堆栈压栈 0x12345678
4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个待压入数据的空位置,称为空堆栈。 栈顶 SP 栈底 空堆栈 满堆栈 压栈 0x12345678 压栈 0x12345678 栈顶 SP 0x12345678 栈顶 SP
4.1 ARM处理器寻址方式 寻址方式分类——堆栈寻址 所以可以组合出四种类型的堆栈方式: 满递增:堆栈向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA、STMFA等; 空递增:堆栈向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA、STMEA等; 满递减:堆栈向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD、STMFD等; 空递减:堆栈向下增长,堆栈指针向堆栈下的第一个空位置。指令如LDMED、STMED等。
4.1 ARM处理器寻址方式 寻址方式分类——块拷贝寻址 多寄存器传送指令用于将一块数据从存储器的某一位置拷贝到另一位置。 如: STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。 ;存储指针在保存第一个值之后增加, ;增长方向为向上增长。 STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。 ;存储指针在保存第一个值之前增加,
4.1 ARM处理器寻址方式 寻址方式分类——相对寻址 相对寻址是基址寻址的一种变通。由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。相对寻址指令举例如下: BL SUBR1 ;调用到SUBR1子程序 BEQ LOOP ;条件跳转到LOOP标号处 ... LOOP MOV R6,#1 SUBR1 ...
第4章 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集
简单的ARM程序 使用“;”进行注释 实际代码段 标号顶格写 声明文件结束 ;文件名:TEST1.S ;功能:实现两个寄存器相加 ;说明:使用ARMulate软件仿真调试 AREA Example1,CODE,READONLY ;声明代码段Example1 ENTRY ;标识程序入口 CODE32 ;声明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 ;文件结束 使用“;”进行注释 实际代码段 标号顶格写 声明文件结束
简单的ARM程序 ;文件名:TEST1.S ;功能:实现两个寄存器相加 ;说明:使用ARMulate软件仿真调试 AREA Example1,CODE,READONLY ;声明代码段Example1 ENTRY ;标识程序入口 CODE32 ;声明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 ;文件结束
第4章 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——指令格式 ARM指令的基本格式如下: 4.2 指令集介绍 ARM指令集——指令格式 ARM指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 其中<>号内的项是必须的,{}号内的项是可选的。各项的说明如下: opcode:指令助记符; cond:执行条件; S:是否影响CPSR寄存器的值; Rd:目标寄存器; Rn:第1个操作数的寄存器; operand2:第2个操作数;
4.2 指令集介绍 ARM指令集——第2个操作数 ARM指令的基本格式如下: 4.2 指令集介绍 ARM指令集——第2个操作数 ARM指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 灵活的使用第2个操作数“operand2”能够提高代码效率。它有如下的形式: #immed_8r——常数表达式; Rm——寄存器方式; Rm,shift——寄存器移位方式;
4.2 指令集介绍 ARM指令集——第2个操作数---------- #immed_8r——常数表达式 4.2 指令集介绍 ARM指令集——第2个操作数---------- #immed_8r——常数表达式 该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到。 循环右移10位 0x00 0x12 1 8位常数 0x00 0x80 1 0x04
4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式 4.2 指令集介绍 ARM指令集——第2个操作数 #immed_8r——常数表达式 该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到。 例如: MOV R0,#1 AND R1,R2,#0x0F
4.2 指令集介绍 ARM指令集——第2个操作数 Rm——寄存器方式 在寄存器方式下,操作数即为寄存器的数值。 例如: 4.2 指令集介绍 ARM指令集——第2个操作数 Rm——寄存器方式 在寄存器方式下,操作数即为寄存器的数值。 例如: SUB R1,R1,R2 MOV PC,R0
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位有效。
4.2 指令集介绍 ARM指令集——第2个操作数 LSL移位操作: LSR移位操作: ASR移位操作: ROR移位操作: RRX移位操作: 4.2 指令集介绍 ARM指令集——第2个操作数 LSL移位操作: LSR移位操作: ASR移位操作: ROR移位操作: RRX移位操作: C
4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式 例如: 4.2 指令集介绍 ARM指令集——第2个操作数 Rm,shift——寄存器移位方式 例如: ADD R1,R1,R1,LSL #3 ;R1=R1+R1*8=9R1 SUB R1,R1,R2,LSR R3 ;R1=R1-(R2/2R3)
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——条件码 ARM指令的基本格式如下: 使用条件码“cond”可以实现高效的逻辑操作,提高代码效率。 4.2 指令集介绍 ARM指令集——条件码 ARM指令的基本格式如下: <opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>} 使用条件码“cond”可以实现高效的逻辑操作,提高代码效率。 所有的ARM指令都可以条件执行,而Thumb指令只有B(跳转)指令具有条件执行 功能。如果指令不标明条件代码,将默认为无条件(AL)执行。
指令条件码表 操作码 条件助记符 标志 含义 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 从不执行(不要使用)
4.2 指令集介绍 ARM指令集——条件码 示例: C代码: If(a > b) a++; Else b++; 对应的汇编代码: 4.2 指令集介绍 ARM指令集——条件码 示例: C代码: If(a > b) a++; Else b++; 对应的汇编代码: CMP R0,R1 ;R0与R1比较 ADDHI R0,R0,#1 ;若R0>R1,则R0=R0+1 ADDLS R1,R1,#1 ;若R0≤R1,则R1=R1+1
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——存储器访问指令 4.2 指令集介绍 ARM指令集——存储器访问指令 ARM处理器是典型的RISC处理器,对存储器的访问只能使用加载和存储指令实现。ARM处理器是冯•诺依曼存储结构,程序空间、RAM空间及I/O映射空间统一编址,除对RAM操作以外,对外围IO、程序数据的访问均要通过加载/存储指令进行。 存储器访问指令分为单寄存器操作指令和多寄存器操作指令。
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
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寄存器,则实现程序跳转功能,这样也就实现了程序散转。 所有单寄存器加载/存储指令可分为“字和无符号字节加载存储指令”和“半字和有符号字节加载存储指令。
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中的字节数据存入指定地址 其中,T为可选后缀。若指令有T,那么即使处理器是在特权模式下,存储系统也将访问看成是在用户模式下进行的。T在用户模式下无效,不能与前索引偏移一起使用T?。
ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令编码 B为1表示字节访问,为0表示字访问 P表示前/后变址 L用于区别加载(L为1)或存储(L为0) 指令执行的条件码 I为0时,偏移量为12位立即数,为1时,偏移量为寄存器移位 为指令的寻址方式 Rd为源/目标寄存器 Rn为基址寄存器 U表示加/减 W表示回写
ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令 立即数。立即数可以是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,#0x12] 寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2] 寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。 如:LDR R1,[R0,R2,LSL #2]
ARM存储器访问指令——单寄存器存储 LDR和STR——字和无符号字节加载/存储指令 从寻址方式的地址计算方法分,加载/存储指令有以下4种格式: 零偏移。 如:LDR Rd,[Rn] 前索引偏移。 如:LDR Rd,[Rn,#0x04]! 程序相对偏移。 如:LDR Rd,labe1 *后索引偏移。 如:LDR Rd,[Rn],#0x04 注意:大多数情况下,必须保证字数据操作的地址是32位对齐的。--即是4的倍数 注意后索引,是指传送 之后,地址变化。
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.半字读写的指定地址必须为偶数,否则将产生不可靠的结果;
ARM存储器访问指令——单寄存器存储 LDR和STR——半字和有符号字节加载/存储指令编码 S为1表示有符号访问,为0表示无符号访问 W表示回写 P表示前/后变址 H为1表示半字访问,为0表示字节访问 指令执行的条件码 U表示加/减 为指令的寻址方式 I为0时,偏移量为12位立即数,为1时,偏移量为寄存器移位 Rd为源/目标寄存器 Rn为基址寄存器 L用于区别加载(L为1)或存储(L为0)
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 R6,[R7] ;读R6 的数据保存到R7 指定的地址中, 只存储一字节数据 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—有感叹号表示回写
ARM存储器访问指令——多寄存器存取 助记符 说明 操作 条件码位置 LDM{mode} Rn{!},reglist 多寄存器加载 reglist←[Rn...],Rn回写等 LDM{cond} {mode} STM{mode} Rn{!},reglist 多寄存器存储 [Rn...]←reglist,Rn回写等 STM{cond} 多寄存器加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。它们主要用于现场保护、数据复制、常数传递等。
ARM存储器访问指令——多寄存器存取 多寄存器加载/存储指令格式如下: LDM{cond}<模式> Rn{!},reglist{^} STM{cond}<模式> Rn{!},reglist{^} cond:指令执行的条件; 模式:控制地址的增长方式,一共有8种模式; !:表示在操作结束后,将最后的地址写回Rn中; reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列; ^:加入该后缀后,进行数据传送且寄存器列表不包含PC时,加载/存储的寄存器是用户模式下的,而不是当前模式的寄存器。若在LDM指令且寄存器列表中包含有PC时使用,那么除了正常的多寄存器传送外,还将SPSR也拷贝到CPSR中,这可用于异常处理返回。注意:该后缀不允许在用户模式或系统模式下使用。 ^号,是为了在特权模式下,进行用户模式寄存器内容的保护。
ARM存储器访问指令——多寄存器存取 LDM和STM——多寄存器加载/存储指令编码 指令执行的条件码 P表示前/后变址 寄存器列表 ?? U表示加/减 Rn为基址寄存器 S对应于指令中的”^”符号 L用于区别加载(L为1)或存储(L为0) W表示回写
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实现堆栈操作。
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’则为指令执行后的基址寄存器。 ?
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 R0!,{R5-R6} . . . LDMED R0!,{R5-R6} 两段代码的执行结果是一样的,但是使用堆栈指令的压栈和出栈操作编程很简单(只要前后一致即可),而使用数据块指令进行压栈和出栈操作则需要考虑空与满、加与减对应的问题。
SWP{cond}{B} Rd,Rm,[Rn] 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的数据用于存储到存储器中,若Rd与Rm 相同,则为寄存器与存储器内容进行交换;Rn为要进行数据交换的存储器地址,Rn不能与Rd和Rm相同。 注意,事实上。只有Rd与Rm相同时,才实现传统意义上的交换。
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的内容写入到该内存单元中 ;(最低字节有效)
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——ARM数据处理指令 数据处理指令大致可分为3类: 数据传送指令; 算术逻辑运算指令; 比较指令。 4.2 指令集介绍 ARM指令集——ARM数据处理指令 数据处理指令大致可分为3类: 数据传送指令; 算术逻辑运算指令; 比较指令。 数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作。所有ARM数据处理指令均可选择使用S后缀,并影响状态标志。 不能对存储内容进行处理,也就不能用间接寻址,只能寄存器寻址与立即数寻址,或寄存器移位寻址。。
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数据处理指令操作码
ARM数据处理指令——数据传送 助记符 说明 操作 条件码位置 MOV Rd,operand2 数据传送 Rd←operand2 MOV{cond}{S} MVN Rd,operand2 数据非传送 Rd←(~operand2) MVN{cond}{S}
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 R1,#0x10 ;R1=0x10 MOV R0,R1 ;R0=R1 MOVS R3,R1,LSL #2 ;R3=R1<<2,并影响标志位 MOV PC,LR ;PC=LR,子程序返回
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
ARM数据处理指令——算术运算 助记符 说明 操作 条件码位置 ADD 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{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,#1 ;R1=R1+1,并影响标志位 ADD R1,R1,R2 ;R1=R1+R2
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,#1 ;R0=R0-1 ,并影响标志位 SUBS R2,R1,R2 ;R2=R1-R2 ,并影响标志位
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
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、R0中): ADDS R0,R0,R2 ;R0等于低32位相加,并影响标志位 ADC R1,R1,R3 ;R1等于高32位相加,并加上低位进位
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位相减,并减去低位借位
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 RSC R3,R1,#0
ARM数据处理指令——逻辑运算指令 助记符 说明 操作 条件码位置 AND 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{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,取出最低位数据 AND R2,R1,R3 ;R2=R1&R3
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位中
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,并影响标志位
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中
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}
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中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMP{cond} Rn, operand2 应用示例: CMP R1,#10 ; R1与10比较,设置相关标志位 CMP R1,R2 ; R1与R2比较,设置相关标志位
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中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMP{cond} Rn, operand2 注意:CMP指令与SUBS指令的区别在于CMP指令不保存运算结果。在进行两个数据的大小判断时,常用CMP指令及相应的条件码来操作。
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标志位
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中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。指令格式如下: CMP{cond} Rn, operand2 注意:CMN指令与ADDS指令的区别在于CMN指令不保存运算结果。CMN指令可用于负数比较,比如CMN R0,#1指令则表示R0与-1比较,若R0为-1(即1的补码),则Z置位;否则Z复位。
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
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有效,而只要有一个测试位不为0,则NE有效。
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位)
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有效。
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——乘法指令 ARM7TDMI具有三种乘法指令,分别为: 32×32位乘法指令; 32× 32位乘加指令; 4.2 指令集介绍 ARM指令集——乘法指令 ARM7TDMI具有三种乘法指令,分别为: 32×32位乘法指令; 32× 32位乘加指令; 32× 32位结果为64位的乘/乘加指令。
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位对应 Rd/RdLo为MLA指令相加的寄存器或64位乘法指令的目标寄存器(低32位) Rn/RdHi为目标寄存器或64位乘法指令的目标寄存器(高32位)
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}
ARM指令——乘法指令 32位乘法指令——MUL指令将Rm和Rs中的值相乘,结果的低32位保存到Rd中。指令格式如下: 助记符 说明 操作 条件码位置 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中。指令格式如下: MUL{cond}{S} Rd,Rm,Rs 应用示例: MUL R1,R2,R3 ;R1=R2×R3 MULS R0,R3,R7 ;R0=R3×R7,同时影响CPSR中的N位和Z位
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中。指令格式如下: MLA{cond}{S} Rd,Rm,Rs,Rn 应用示例: MLA R1,R2,R3,R0 ; R1=R2×R3+R0
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中。指令格式如下: UMULL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: UMULL R0,R1,R5,R8 ; (R1、R0)=R5×R8
UMLAL{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位无符号乘加指令——UMLAL指令将Rm和Rs中的值作无符号数相乘,64位乘积与RdHi、RdLo相加,结果的低32位保存到RdLo中,而高32位保存到RdHi中。指令格式如下: UMLAL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: UMLAL R0,R1,R5,R8 ;(R1、R0)=R5×R8+(R1、R0)
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中。指令格式如下: SMULL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: SMULL R2,R3,R7,R6 ; (R3、R2)=R7×R6
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中。指令格式如下: SMLAL{cond}{S} RdLo,RdHi,Rm,Rs 应用示例: SMLAL R2,R3,R7,R6 ; (R3、R2)=R7×R6+(R3、R2)
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——分支指令 在ARM中有两种方式可以实现程序的跳转,一种是使用分支指令直接跳转,另一种则是直接向PC寄存器赋值实现跳转。 分支指令有以下三种: 分支指令B; 带链接的分支指令BL; 带状态切换的分支指令BX。
ARM分支指令——指令编码 分支指令B/BL指令编码格式 分支指令BX指令编码格式 指令执行的条件码 L区别B指令(L为0)和BL指令(L为1) 24位有符号立即数(偏移量) 分支指令BX指令编码格式 指令执行的条件码 Rm目标地址寄存器,该寄存器装载跳转地址
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond}
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond} 分支指令——B指令,该指令跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下: B{cond} Label 应用示例: B WAITA ; 跳转到WAITA标号处 B 0x1234 ; 跳转到绝对地址0x1234处
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond} 带链接的分支指令——BL指令适用于子程序调用,使用该指令后,下一条指令的地址被拷贝到R14(即LR) 连接寄存器中,然后跳转到指定地址运行程序。跳转范围限制在当前指令的±32M字节地址内。指令格式如下: BL{cond} Label 2. 程序跳转到目标地址Label继续执行,当子程序执行结束后,将LR寄存器内容存入PC,返回调用函数继续执行 BL Label xxx Label MOV PC,LR Addr1 Addr2 LR PC 1.当程序执行到BL跳转指令时,硬件将下一条指令的地址Addr2装入LR寄存器,并把跳转地址装入程序计数器(PC) Addr1 Label Addr2 Addr2
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond} 带链接的分支指令——BL指令适用于子程序调用,使用该指令后,下一条指令的地址被拷贝到R14(即LR) 连接寄存器中,然后跳转到指定地址运行程序。跳转范围限制在当前指令的±32M字节地址内。指令格式如下: BL{cond} Label 应用示例: BL DELAY ; 调用子程序DELAY
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond} 带状态切换的分支指令——BX指令,该指令可以根据跳转地址(Rm)的最低位来切换处理器状态。其跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下: BX{cond} Rm 跳转地址Rm[0] 跳转后 CPSR标志T位 处理器状态 ARM 1 Thumb
ARM指令——分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label BL{cond} BX Rm 带状态切换的分支指令 PC←label,切换处理器状态 BX{cond} 带状态切换的分支指令——BX指令,该指令可以根据跳转地址(Rm)的最低位来切换处理器状态。其跳转范围限制在当前指令的±32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下: BX{cond} Rm 应用示例: ADRL R0,ThumbFun+1 ;将Thumb程序的入口地址加1存入R0 BX R0 ; 跳转到R0指定的地址, ;并根据R0的最低位来切换处理器状态
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM指令集——协处理器指令 ARM内核支持协处理器操作,协处理器的控制要通过协处理器命令实现。 4.2 指令集介绍 ARM指令集——协处理器指令 ARM内核支持协处理器操作,协处理器的控制要通过协处理器命令实现。 ARM内核与协处理器的关系 ARM内核 协处理器A 协处理器B 握手信号 数据地址总线 …
ARM指令——协处理器指令 助记符 说明 操作 条件码位置 CDP coproc,opcode1,CRd,CRn, CRm{,opcode2} 协处理器数据操作指令 取决于协处理器 CDP{cond} LDC{L} coproc, CRd,<地址> 协处理器数据读取指令 LDC{cond}{L} STC{L} coproc, CRd,<地址> 协处理器数据写入指令 STC{cond}{L} MCR coproc,opcode1,Rd,CRn, ARM寄存器到协处理器寄存器的数据传送指令 MCR{cond} MRC coproc,opcode1,Rd,CRn, 协处理器寄存器到ARM寄存器到的数据传送指令
ARM协处理器指令——数据操作指令 ARM处理器通过CDP指令通知ARM协处理器执行特定的操作。该操作由协处理器完成,即对命令的参数的解释与协处理器有关,指令的使用取决于协处理器。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。指令格式如下: 存放第1个源操作数的协处理器寄存器 作为目标寄存器的协处理器寄存器 CDP{cond} coproc,opcode1,CRd,CRn,CRm{,opcode2} 存放第2个源操作数的协处理器寄存器 协处理器的特定操作码 指令操作的协处理器名 可选的协处理器特定操作码 指令执行的条件码 CDP{cond} coproc,opcode1,CRd,CRn,CRm{,opcode2} 数据操作指令编码
CDP{cond} coproc,opcode1,CRd,CRn,CRm{,opcode2} ARM协处理器指令——数据操作指令 ARM处理器通过CDP指令通知ARM协处理器执行特定的操作。该操作由协处理器完成,即对命令的参数的解释与协处理器有关,指令的使用取决于协处理器。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。指令格式如下: 应用示例: CDP p7,0,c0,c2,c3,0 ;对协处理器7操作,操作码为0, ;可选操作码为0 CDP p6,1,c3,c4,c5 ;对协处理器6操作,操作码为1 CDP{cond} coproc,opcode1,CRd,CRn,CRm{,opcode2}
ARM协处理器指令——数据存取指令 协处理器数据存取指令LDC/STC指令可以将某一连续内存单元的数据读取到协处理器的寄存器中,或者将协处理器的寄存器数据写入到某一连续的内存单元中,传送的字数由协处理器来控制。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 数据读取指令格式 LDC{cond}{L} coproc, CRd,<地址> 数据存储指令格式 STC{cond}{L} coproc, CRd,<地址>
ARM协处理器指令——数据存取指令 协处理器数据存取指令LDC/STC指令可以将某一连续内存单元的数据读取到协处理器的寄存器中,或者将协处理器的寄存器数据写入到某一连续的内存单元中,传送的字数由协处理器来控制。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 W表示回写 P表示前/后变址 8位立即数偏移 数据操作指令编码 指令执行的条件码 协处理器编号 U表示加/减 协处理器中的目标寄存器 N表示数据大小 基址寄存器 L表示该指令是读取(为0)还是写入(为1)
ARM协处理器指令——数据存取指令 协处理器数据存取指令LDC/STC指令可以将某一连续内存单元的数据读取到协处理器的寄存器中,或者将协处理器的寄存器数据写入到某一连续的内存单元中,传送的字数由协处理器来控制。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 数据操作指令编码 应用示例: LDC p5,c2,[R2,#4] ;读取R2+4指向的内存单元的数据, ;传送到协处理器p5的c2寄存器中 STC p5,c1,[R0] ;将协处理器p5的C1寄存器内数据 ;传送到R0指向的内存单元
ARM协处理器指令——寄存器传送指令 如果需要在ARM处理器中的寄存器与协处理器中的寄存器之间进行数据传送,那么可以使用MCR/MRC指令。MCR指令用于将ARM处理器的寄存器中的数据传送到协处理器的寄存器。MRC指令用于将协处理器的寄存器中的数据传送到ARM处理器的寄存器中。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 MCR指令格式(ARM协处理器) MCR{cond} coproc,opcode1,Rd,CRn,CRm{,opcode2} MRC指令格式(协处理器 ARM ) MRC{cond} coproc,opcode1,Rd,CRn,CRm{,opcode2}
ARM协处理器指令——寄存器传送指令 如果需要在ARM处理器中的寄存器与协处理器中的寄存器之间进行数据传送,那么可以使用MCR/MRC指令。MCR指令用于将ARM处理器的寄存器中的数据传送到协处理器的寄存器。MRC指令用于将协处理器的寄存器中的数据传送到ARM处理器的寄存器中。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 指令执行的条件码 协处理器编号 寄存器传送指令编码 表示协处理器特定操作码 存放第2个操作数的协处理器寄存器 L表示数据是传入ARM(为0)还是传入协处理器(为1) 可选的协处理器特定操作码 在ARM中的寄存器 存放第1个操作数的协处理器寄存器
ARM协处理器指令——寄存器传送指令 如果需要在ARM处理器中的寄存器与协处理器中的寄存器之间进行数据传送,那么可以使用MCR/MRC指令。MCR指令用于将ARM处理器的寄存器中的数据传送到协处理器的寄存器。MRC指令用于将协处理器的寄存器中的数据传送到ARM处理器的寄存器中。若协处理器不能成功地执行该操作,将产生未定义指令异常中断。 寄存器传送指令编码 应用示例: MCR p6,2,R7,c1,c2 ;将ARM中的R7寄存器内容传递 ; 到协处理器6的C1和C2寄存器 MRC p5,2,R2,c3,c2 ;将协处理器5的C3和C2寄存器 ;内容传递到ARM中的R2寄存器
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
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}
ARM杂项指令——软中断指令 SWI指令用于产生软中断,从而实现在从户模式变换到管理模式,并且将CPSR保存到管理模式的SPSR中,然后程序跳转到SWI异常入口。在其它模式下也可使用SWI指令,处理器同样地切换到管理模式。 该指令主要用于用户程序调用操作系统的系统服务,操作系统在SWI异常处理程序中进行相应的系统服务。 SWI指令格式 SWI{cond} immed_24 SWI指令编码 指令执行的条件码 指令传递的参数(24位立即数)
ARM杂项指令——软中断指令 根据SWI指令传递的参数SWI异常处理程序可以作出相应的处理。SWI指令传递参数有以下两种方法, 指令中的24位立即数指定了用户请求的服务类型,参数通过通用寄存器传递。 MOV R0,#34 ;设置子功能号为34 SWI 12 ;调用12号软中断 指令中的24位立即数被忽略,用户请求的服务类型由寄存器R0的值决定,参数通过其它的通用寄存器传递。 MOV R0,#12 ;调用12号软中断 MOV R1,#34 ;设置子功能号为34 SWI 0
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, #0x20 ; 测试T标志位 LDRNEH R0, [LR,#-2] ; 若是Thumb指令,读取指令码(16位) BICNE R0, R0, #0xFF00 ; 取得Thumb指令的8位立即数 LDREQ R0, [LR,#-4] ; 若是ARM指令,读取指令码(32位) BICEQ R0, R0, #0xFF000000 ; 取得ARM指令的24位立即数 ... LDMFD SP!, {R0-R3, R12, PC}^ ; SWI异常中断返回
ARM杂项指令——状态寄存器读指令 在ARM处理器中,只有MRS指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以了解当前处理器的工作状态。读SPSR寄存器可以了解到进入异常前的处理器状态。 MRS指令格式 MRS{cond} Rd,psr 指令对应编码 指令执行的条件码 区别CPSR(为0)和SPSR(为1)寄存器 目标寄存器,不能为R15
ARM杂项指令——状态寄存器读指令 在ARM处理器中,只有MRS指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以了解当前处理器的工作状态。读SPSR寄存器可以了解到进入异常前的处理器状态。 MRS指令格式 MRS{cond} Rd,psr 应用示例: MRS R1,CPSR ; 将CPSR状态寄存器读取,保存到R1中 MRS R2,SPSR ; 将SPSR状态寄存器读取,保存到R2中
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]) 保存要传送到状态寄存器指定域数据的源寄存器 要传送到状态寄存器指定域的立即数
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]) Rotate: 立即数对齐 8_bit_immediate:8位立即数 保存要传送到状态寄存器指定域数据的源寄存器 要传送到状态寄存器指定域的立即数
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.返回上一层函数;
ARM指令小节目录 1.指令格式 2.条件码 3.存储器访问指令 4.数据处理指令 5.乘法指令 6.ARM分支指令 7.协处理器指令 8.杂项指令 9.伪指令
4.2 指令集介绍 ARM伪指令 ARM伪指令不属于ARM指令集中的指令,是为了编程方便而定义的。伪指令可以像其它ARM指令一样使用,但在编译时这些指令将被等效的ARM指令代替。ARM伪指令有四条,分别为ADR伪指令、ADRL伪指令、LDR伪指令、NOP伪指令。
ADR{cond} register,expr ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 ADR伪指令格式 ADR{cond} register,expr 指令执行的条件码 加载的目标寄存器 地址表达式 地址表达式expr的取指范围: 当地址值不是字对齐时,其取指范围为-255~255; 当地址值是字对齐时,其取指范围为-1020~1020; 当地址值是16字节对齐时,其取指范围将更大。
ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): ... ADR R0,Delay Delay MOV R0,r14 使用伪指令将程序标号Delay的地址存入R0
ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r0,pc,#0x3c 0x64 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 地址 程序代码
ARM伪指令——小范围的地址读取 ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r0,pc,#0x3c 0x64 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 ADR伪指令被汇编成一条指令
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
ADRL{cond} register,expr ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 ADRL伪指令格式 ADRL{cond} register,expr 指令执行的条件码 加载的目标寄存器 地址表达式 地址表达式expr的取指范围: 当地址值不是字对齐时,其取指范围为-64K~64K; 当地址值是字对齐时,其取指范围为-256K~256K; 当地址值是16字节对齐时,其取指范围将更大。
ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): ... ADRL R0,Delay Delay MOV R0,r14 使用伪指令将程序标号Delay的地址存入R0
ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r0,pc,#40 0x24 ADD r0,r0,#0 0x68 MOV r0,r14 注意有三级流水,当前执行的指令与PC值,相差8 使用伪指令将程序标号Delay的地址存入R0 地址 程序代码
ARM伪指令——中等范围的地址读取 ADRL伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR伪指令可以读取更大范围的地址 。在汇编编译器编译源程序时,ADRL伪指令被编译器替换成两条合适的指令。若不能用两条指令实现,则产生错误,编译失败。 应用示例(源程序): 编译后的反汇编代码: ... ADRL R0,Delay Delay MOV R0,r14 ... 0x20 ADD r0,pc,#40 0x24 ADD r0,r1,#0 0x68 MOV r0,r14 使用伪指令将程序标号Delay的地址存入R0 ADRL伪指令被汇编成两条指令,尽管第2条指令并没有意义
LDR{cond} register,=expr ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 LDR伪指令格式 LDR{cond} register,=expr 指令执行的条件码 加载的目标寄存器 基于PC的地址表达式或外部表达式
ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 应用示例(源程序): ... LDR R1,=InitStack InitStack MOV R0, LR 使用伪指令将程序标号InitStack的地址存入R1
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 地址 程序代码
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标号的地址
ARM伪指令——大范围的地址读取 LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 注意: 1.从指令位置到文字池的偏移量必须小于4KB;? 2.与ARM指令的LDR相比,伪指令的LDR的参数有“=”号。
ARM伪指令——空操作伪指令 NOP伪指令在汇编时将会被代替成ARM中的空操作,比如可能是“MOV R0,R0”指令等。NOP可用于延时操作。 NOP伪指令格式 NOP 应用示例(延时子程序): Delay NOP ;空操作 NOP SUBS R1,R1,#1 ;循环次数减一 BNE Delay ;如果循环没有结束,跳转Delay继续 MOV PC,LR ;子程序返回
第4章 目录 1.ARM处理器寻址方式 2.指令集介绍 ARM指令集 Thumb指令集
4.2 指令集介绍 Thumb指令 Thumb指令集可以看作是ARM指令压缩形式的子集,它是为减小代码量而提出的,具有16位的代码密度。Thumb指令体系不完整,只支持通用功能。必要时仍需要使用ARM指令,如进入异常时。 说明:Thumb指令的格式与使用方式与ARM指令集类似,而且使用并不是很频繁,建议这部分内容选修。
简单的Thumb程序 在Thumb程序段之前要用CODE16声明。 ; 功能:使用BX指令切换处理器状态 AREA Example8,CODE,READONLY ENTRY CODE32 ARM_CODE ADR R0,THUMB_CODE+1 BX R0 ; 跳转并切换处理器状态 CODE16 THUMB_CODE MOV R0,#10 ; R0 = 10 MOV R1,#20 ; R1 = 20 ADD R0,R1 ; R0 = R0+R1 B . END 在Thumb程序段之前要用CODE16声明。
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
4.2 指令集介绍 Thumb指令集与ARM指令集的区别 Thumb指令集较ARM指令集有如下限制: 4.2 指令集介绍 Thumb指令集与ARM指令集的区别 Thumb指令集较ARM指令集有如下限制: 只有B指令可以条件执行,其它指令都不能条件执行; 分支指令的跳转范围有更多限制; 数据处理指令的操作结果必须放入其中一个; 单寄存器访问指令,只能操作R0~R7; LDM和STM指令可以对R0~R7的任何子集进行操作;
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
4.2 指令集介绍 Thumb存储器访问指令 单寄存器访问指令 助记符 说明 操作 影响标志 LDR/STR Rd,addressing 4.2 指令集介绍 Thumb存储器访问指令 单寄存器访问指令 助记符 说明 操作 影响标志 LDR/STR Rd,addressing 加载/存储字数据 Rd←[Rn,#immed_5×4],Rd、Rn为R0~R7 无 LDRH/STRH Rd,addressing 加载/存储无符号半字数据 Rd←[Rn,#immed_5×2],Rd、Rn为R0~R7 LDRB/STRB Rd,addressing 加载/存储无符号字节数据 Rd←[Rn,#immed_5×1],Rd、Rn为R0~R7 LDRSH Rd,addressing 加载有符号半字数据 Rd←[Rn,Rm],Rd、Rn、Rm为R0~R7 LDRSB Rd,addressing 加载有符号字节数据
4.2 指令集介绍 Thumb存储器访问指令 LDR和STR——加载/存储指令 根据指令的寻址方式不同,可以分为以下三类: 立即数偏移寻址; 4.2 指令集介绍 Thumb存储器访问指令 LDR和STR——加载/存储指令 根据指令的寻址方式不同,可以分为以下三类: 立即数偏移寻址; 寄存器偏移寻址; PC或SP相对偏移寻址;
单寄存器访问指令——立即数偏移寻址 以这种寻址方式对存储器访问时,存储器的地址以一个寄存器的内容为基址,在偏移一个立即数后指明。指令格式如下: LDR Rd,[Rn,#immed_5×4] ;加载内存中的字数据到寄存器Rd中 STR Rd,[Rn,#immed_5×4] ;将Rd中的字数据存储到指定地址的内存中 LDRH Rd,[Rn,#immed_5×2] ;加载内存中的半字数据到寄存器Rd的低16位中 STRH Rd,[Rn,#immed_5×2] ;存储Rd中的低16位半字数据到指定的内存单元 LDRB Rd,[Rn,#immed_5×1] ;加载内存中的字节数据到寄存器Rd中 STRB Rd,[Rn,#immed_5×1] ;存储Rd中的低8位字节数据到指定的内存单元 其中:Rd 表示加载或存储的寄存器。必须为R0~R7。 Rn 表示基址寄存器。必须为R0~R7。 immed_5×N 表示立即数偏移量,其取值范围为(0~31)×N。
单寄存器访问指令——立即数偏移指令编码 L用于区别加载(L为1)或存储(L为0) 指令执行的条件码: Rd:源或目标寄存器 Rn:基址寄存器 0110b:LDR/STR指令; 1000b:LDRH/STRH指令; 0111b:LDRB/STRB指令; Rd:源或目标寄存器 Rn:基址寄存器 Immed_5:5位无符号立即数偏移
单寄存器访问指令——立即数偏移寻址 注意:进行字数据访问时,必须保证传送地址为32位对齐。进行半字数据访问时,必须保证传送地址为16位对齐。 应用示例: LDR R0,[R1,#0x4] STR R3,[R4] LDRH R5,[R0,#0x02] STRH R1,[R0,#0x08] LDRB R3,[R6,#20] STRB R1,[R0,#31] 注意:进行字数据访问时,必须保证传送地址为32位对齐。进行半字数据访问时,必须保证传送地址为16位对齐。
单寄存器访问指令——寄存器偏移寻址 这种寻址方式是以一个寄存器的内容为基址,以另一个寄存器的内容为偏移量,两者相加作为存储器的地址。指令格式如下: LDR Rd,[Rn,Rm] ;加载一个字数据 STR Rd,[Rn,Rm] ;存储一个字数据 LDRH Rd,[Rn,Rm] ;加载一个无符号半字数据 STRH Rd,[Rn,Rm] ;存储一个无符号半字数据 LDRB Rd,[Rn,Rm] ;加载一个无符号字节数据 STRB Rd,[Rn,Rm] ;存储一个无符号字节数据 LDRSH Rd,[Rn,Rm] ;加载一个有符号半字数据 LDRSB Rd,[Rn,Rm] ;存储一个有符号半字数据 其中:Rd 表示加载或存储的寄存器。必须为R0~R7。 Rn 表示基址寄存器。必须为R0~R7。 Rm 表示内含数偏移量的寄存器,必须为R0~R7 。
单寄存器访问指令——寄存器偏移指令编码 L用于区别加载(L为1)或存储(L为0) 指令执行的条件码: Rd:源或目标寄存器 Rn:基址寄存器 00b:LDR/STR指令; 01b:LDRH/STRH指令; 10b:LDRB/STRB指令; Rd:源或目标寄存器 Rn:基址寄存器 Rm:偏移量寄存器 说明:当opcode位为11b时,L位为0代表指令“LDRSB“,L位为1代表指令“LDRSH”
单寄存器访问指令——寄存器偏移寻址 注意:进行字数据访问时,必须保证传送地址为32位对齐。进行半字数据访问时,必须保证传送地址为16位对齐。 应用示例: LDR R3,[R1,R0] STR R1,[R0,R2] LDRH R6,[R0,R1] STRH R0,[R4,R5] LDRB R2,[R5,R1] STRB R1,[R3,R2] LDRSH R7,[R6,R3] LDRSB R5,[R7,R2] 注意:进行字数据访问时,必须保证传送地址为32位对齐。进行半字数据访问时,必须保证传送地址为16位对齐。
单寄存器访问指令——相对偏移寻址 这种寻址方式是以PC或SP寄存器的内容为基址,以一个立即数为偏移量,两者相加作为存储器的地址。指令格式如下: LDR Rd,[PC,#immed_8×4] LDR Rd,label LDR Rd,[SP,#immed_8×4] STR Rd,[SP,#immed_8×4] 其中:Rd 表示加载或存储的寄存器。必须为R0~R7。 immed_8×4 表示偏移量,取值范围是(0~255)×4 。 label 表示程序相对偏移表达式,Label必须在当前指令之后的1KB范围内。
单寄存器访问指令——相对偏移指令编码 PC相对偏移LDR指令编码 SP相对偏移LDR/STR指令编码 L:用于区别加载(L为1)或存储(L为0) immed8:偏移量 Rd:目标或源寄存器
单寄存器访问指令——相对偏移寻址 注意:以PC作为基地址的相对偏移寻址指令只有LDR,而没有STR指令。 应用示例: LDR R0,[PC,#0x08] ;读取PC+0x08地址上的字数据, ;保存到R0中 LDR R7,LOCALDAT ;读取LOCALDAT地址上的 ;字数据,保存到R7中 LDR R3,[SP,#1020] ; 读取SP+1020地址上的字数据, ;保存到R3中 STR R2,[SP] ; 存储R2寄存器的数据到SP ;指向的存储单元 (偏移量为0) 注意:以PC作为基地址的相对偏移寻址指令只有LDR,而没有STR指令。
4.2 指令集介绍 Thumb存储器访问指令 PUSH和POP——寄存器入栈及出栈指令 4.2 指令集介绍 Thumb存储器访问指令 PUSH和POP——寄存器入栈及出栈指令 实现低寄存器和可选的LR寄存器入栈及低寄存器和可选的PC寄存器出栈操作。堆栈地址由SP寄存器设置,堆栈是满递减堆栈。
寄存器入栈及出栈指令 指令格式 指令编码 L用于区别出栈(L为1)或入栈(L为0) PUSH {reglist[,LR]} POP {reglist[,PC]} 其中: reglist 入栈/出栈低寄存器列表,即R0~R7。 LR 入栈时的可选寄存器。 PC 出栈时的可选寄存器。 指令编码 L用于区别出栈(L为1)或入栈(L为0) R用于区别操作寄存器中是否有LR/PC寄存器(有则R为1,否则为0)
寄存器入栈及出栈指令 指令格式 应用示例: PUSH {R0-R7,LR} ;将低寄存器R0~R7全部入栈, ;LR也入栈 PUSH {reglist[,LR]} POP {reglist[,PC]} 其中: reglist 入栈/出栈低寄存器列表,即R0~R7。 LR 入栈时的可选寄存器。 PC 出栈时的可选寄存器。 应用示例: PUSH {R0-R7,LR} ;将低寄存器R0~R7全部入栈, ;LR也入栈 POP {R0-R7,PC} ;将堆栈中的数据弹出到 ;低寄存器R0~R7及PC中
4.2 指令集介绍 Thumb存储器访问指令 LDMIA和STMIA——多寄存器加载/存储指令 4.2 指令集介绍 Thumb存储器访问指令 LDMIA和STMIA——多寄存器加载/存储指令 可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDMIA为加载多个寄存器;STMIA为存储多个寄存器。使用它们允许一条指令传送8个低寄存器R0~R7的任何子集。
多寄存器加载/存储指令 指令格式 指令编码 L用于区别加载(L为1)还是存储(L为0) LDMIA Rn!,reglist STMIA Rn!,reglist 其中: Rn 加载/存储的起始地址寄存器。Rn必须为R0~R7。 reglist 加载/存储的寄存器列表。寄存器必须为R0~R7。 指令编码 L用于区别加载(L为1)还是存储(L为0)
多寄存器加载/存储指令 LDMIA/STMIA 的主要用于数据复制、参数传送等。进行数据传送时,每次传送后地址加4。 若Rn在寄存器列表中: 对于LDMIA指令,Rn的最终值是加载的值,而不是增加后的地址; 对于STMIA指令,若Rn是寄存器列表中的最低数字的寄存器,则Rn存储的值为Rn在初值,其它情况不可预知。 应用示例: LDMIA R0!,{R2-R7} ;加载R0指向的地址上的多字数据, ;保存到R2~R7中, R0的值更新。 STMIA R1!,{R2-R7} ;将R2~R7的数据存储到R1指向的 ;地址上,R1值更新
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
4.2 指令集介绍 Thumb数据处理指令 Thumb数据处理指令涵盖了编译器需要的大多数操作。大部分的Thumb数据处理指令采用2地址格式,不能在单指令中同时完成一个操作数的移位及一个ALU操作。所以数据处理操作比ARM状态的更少,并且访问寄存器R8~R15受到限制。数据处理指令分为两类: 数据传送指令 算术逻辑运算指令
4.2 指令集介绍 Thumb数据处理指令——数据传送指令 助记符 操作 影响标志 MOV Rd,#expr 4.2 指令集介绍 Thumb数据处理指令——数据传送指令 助记符 操作 影响标志 MOV Rd,#expr Rd←expr,Rd为R0~R7 影响N、Z MOV Rd,Rm Rd←Rm,Rd、Rm均可为R0~R15 Rd和Rm均为R0~R7时,影响N、Z,清零C、V MVN Rd,Rm Rd←(~Rm) ,Rd、Rm均为R0~R7 NEG Rd,Rm Rd←(-Rm) ,Rd、Rm均为R0~R7 影响N、Z、C、V
数据传送指令——MOV MOV指令将8位立即数或寄存器传送到目标寄存器中。其指令格式如下: 指令编码(立即数传送) 指令编码(寄存器传送) MOV Rd,#expr MOV Rd,Rm 其中:Rd 目标寄存器。MOV Rd,#expr时,Rd必须在R0~R7之间。 exper 8位立即数,即0~255。 Rm 源寄存器。为R0~R15。 指令编码(立即数传送) 指令编码(寄存器传送)
数据传送指令——MOV 注意: 应用示例: MOV R1,#0x10 ; R1=0x10 MOV R0,R8 ; R0=R8 “MOV Rd,#expr”指令会更新N和Z标志,对标志C和V无影响。 “MOV Rd,Rm”指令,若Rd或Rm是高寄存器(R8~R15),则标志不受影响,若Rd或Rm都是低寄存器(R0~R7),则更新标志N和Z,且清除标志C和V。 应用示例: MOV R1,#0x10 ; R1=0x10 MOV R0,R8 ; R0=R8 MOV PC,LR ; PC=LR,子程序返回
数据传送指令——MVN MVN指令将寄存器Rm按位取反后传送到目标寄存器Rd中。指令的执行会更新N和Z标志,对标志C和V无影响。其指令格式如下: MVN Rd,Rm 其中:Rd 目标寄存器。MOV Rd,#expr时,Rd必须在R0~R7之间。 Rm 源寄存器。为R0~R15。 指令编码
数据传送指令——MVN MVN指令将寄存器Rm按位取反后传送到目标寄存器Rd中。指令的执行会更新N和Z标志,对标志C和V无影响。其指令格式如下: MVN Rd,Rm 其中:Rd 目标寄存器。MOV Rd,#expr时,Rd必须在R0~R7之间。 Rm 源寄存器。为R0~R15。 应用示例: MVN R1,R2 ; 将R2取反,结果存于R1
数据传送指令——NEG NEG指令将寄存器Rm乘以-1后传送到目标寄存器Rd中。指令会更新N、Z、C和V标志。其指令格式如下: 指令编码 NEG Rd,Rm 其中:Rd 目标寄存器,必须在R0~R7之间。 Rm 源寄存器。为R0~R15。 指令编码
数据传送指令——NEG NEG指令将寄存器Rm乘以-1后传送到目标寄存器Rd中。指令会更新N、Z、C和V标志。其指令格式如下: 应用示例: NEG Rd,Rm 其中:Rd 目标寄存器,必须在R0~R7之间。 Rm 源寄存器。为R0~R15。 应用示例: NEG R1,R0 ; R1=-R0
4.2 指令集介绍 Thumb数据处理指令——算术逻辑运算指令 算术逻辑指令包括以下几类: 算术指令 逻辑运算指令 移位指令 比较指令
算术运算指令——ADD ADD指令将两个数据相加,结果保存到Rd寄存器中。 低寄存器的ADD指令格式: 应用示例: ADD Rd,Rn,Rm ADD Rd,Rn,#expr3 ADD Rd,#expr8 其中:Rd 目标寄存器,必须在R0~R7之间。 Rn 第1个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 exper 3位立即数,即0~7。 expr8 8位立即数,即0~255。 应用示例: ADD R1,R1,R0 ; R1=R0+R1 ADD R1,R1,#7 ; R1=R1+7 ADD R1,#200 ; R1=R1+200
算术运算指令——ADD ADD指令将两个数据相加,结果保存到Rd寄存器中。 高或低寄存器的ADD指令格式: 应用示例: ADD Rd,Rm 其中:Rd 目标寄存器,也是第一个操作数寄存器。 Rm 第2个操作数寄存器。 应用示例: ADD R1,R10 ; R1=R1+R10
算术运算指令——ADD ADD指令将两个数据相加,结果保存到Rd寄存器中。 SP操作的ADD指令格式: 应用示例: ADD SP,#expr 其中:SP 目标寄存器,也是第一个操作数寄存器。 expr 立即数,在-508~+508之间的4的整数倍的数。 应用示例: ADD SP,#-500 ;SP=SP-500
算术运算指令——SUB SUB指令将两个数据相减,结果保存到Rd寄存器中。 低寄存器的SUB指令格式: 应用示例: SUB Rd,Rn,Rm SUB Rd,Rn,#expr3 SUB Rd,#expr8 其中:Rd 目标寄存器,必须在R0~R7之间。 Rn 第1个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 exper 3位立即数,即0~7。 expr8 8位立即数,即0~255。 应用示例: SUB R1,R1,R0 ; R1=R1-R0 SUB R1,R1,#7 ; R1=R1-7 SUB R1,#200 ; R1=R1-200
算术运算指令——SUB SUB指令将两个数据相减,结果保存到Rd寄存器中。 SP操作的SUB指令格式: 应用示例: SUB SP,#expr 其中:SP 目标寄存器,也是第一个操作数寄存器。 expr 立即数,在-508~+508之间的4的整数倍的数。 应用示例: SUB SP,#380 ;SP=SP-380
算术运算指令——ADC ADC指令将Rm的值相加,再加上CPSR中的C条件标志位,结果保存到Rd寄存器。 ADC指令格式: ADC Rd, Rm 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例(64位加法): ADD R0,R2 ADC R1,R3 ;(R1、R0)=(R1、R0)+(R3、R2)
算术运算指令——SBC SBC指令用寄存器Rd减去Rm,再减去CPSR中的C条件标志位的非,结果保存到Rd寄存器。 SBC指令格式: 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例(64位减法): SUB R0,R2 SBC R1,R3 ;(R1、R0)=(R1、R0)-(R3、R2)
算术运算指令——MUL MUL乘法指令用寄存器Rd乘以Rm,结果保存到Rd寄存器。 MUL指令格式: 应用示例: 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例: MUL R0,R1 ;R0=R0×R1
逻辑运算指令——AND AND指令将寄存器Rd的值与寄存器Rm的值按位作逻辑“与”操作,结果保存到Rd寄存器中。 AND指令格式: ADD Rd, Rm 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例: MOV R1,#0x0F AND R0,R1 ; R0=R0 & R1,清零R0高24位
逻辑运算指令——ORR ORR指令将寄存器Rd的值与寄存器Rn的值按位作逻辑“或”操作,结果保存到Rd寄存器中。 ORR指令格式: ORR Rd, Rm 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例: MOV R1,#0x0F ORR R0,R1 ; R0=R0 | R1,置位R0低4位
逻辑运算指令——EOR EOR指令将寄存器Rd的值与寄存器Rn的值按位作逻辑“异或”操作,结果保存到Rd寄存器中。 EOR指令格式: EOR Rd, Rm 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例: MOV R1,#0x0F EOR R0,R1 ; R0=R0 ^ R1,取反R0低4位
逻辑运算指令——BIC BIC指令将寄存器Rd的值与寄存器Rm的值的反码作逻辑“与”操作,结果保存到Rd寄存器中。 BIC指令格式: 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rm 第2个操作数寄存器,必须在R0~R7之间。 应用示例: MOV R1,#0x02 BIC R0,R1 ; 清零R0的第2位,其它位不变
移位指令——ASR ASR指令将数据算术右移,将符号位拷贝到左侧空出的位,移位结果保存到Rd寄存器中。 ASR指令格式: ASR移位操作: ASR Rd, Rs ASR Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~32 ASR移位操作: 若移位位数为32,则Rd清零,最后移出的位保留在标志C中;若移位位数大于32,则Rd和标志C均被清零;若移位位数为0,则不影响C标志。
移位指令——ASR ASR指令将数据算术右移,将符号位拷贝到左侧空出的位,移位结果保存到Rd寄存器中。 ASR指令格式: 应用示例: ASR Rd, Rs ASR Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~32 应用示例: ASR R1,R2 ASR R3,R1,#2
移位指令——LSL LSL指令将数据逻辑左移,空位清零,移位结果保存到Rd寄存器中。 LSL指令格式: LSL移位操作: LSL Rd, Rs LSL Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~31 LSL移位操作: 若移位位数为32,则Rd清零,最后移出的位保留在标志C中;若移位位数大于32,则Rd和标志C均被清零;若移位位数为0,则不影响C标志。
移位指令——LSL LSL指令将数据逻辑左移,空位清零,移位结果保存到Rd寄存器中。 LSL指令格式: 应用示例: LSL R6,R7 LSL Rd, Rs LSL Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~31 应用示例: LSL R6,R7 LSL R1,R6,#2
移位指令——LSR LSR指令将数据逻辑右移,空位清零,移位结果保存到Rd寄存器中。 LSR指令格式: LSR移位操作: LSR Rd, Rs LSR Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~32 LSR移位操作: 若移位位数为32,则Rd清零,最后移出的位保留在标志C中;若移位位数大于32,则Rd和标志C均被清零;若移位位数为0,则不影响C标志。
移位指令——LSR LSR指令将数据逻辑右移,空位清零,移位结果保存到Rd寄存器中。 LSR指令格式: 应用示例: LSR R3,R0 LSR Rd, Rs LSR Rd,Rm,#expr 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 Rm 立即数移位的源寄存器,必须在R0~R7之间 expr 立即数移位位数,值为1~32 应用示例: LSR R3,R0 LSR R5,R2,#2
移位指令——ROR ROR指令将数据循环右移,寄存器右侧移出的位放入左侧空出的位上,移位结果保存到Rd寄存器中。 ROR指令格式: ROR Rd, Rs 其中:Rd 目标寄存器,也是第一个操作数寄存器,必须在R0~R7之间。 Rs 寄存器控制移位中包含移位位数的寄存器,必须在R0~R7之间 ROR移位操作: 应用示例: ROR R3,R0
比较指令——CMP CMP指令使用寄存器Rn的值减去第二个操作数的值,根据操作的结果更新CPSR中的N、Z、C和V标志位。 ROR指令格式: CMP Rn,Rm CMP Rn,#epr 其中:Rn 第一个操作数寄存器,必须在R0~R7之间。 Rm 第二个操作数寄存器,必须在R0~R7之间。 expr 立即数,值为0~255 应用示例: CMP R1,#10 ;R1与10比较,设置相关标志位 CMP R1,R2 ;R1与R2比较,设置相关标志位
比较指令——CMN CMN指令使用寄存器Rn的值加上寄存器Rm的值,根据操作的结果更新CPSR中的N、Z、C和V标志位。 ROR指令格式: 其中:Rn 第一个操作数寄存器,必须在R0~R7之间。 Rm 第二个操作数寄存器,必须在R0~R7之间。 应用示例: CMN R0,R2 ;R0与-R2比较,设置相关标志位
比较指令——TST TST指令将寄存器Rn的值与寄存器Rm的值按位作逻辑“与”操作,根据操作的结果更新CPSR中的N、Z、C和V标志位。 其中:Rn 第一个操作数寄存器,必须在R0~R7之间。 Rm 第二个操作数寄存器,必须在R0~R7之间。 应用示例: MOV R0,#0x01 TST R1,R0 ;判断R1的最低位是否为0
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
4.2 指令集介绍 Thumb分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} 4.2 指令集介绍 Thumb分支指令 助记符 说明 操作 条件码位置 B label 分支指令 PC←label B{cond} BL label 带链接的分支指令 LR←PC-4,PC←label 无 BX Rm 带状态切换的分支指令 PC←label,切换处理器状态
分支指令——B B指令跳转到指定的地址执行程序,它是Thumb指令集中的唯一有条件执行指令。如果使用了条件执行,那么跳转范围在-252~+256字节内。如果没有使用条件执行,那么跳转范围在±2K内。 B指令格式: B{cond} label 其中:label 表示程序标号。 应用示例: B WAITB ;WAITB标号在当前指令的±2K范围内 BEQ LOOP1 ;LOOP1标号在当前指令的-252~+256范围内
分支指令——BL BL指令在跳转到指定地址执行程序前,将下一条指令的地址拷贝到R14链接寄存器中。 BL指令格式: BL label 其中:label 表示程序标号。 注意:由于BL指令通常需要大的地址范围,很难用16位指令格式实现,为此,Thumb采用两条这样的指令组合成22位半字偏移(符号扩展为32位),使指令转移范围为±4MB。 应用示例: 反汇编代码: ADD R0,R1 BL RstInit [0x1809] add r1,r1,r0 [0xf9dcf000] bl RstInit 指令机器码 汇编指令 32位长的机器码
分支指令——BX BX指令是带状态切换的分支指令,跳转地址由Rm指定,同时根据Rm的最低位的值切换处理器状态,当最低两位均为0时,切换到ARM状态。 BX指令格式: BX Rm 其中:Rm 保存有目标地址的寄存器。 应用示例: ADR R0,ArmFun ;将ARM程序段地址存入R0 BX R0 ;跳至R0指定的地址,并切换到ARM状态
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
Thumb杂项指令——SWI SWI指令用于产生软中断,从而实现从用户模式变换到管理模式,CPSR保存到管理模式的SPSR中,同时程序跳转到SWI向量。在系统模式下也可以使用SWI指令,处理器同样能切换到管理模式。(参数传递的方法参看ARM指令SWI的使用) SWI指令格式: SWI immed_8 其中: immed_8 8位立即数,值为0~255之间的整数。 应用示例: SWI 1 ;软中断,中断立即数为0 SWI 0x55 ;软中断,中断立即数为0x55
Thumb指令小节目录 1.Thumb指令集与ARM指令集的区别 2.存储器访问指令 3.数据处理指令 4.分支指令 5.杂项指令 6.伪指令
Thumb伪指令——ADR ADR伪指令将基于PC相对偏移的地址值读取到寄存器中。 ADR指令格式: 应用示例: ADR R0,TxTab ADR register,expr 其中:register 加载的目标寄存器 expr 地址表达式。偏移量必须是正数并小于1KB。 expr必须是局部定义的,不能被导入。 应用示例: ADR R0,TxTab ... TxTab DCB “ARM7TDMI”,0 地址范围不超过1KB
Thumb伪指令——LDR LDR伪指令用于加载32位的立即数或一个地址值到指定寄存器。在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。详细说明参看ARM伪指令部分。 LDR指令格式: LDR register,=expr/label-expr 其中:register 加载的目标寄存器 expr 32位立即数 label-expr 基于PC的地址表达式或外部表达式。 应用示例: LDR R0,=0x12345678 ;加载32位立即数0x123456778 LDR R0,=DATA_BUF+60 ;加载DATA_BUF地址+60 ... LTORG ;声明文字池 地址范围不超过1KB
Thumb伪指令——NOP NOP伪指令在汇编时将被替换成一条Thumb空操作的指令。比如可能为“MOV R0,R0”指令。NOP伪指令可用于延时操作。 应用示例(延时子程序): Delay NOP ;空操作 NOP SUB R1,R1,#1 ;循环次数减一 ;不需要加‘S’标志,就可以影响CPSR标志位 BNE Delay ;如果循环没有结束,跳转Delay继续 MOV PC,LR ;子程序返回