arm指令集——跳转指令

Green Green     2022-08-13     325

关键词:

 

 

ARM 汇编指令条件执行

在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位。在数据处理指令中使用S后缀来实现该功能。

 

不要在CMP,CMN,TST或者TEQ指令中使用S后缀。这些比较指令总是会更新标志位。

 

在Thumb模式下,所有数据处理指令都更新CPSR中的标志位。有一个例外就是:当一个或更多个高寄存器被用在MOV和ADD指令时,此时MOV和ADD不能更新状态标志.

 

几乎所有的ARM指令都可以根据CPSR中的ALU状态标志位来条件执行。参见表2-1条件执行后缀表。

 

在ARM模式下,你可以:

 

  • 根据数据操作的结果更新CPSR中的ALU状态标志;
  • 执行其他几种操作,但不更新状态标志;
  • 根据当前状态标志,决定是否执行接下来的指令。

 

在Thumb模式,大多数操作总是更新状态标志位,并且只能使用条件转移指令(B)来实现条件执行。该指令(B)的后缀和在ARM模式下是一样的。其他指令不能使用条件执行。

 

ALU状态标志

 

CPSR寄存器包含下面的ALU状态标志:

  N       Set when the result of the operation was Negative
  Z Set when the result of the operation was Zero
  C Set when the operation result in a Carry(发生进位,或借位)
  V Set when the operation caused oVerflow(操作造成溢出)
  Q ARM architecture v5E only sticky flag

 

 

 

 

 

 

 

2.5.2 执行条件

 

N,Z,C,V相关的条件码后缀如下表所列:

 

技术分享

示例1

  ADD  r0, r1, r2              ; r0 = r1 + r2, 不更新标志位
  ADDS  r0, r1, r2      ; r0 = r1 + r2, 后缀S表示更新标志位
  ADCSS  r0, r1, r2      ; If C 标志为1,则执行r0 = r1 + r2, 且更新标志,
  CMP  r0, r1            ; CMP指令肯定会更新标志. 

示例2 求最大公约数

gcd
  CMP r0, r1    
  BEQ end    ; r0 = r0 结束程序
  BLT less    ; r0 < r1 跳转至 less
  SUB r0, r0, r1  ; r0 > r1时 r0 = r0 - r1
  B gcd  ; 条件都不满足是继续循环
less
  SUB r1, r1, r0    ; r0 < r1 r1 = r1 - r0
  B gcd
end

示例3

MAIN
  mov r1, #1   mov r2, #1   cmp r1, r2   beq FUNC      ;if(eq) b FUNC => 实质:if(z == 1) b FUNC   bne FUNC    ;实质:if(z == 0) b FUNC   mov r3, #3   mov r4, #4 FUNC   mov r5, #5   mov r6, #6

 

寻址方式

 

基地址变址寻址方式

 

