当前位置: 首页 > article >正文

B Label, BL Label 指令

B Label, BL Label

跳转到标号Label 处,B跳转指令的跳转范围大小为[0,32MB], 可以往前跳,也可以往后条,无条件跳转指令B主要用在循环,分之结构的汇编程序中,使用示例如下。

CMP R2, #0

REQ label 若R2 = 0,则跳转到label处。

label:

....

2 BL label

BL跳转指令表示带链接的跳转,在跳转之前,BL指令会先将当前指令的下一条指令地址(即返回地址)保存到LR寄存器中,然后跳转到label处执行,BL指令一半用在函数调用的场合,主函数在跳转到自函数执行之前,会先将返回地址,即当前跳转指令的吓一条指令地址保存到LR寄存器中,自函数执行结束后,LR寄存器中的地址将被赋值给PC,处理器就可以返回到原来的主函数中继续运行了。

3 BX Rm

BX 表示带状态切换的跳转,Rm寄存器中保存的是跳转地址,要跳转的目标地址处可能是ARM指令,也可能是Thumb指令,处理器根据Rm[0]位决定是切换到ARM状态还是切换到Thumb状态。

0 表示目标地址处是ARM指令,在跳转之前要先切换到Thumb状态。

1 表示目标地址处是Thumb指令,在跳转之前要先切换的跳转,使用方法和上面相同。不再赘述。

3.3 ARM寻址方式

    ARM属于RISC体系结构,一个ARM汇编程序中的大部分汇编指令,基本上都和数据传输有关,在内存一寄存器,内存一内存,寄存器一寄存器之间来回传输数据。不通的ARM指令又有不同的寻址方式,比较常见的寻址方式有寄存器寻址,立即寻址,寄存器偏移寻址,寄存器间接寻址,基止寻址,多寄存器寻址,相对寻址等。

3.3.1 寄存器寻址

    寄存器寻址比较简单,操作数保存在寄存器中,通过寄存器名就可以直接对寄存器中的数据进行读写。

MOV R1, R2 将寄存器R2中的值传递到R1

ADD R1, R2, R3; R1 = R2 + R3

3.3.2 立即数殉职

   在立即数旬之中,ARM指令中的操作数为一个常数,立即书以#

为前缀,0x前缀表示该立即数为十六进制,不加前缀默认是十进制。

ADD R1, R1, #1 将R1寄存器中的值加1,并将结果保存到R1中。

MOV R1, #0xff 将十六进制常熟0xff 写到R1寄存器中

MOV R1, #12 将十进制常熟12放到R1寄存器中

ADD R1,R1,#16 R1 = R1 + 16

3.3.3 寄存器偏移寻址

   寄存器偏移寻址可以看作寄存器寻址的一种特特例,通过第二个操作数operand2 的灵活配置,我们可以将第二个操作数做各种左移和右移操作,作为新的操作数使用。

MOV R2,R1,L5L, #3

ADD R3, R2, R1, L5L, #3

ADD R3, R2, R1, L5L, R0

常见的移位操作有逻辑移位和算数移位,两者的区别是,逻辑移位无论是左移还是右移,空缺的一律补0,而算数移位则不同,左移补0,右移补符号位。

3.3.4 寄存器间接寻址

    寄存器间接寻址主要用来在内存和寄存器之间传递数据,寄存器中保存的是数据在内存中的存储地址,我们通过这个地址就可以在寄存器和内存之间传输数据,C预研中的指针操作,在汇编层次其实就是使用寄存器间接寻址实现的,寄存器间接寻址的使用示例以及说明如下所示。

LDR R1,[R2] 将R2中的值作为地址,取该内存地址上的数据,保存到R1

STR R1, [R2] 将R2中的值作为地址,将R1寄存器的值写入该内存地址。

3.3.5 基址寻址

   基址殉职其实也属于寄存器间接寻址。两者的不同之处在于,基址寻址将寄存器中国呢的地址与一个偏移量相加,生成一个新地址,然后基于这个新地址去访问内存。

   LDR R1, [FP,#2] 将FP中的值加2作为新的地址,取改地址上的值保存到R1

   LDR R1, [FP, #2] 

LDR R1,[Fp, R0] 取FP + R0位置的值存入R1

   STR R1, [FP, #-2] 将R1存入FP - 2地址位置。

  基址寻址一般用在查表,数据访问,函数的栈帧管理等场合,根据偏移的正负,基址寻址又可以分为向前索引寻址和向后索引殉职,如上面的第一条和第三条指令,就是向后缩阴寻址,而第6条指令则为向前索引寻址。

3.3.6 多寄存器寻址

  STM/LDM 指令就属于多寄存器寻址,一次可以传输多个寄存器的值

LDMIA SP!, {R0-R2, R14} 将内存栈中的数据依次弹出到R14, R2,R1,R0

STMDB SP!, {R0-R2,R14} 将R0,R1,R2,R14依次压入栈

STMFD SP!,

  在多寄存器寻址中,用大括号括起来的就是寄存器列表,寄存器之间用逗号隔开,如果是连续的寄存器,还可以使用连续符号连接,如R0R3,就表示R0,R1,R2这4个寄存器,。

LDM/STM指令一半和IA,IB,DA,DB组合使用,分别表示Increase After, Increase Before, Decrease After Decrease Before 

ARM没有专门的入栈和出栈指令,ARM中的栈操作其实就是通过上面所讲的STM/LDM指令和栈指针SP配合操作完成的,栈一半可以分为以下四类

递增栈A 入栈时,SP栈指针从弟弟址往高地址方向增长。

递减栈D 入栈时,SP栈指针从高地址往低地址方向增长

满栈F,SP栈指针总是指向栈顶元素。

空栈E,SP栈指针总是指向栈顶元素。

空栈E,SP栈指针总是指向栈顶元素的下一个空闲的存储单元。

ARM默认使用满递减堆栈,通过STMFD/LDMFD指令配对使用,完成堆栈的入栈和出栈操作,ARM中的PUSH和POP指令其实就是LDM/STM的同义词。


http://www.kler.cn/news/136304.html

相关文章:

  • openjdk17在java方法中创建对象 类加载在C++源码实现步骤
  • 3-petalinux2018.3 摸索记录 - 命令驱动 _ 交叉编译链
  • 攻防世界-流量分析WP
  • 读《认知觉醒》:浅谈费曼技巧
  • 使用 docker 的方式部署 NFS server 提供文件共享能力
  • 2024-网鼎杯第二次模拟练习-web02
  • 基于安卓android微信小程序美容理发店预约系统app
  • 工具及方法 - 多邻国: Duolingo
  • LeetCode第七题整数反转
  • 什么是一阶逻辑?
  • 数据结构【DS】图的遍历
  • 2311rust,到66版本更新
  • 简单模拟 Spring 创建的动态代理类(解释一种@Transactional事务失效的场景)
  • 使ros1和ros2的bag一直互通
  • Go解析soap数据和修改其中数据
  • MR素数测试及 pycryptodome库下 已知MR伪素数以及强伪证 生成指定伪随机数生成器绕过素性检测
  • 网络工程师-HCIA网课视频学习
  • Apache Airflow (十二) :PythonOperator
  • 【Linux】【开发】使用sed命令遇到的乱码问题
  • 内置函数和消息传递API
  • 类与对象(上篇)
  • WinForms C# 导入和导出 CSV 文件 Spread.NET
  • Rust开发——切片(slice)类型
  • -bash: jps: command not found
  • React整理总结(五、Redux)
  • 【左程云算法全讲11】贪心算法 并查集