种类 格式 模式
1 [Rn, #±<offset_12]> 立即数前索引寻址
2 [Rn, ±Rm] 寄存器前索引寻址
3 [Rn, Rm, <shift>#<offset_12>] 寄存器位移的前索引寻址
4 [Rn, #±<offset_12>]! 立即数自动索引寻址
5 [Rn, ±Rm]! 寄存器自动索引寻址
6 [Rn, Rm, <shift<#<offset_12>]! 寄存器移位的自动索引寻址
7 [Rn], #±<offset_12> 立即数后索引寻址
8 [Rn], ±<Rm> 寄存器后索引寻址
9 [Rn], ±<Rm>, <shift>#<offset_12> 带移位的寄存器后索引寻址

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

寄存器前索引寻址

  mov r0, #0x40000000
  mov r1, #0xF000000F
  str r1, [r0, #4]  ;将 r1 中的数据存储到地址为 r0 + 4 的内存空间中

 

寄存器移位的前索引寻址

  mov r2, #8
  str r1, [r0, r2, lsl #1]  ;将 r1 中的数据存储到地址为 r0 + (r2 << 1)的内存空间中

 

 

寄存器后索引寻址

  str r1, [r0], #4  ;将 r1 中的数据存储到地址为 r0 的内存空间中,然后 r0 = r0 + 4

 

寄存器自动索引寻址 

str r1, [r0, #4]!  ;将 r1 中的数据存储到 r0 + 4 的内存空间中, 然后 r0 = r0 + 4

 

 

 多寄存器寻址/块拷贝寻址  LDM STM

对栈进行操作是,使用较多  比如说 用 IA 自动索引寻址存,就用 DB 自动索引读

 

 

Load/Store指令

Load/store是一组内存访问指令,用来在ARM寄存器和内存之间进行数据传送,ARM指令中有3种基本的数据传送指令。

  1. 单寄存器 Load/Store 内存访问指令(single register):这些指令为ARM寄存器和存储器提供了更灵活的单数据项传送方式。数据可以使字节,16位半字或32位字
  2. 多寄存器 Load/Store 内存访问指令:可以实现大量数据的同时传送,主要用于进程的进入和退出、保存和恢复工作寄存器以及复制寄存器中的一片(一块)数据
  3. 但寄存器交换指令(single register swap): 实现寄存器数据和内存数据进行交换,而且是在一条指令中完成,执行过程中不会受到中断干扰

单寄存器Load/Store指令

LDR指令:用于从内存中将一个32位的字读取到目标寄存器  指令格式  LDR{<cond>} <Rd>, <addr_mode> 

;指令举例
  LDR R1, [R0, #0x12]  ;将R0 + 12地址处的数据读出,保存到R1中(R0保持不变)
  LDR Rd,[Rn], #0x04 ;立即数后索引寻址,Rn的值用作传输数据的存储地址。在数据传送后,将偏移量 0x04 与Rn相加,记过写回到 Rd中

 

STR指令:用于将一个32位的字节数据写入到指令中指定的内存单元  指令格式  STR{<cond>} <Rd>,<addr_mode> 

;LOAD/STORE指令
;向内存写入数据 STR
mov r0, #40000000
mov r1, #ff000000
str r1, [r0]  ;用于将一个32位的字数据写入到指令指定的内存单元(以 r0 值为起始地址的 4byte 内存单元)
strb r1, [r0]  ;将r1 中的 [7:0]存储到 r0 对应的内存空间
strh r1, [r0]  ;将r1 中的 [15:0]存储到 r0 为起始地址的两个字节的内存空间
          ;在对数据进行操作时,应根据数据本身的属性(几个字节)进行操作

 

多寄存器Load/Store指令

LDM指令:实现数据从连续的内存单元中读取到指令指定的寄存器列表中。值得注意的是 LDM指令和STM指令:序号的寄存器对应内存中高地址的数据

指令格式: LDM{<cond>}<addressing_mode> <Rn>{!}, <registers> 

STM指令:实现将指令中寄存器列表里的数值写入到一块连续的内存单元之中

指令格式: STM{<cond>} <addressing_mode> <Rn>{!}, <register> 

LDM/STM <cond>的几种寻址方式:

  格  式 地址变化格式  
1 IA(Increment After) 后递增方式 先存储后增长
2 IB(Increment Before) 先递增方式 现增长后存储
3 DA(Decrement After) 后递减方式 先存储后递减
4 DB(Decrement Before) 先递减方式 先递减后存储

   

 

 

 

 

mov r0, #0x40000000
  mov r1, #1
  mov r2, #2
  mov r3, #3
  ldm r0, {r1-r3}
  stm r0, {r1-r3}  ;将 r1 - r3 寄存器(连续寄存器)中的数据存储到 以 r0 位起始地址的内存空间中
  stm r0, {r3, r1}   ;将 r1 、 r3 寄存器(不连续寄存器)中的数据存储到 以 r0 位起始地址的内存空间中
            ;批量操作时,低编号的寄存器数据对应内存中的低地址
  stm r0!, {r1-r3}  ;寄存器批量存储,也适用自动索引寻址, 操作完成后   r0 = r0 + (寄存器个数)*4

 

 

跳转指令

B和BL跳转指令

MAIN
  mov r0, #2
  mov r1, #3
  mov lr, pc  ;B 指令不会自动保存 PC;手动保存返回地址、当前PC
  b lable    ;跳转到标号 FUNC (标号的实质是地址)
  mov r3, r0
FUNC
  sub r0, r1, r0
  mov pc,lr  ;返回主程序继续执行

跳转指令是改变指令执行顺序的标准方式 (控制流指令)

B 和 BL 指令都是 相对跳转(短跳转) 指令,通过偏移量跳转, 最大跳转距离是 ±32M

使用 mov pc, <>可以实现 对跳转(长跳转)(不会保存当前 PC 值)

关于B指令和BL指令最大跳转距离是 ±32M:

  ARM汇编每条指令占用 4byte,生成机器码 B 、BL存放在bits[31:24], bits[23:0]是立即数空间,可以表示 2^24个地址。由于每条汇编指令占用4byte字节(最低两位都为 0),因此可以使用 24位二进制数来表示 26 位的寻址空间。

B指令和BL指令的区别

  • B指令在使用时不会对当前 PC 值进行保存,为保证跳转指令执行后能正常返回,要手动对其进行保存
  • BL (带连接的跳转指令)能够在跳转时对当前 PC 值自动进行保存。 

 

带状态切换的跳转指令 BX

不会保存跳转前 PC 值 ±32M范围

带状态切换(ARM&Thmub)的跳转指令BX  ,语法格式:BX{<cond>} <Rm> ,使程序跳转到指令中参数 Rm 指定的地址进行执行。并将 Rm 的第 0 位复制到 CPRS 中的 T 位, bit[31: 1]存入PC。

   PC也可以作为 Rm 寄存器使用,当PC作为 Rm 使用时,指令 BX PC 便跳转到当前指令下面第 2 条指令出执行(三级流水线:当前正在执行的指令地址为 PC - 8,正在译码的指令为 PC - 4, 正在取指的指令是 PC)。但这种方式不值得推荐,最好使用下面的方式完成这种跳转。

  mov pc, pc
;或者
  add pc, pc, #0

 

带状态切换的连接跳转指令

 与BX功能一致,但会自动保存跳转时的 PC 值,语法格式: BLX <target_add> 。target_add为指令的跳转目标地址,该地址是一个立即数

 

状态(寄存器)操作指令

ARM指令集提供了两条指令(MSR,MRS),用来操作状态寄存器PSR

MRS指令,语法格式 MRS {cond} Rd, PSR 用于把CPSR或SPSR的值传送到一个寄存器;

MSR指令,语法格式 MSR {cond} PSR_filed, #immed_8r 或 MSR {cond} PSR_filed, Rm 用于把一个寄存器的值或一个立即数传送到CPSR或SPSR;使用这两条只能可以实现对程序状态寄存器的状态修改操作。

  在使用MSR指令对PSR进行修改操作时,要通过field设置状态寄存器需要操作的域。状态寄存器的32位被分为4个8位的域(filed)分别为:bits[31:24]条件域,用 F 表示; bits[23: 16]状态域,用 S 表示;bits[15:8]预留域,用 X 表示;bits[7:0]控制域,用 C 表示。

;程序举例:是能IRQ中断
ENABLE_IRQ
  MRS  R0,CPSR  
  BIC   R0,R0,#080  ;将CPSR bit7 I 清零,是能IRQ
  MSR  CPSR_c,R0  ;典型的读-改-回写操作
  MOV   PC,LR

 

 

异常产生指令

ARM指令集提供了两条产生异常的指令(中断指令 SWI,断点中断指令 BKPT),通过这两条指令可以用软件的方法实现异常。 

中断指令

软件中断指令 SWI (software Interrupt)用于产生软中断,实现从用户模式切换到管理模式,CPSR保存到管理模式的 SPSR 中,执行转移到 SWI 向量。

语法格式 SWI {<cond>} <immed_24>  immed_24 为中断号

 

 

 

栈:按增长方向分为 递增栈;递减栈

按压栈操作顺序(sp位置)分为;满栈和空栈

满栈(FULL):sp指向栈顶元素

空栈(EMPTY):sp指向栈顶元素相邻位置

根据栈的不同分类,将其寻址方式分为以下4种

1)满递减 FD(Full Descending)

2)空递减 ED(Empty Descending)

3)满递增 FA(Full Asceding)

4)空递增 EA(Empty Ascending)

 习惯上大都使用满减栈。

压栈出栈的几种操作方式 

  ;初始化栈 
  mov sp, #0x40000018
MAIN
  mov r0, #1
  mov r1, #1
  bl FUNC          
  add r2, r0, r1
FUNC
  ;压栈保护现场
  stmfd sp!, {r0, r1}
  mov r0, #2
  mov r1, #4
  sub r2, r1, r0
  ;出栈恢复现场
  ldmfd sp!, {r0, r1}
  mov pc, lr   

;初始化栈 
MAIN
  mov r0, #1
  mov r1, #1
  bl FUNC          
  add r2, r0, r1
FUNC
  ;压栈保护现场
  stmfd sp!, {r0, r1, lr}
  mov r0, #2
  mov r1, #4
  sub r2, r1, r0
  ;出栈恢复现场
  ldmfd sp!, {r0, r1, pc}   

 

 

 

swp r0, r1, [r2]
 ;将r0中的数据放入内存地址是r2的地址空间,同时将r2中的值放入r1寄存器
 ;处理器与内存之间进行数据交换  交换过程不会被打断

 







arm汇编指令

ARM处理器的指令集可以分为跳转指令、数据处理指令、程序状态寄存器(PSR)处理指令、加载/存储指令、协处理器指令和异常产生指令6大指令一、跳转指令跳转指令用于实现程序流程的跳转跳转指令分类Ⅰ.使用专门的跳转指令... 查看详情

arm指令集

  ARM指令可以分为数据处理类指令、跳转类指令、异常中断指令、Load/Store指令、协处理器指令、操作CPSR指令等几类。1、数据处理指令其中第二个操作数<shifter_operand>可以有三种形式:(1)立即数形式   &nb... 查看详情

arm指令和thumb指令有啥区别

  Thumb指令集与ARM指令的区别一般有如下几点:  跳转指令  程序相对转移,特别是条件跳转与ARM代码下的跳转相比,在范围上有更多的限制,转向子程序是无条件的转移。  数据处理指令  数据处理指令是对通用寄... 查看详情

arm指令分类及其寻址方式

ARM指令分类及其寻址方式一:ARM指令的分类  ARM指令集可以分为以下6类:  •跳转指令;  •数据处理指令;  •程序状态寄存器(PSR)传输指令;  •load/store指令;  •协处理器指令;  •异常... 查看详情

thumb指令集与arm指令集的差别

Thumb指令集     Thumb指令能够看做是ARM指令压缩形式的子集。是针对代码密度【1】的问题而提出的。它具有16为的代码密度。Thumb不是一个完整的体系结构,不能指望处理程序仅仅运行Thumb指令而不支持ARM指令集... 查看详情

arm指令集thumb指令集thumb-2指令集

MCU使用什么指令集主要由内核决定的,比如Cortex-M3使用的是Thumb-2指令集  ARM指令集:编代码全部是32bits的,每条指令能承载更多的信息,因此使用最少的指令完成功能,所以在相同频率下运行速度也是最快的,但也因为... 查看详情

arm精简指令集与复杂指令集

...平板成为同一个硬件下的系统。而ARM使用的就是CISC精简指令集,大学汇编没有学好,只能在此补上...??CISCComplexInstructionSetComputer即为复杂指令集,CISC的硬件指令更多,因此它的兼容性更好,执行复杂操作更快,因此在游戏机、... 查看详情

arm汇编指令

ARM汇编指令基于RISC架构,因此其指令集非常精简,本文重点介绍必须掌握的相关指令。1.算数和逻辑指令mov指令:movr0,#1@0x1--->r0mvn指令:mvnr0,#0@0x0取反--->r0add指令:addr0,r1,r2@r0=r1+r2sub指令:subr0,r1,r2@r0=r1-r2and指令:andr0,r1,r2@r0... 查看详情

嵌入式:arm指令集分类及编码

ARM指令集是32位的,程序的启动都是从ARM指令集开始。主要是以下三个方面:指令分类及指令格式条件执行指令集编码指令分类及指令格式ARM指令使用的基本格式如下:〈opcode〉〈cond〉S〈Rd〉,〈Rn〉,〈operand2〉<>是必须项,... 查看详情

[arm]arm指令集

ARM指令集 一、ARM指令的格式和分类经典ARM指令格式如下:<opcode><cond>S<Rd>,<Rn>,<operand2><opcode> <cond> S  <Rd>,<Rn>,<operand2>& 查看详情

arm指令集—swp指令

ARM指令集—SWP指令SWP和SWPB是ARM指令集中对存储单元的原子操作。即对存储单元的一次读和一次不可被切割。SWP和SWPB分别完毕存储器和寄存器之间一个字(32bit)和一个字节(8bit)的数据交换。SWP指令主要是完毕ARM体系架构处理... 查看详情

汇编跳转指令bblbxblx和bxj的区别(代码片段)

跳转指令用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转:(1)使用专门的跳转指令。(2)直接向程序计数器PC写入跳转地址值。 通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任... 查看详情

arm指令集

S后缀:  在指令后面加上S后缀后,指令运行后的结果会改变CPSR中条件标志位的值。某些指令不加S后缀也会无条件改变CPSR中的条件标志位,如CMP、TST等指令。其他的指令不加S后缀的话,其指令运行的结果是不会改变CPSR... 查看详情

arm体系结构与编程的作品目录

...存储空间1.7.2ARM存储器格式1.7.3非对齐的存储访问操作1.7.4指令预取和自修改代码第2章ARM指令分类及其寻址方式2.1ARM指令集概要介绍2.1.1ARM指令的分类2.1.2ARM指令的一般编码格式2.1.3ARM指令的条件码域2.2ARM指令寻址方式2.2.l数据处理... 查看详情

ios指令集arm64、armv7s、armv7、i386、x86_64

参考技术AARM架构过去称作进阶精简指令集机器(AdvancedRISCMachine,更早称作:AcornRISCMachine),是一个32位精简指令集(RISC)处理器架构,ARM处理器非常适用于移动通讯领域,符合其主要设计目标为低耗电的特性。ARM和Intel处理器... 查看详情

arm汇编指令速记(代码片段)

这里写目录标题1.跳转指令2.数据交互指令3.数据传送指令1.跳转指令B无条件跳转BL带链接的无条件跳转BX带状态切换的无条件跳转BLX带链接和状态切换的无条件跳转Bloc_地址BNE,BEQ2.数据交互指令存储器(主存,内存)寄... 查看详情

arm汇编基础上(代码片段)

ARM是一个精简指令集处理器,其指令集的设计是定长的,也就是其汇编对应的机器码是定长的(2字节或者4字节)。那么对于定长而言,其优点就是更快的被执行,因为这样CPU取指令译码的速度相对x86的CPU... 查看详情

arm指令周期

 1.大部分算术运算和逻辑运算指令都是单周期的,例如加法、减法、位级运算和移位 2.乘法指令根据操作数位数的不同,从2-5个周期都有可能。 3.无条件跳转语句和跳转语句成功跳转,需要重新填充流水线,因此至少... 查看详情