【物联网】ARM核常用指令(详解):数据传送、计算、位运算、比较、跳转、内存访问、CPSR/SPSR、流水线及伪指令

文章目录

  • 指令格式(重点)
    • 1. 立即数
    • 2. 寄存器位移
  • 一、数据传送指令
    • 1. MOV指令
    • 2. MVN指令
    • 3. LDR指令
  • 二、数据计算指令
    • 1. ADD指令
    • 1. SUB指令
    • 1. MUL指令
  • 三、位运算指令
    • 1. AND指令
    • 2. ORR指令
    • 3. EOR指令
    • 4. BIC指令
  • 四、比较指令
  • 五、跳转指令
    • 1. B/BL指令
    • 2. ldr指令
    • 练习
  • 六、内存访问指令
    • 1. 单内存访问指令
      • 练习
    • 2. 多内存访问指令
      • 示例
    • 3. 栈操作指令
      • 示例
  • 七、CPSR/SPSR操作指令
      • 练习
  • 八、ARM指令流水线分析及伪指令
    • 1. 最佳流水线
    • 2. 内存访问指令流水线
    • 3. 分支流水线
    • 4. ARM伪指令、汇编与C混合编程、Volatile关键字
      • (1)LDR R0,=0x12345678分析
      • (2)LDR R0,=Label 分析
      • (3)LDR R0,Label
      • (4)ADR R0,Label分析
      • (5)如何判别代码在实际内存中运行的地址?


指令格式(重点)

在这里插入图片描述

1. 立即数

一个常数,该常数必须对应8位位图,即一个8位的常数通过,循环右移偶数位得到该数,该数
数为合法立即数。

在指令中表示方法:#数字,例如:#100

快速判定是否是合法立即数:

  • 首先将这个数转换为32bit的16进制形式,例如218=0xDA=0x000000DA
  • 除零外,仅有一位数为合法立即数
  • 除零外,仅有二位数,并且相邻(包括首尾,如0x1000000A)的为合法立即数。
  • 除零外,仅有三位数,并且相邻(包括中间有0相间,例如0x10800000,包括首尾相邻
    如:0x14000003),这三位数中,最高位取值仅能为1、2、3,最低位取值仅能为4、8、C
    中间位0x0~0xF。
    这种组合的为合法立即数。

2. 寄存器位移

将寄存器值读取之后,进行移位运算后,作为操作数2参与运算。支持的移位方式如下:

  • LSL(Logical shift Left)逻辑右移
  • LSR(Logical shift Right)逻辑左移
  • ASR(Arithmetic shift Right)算术右移
r0,lsr #4 表示r0 >>4
r0,lsr r1 表示r0 >>r1
#3,LsL #4 错误,只能是寄存器移位,不能是立即数移位

一、数据传送指令

1. MOV指令

格式:mov 目标寄存器,操作数2
功能:将操作数2的值赋值给目标寄存器

在这里插入图片描述

2. MVN指令

格式:mvn 目标寄存器,操作数2
功能:将操作2取反的值给目标寄存器

在这里插入图片描述

3. LDR指令

格式: LDR 目标寄存器,= 数据
功能: 完成任意的数据传送到目标寄存器
注意: 数据前面不能加#,因为此时数据不按立即数来处理

在这里插入图片描述

二、数据计算指令

1. ADD指令

格式: add 目标寄存器,操作数1操作数2
功能: 将操作数1加上操作数2的结果给目标寄存器
在这里插入图片描述

1. SUB指令

格式: sub 目标寄存器,操作数1操作数2
功能: 将操作数1减去操作数2的结果给目标寄存器

在这里插入图片描述

1. MUL指令

格式: mul 目标寄存器,操作1操作2
功能: 将操作数1乘以操作数2的结果存放在目标寄存器

注意:操作数1操作2必须都是寄存器,并且操作1的寄存器编号不能和目标寄存器一样

在这里插入图片描述

三、位运算指令

1. AND指令

格式: and 目标寄存器,操作数1操作数2
功能: 将操作数1按位与操作数2的结果存放在目标寄存器
在这里插入图片描述

2. ORR指令

格式: orr 目标寄存器,操作数1操作数2
功能: 将操作1按位或操作2的结果存放在目标寄存器

3. EOR指令

格式: eor 目标寄存器,操作1操作2
功能: 将操作数1按位异或操作数2的结果存放在目标寄存器

在这里插入图片描述

4. BIC指令

格式: bic 目标寄存器,操作1操作2
功能: 将操作数1按位与操作数2取反的结果存放在目标寄存器
目标寄存器 = 操作数1 & ~操作数2

在这里插入图片描述

四、比较指令

格式: cmp 寄存器,操作数2
等于寄存器减去操作数2
功能: 将寄存器的值与操作2比较,比较的结果会自动影响CPSR的NZCV

在这里插入图片描述

答案

在这里插入图片描述

五、跳转指令

1. B/BL指令

格式: B/BL 标签
功能: 跳到一个指定的标签,BL 跳转之前,将跳转前的PC的值保存在LR,跳转范围+/- 32M
在这里插入图片描述

NZCV 标志位

标志位含义
N (Negative)结果为负数(Rn < Rm)
Z (Zero)结果为 0(Rn == Rm)
C (Carry)发生借位(无符号比较时 Rn < Rm)
V (Overflow)溢出(有符号计算超出范围)

比较指令 + B 条件跳转

指令条件说明
BEQ labelZ == 1相等(Rn == Rm)时跳转
BNE labelZ == 0不相等(Rn ≠ Rm)时跳转
BGT labelZ == 0 且 N == V大于(Rn > Rm,有符号)时跳转
BGE labelN == V大于等于(Rn ≥ Rm,有符号)时跳转
BLT labelN ≠ V小于(Rn < Rm,有符号)时跳转
BLE labelZ == 1 或 N ≠ V小于等于(Rn ≤ Rm,有符号)时跳转
BHI labelC == 1 且 Z == 0大于(Rn > Rm,无符号)时跳转
BHS labelC == 1大于等于(Rn ≥ Rm,无符号)时跳转
BLO labelC == 0小于(Rn < Rm,无符号)时跳转
BLS labelC == 0 或 Z == 1小于等于(Rn ≤ Rm,无符号)时跳转

2. ldr指令

格式: ldr pc,= 标签名
功能: 将PC指针指闻标签表示的地址
在这里插入图片描述

练习

在这里插入图片描述

答案

在这里插入图片描述

六、内存访问指令

1. 单内存访问指令

LDR 将内存中的值加载到寄存器(读内存)
STR 将寄存器的内容写入内存(写内存)

寄存器间接寻址:寄存器的值是一个地址

LDR ro,[r1 ]     //r0 = *r1
STR ro,[ r1 ] //*r1 = ro

基址变址寻址:将基地址寄存器加上指令中给出的偏移量,得到数据存放的地址

  • A. 前索引
STR r0,[r1,#4] //*(r1 + 4)= r0
LDR r0,[r1,#4] //r0 =*(r1+ 4)
  • B. 后索引
STR r0,[r1],#4   //*r1=r0 &&r1=r1 + 4
LDR r0,[r1],#4   //r0=*r1 &&r1=r1 + 4
  • C. 自动索引
STR r0,[r1,#4]!    //*(r1+4)=r0&&r1=r1+4
LDR r0,[r1,#4]!    //r0=*(r1+4)&&r1 =r1+4

示范:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

练习

将1-10数据存放在基地址为0x4000,0000,将0x4000,0000起始地址的值拷贝到0x4000,0100

答案
在这里插入图片描述

将0x1234写到0x4000,0000,将0xabcd写到0x4000,0004,然后从这两个地址读取数据做案加,最终结果存放在r0

答案2
在这里插入图片描述

2. 多内存访问指令

LDM 将一块内存的数据,加载到多个寄存器中
STM 将多个寄存器的值,存储到一块内存

格式:

LDM{条件}{s}<MODE>基址寄存器{!},{Reglist}^
STM{条件}{s}<MODE>基址寄存器{!},{Reglist}^

mode说明
IA后增加地址
IB先增加地址
DA后减少地址
DB先减少地址

基址寄存器
用于放内存的起始地址

!
最后更新基址寄存器的值

Reglist

  • 多个寄存器,从小到大,中间用 , 隔开,如 {r0,r2,r3}{r0-r7,r10}
  • 寄存器号大的对应内存的高地址,寄存器号小的对应内存的低地址

^

  • 它存在,如果 Reglist 没有 pc 的时候,这个时候操作的寄存器是用户模式下的寄存器
  • LDM 指令中,有 PC 的时候,在数据传送的时候,会将 SPSR 的值拷贝到 CPSR,用于异常的返回

流程图:
在这里插入图片描述
在这里插入图片描述

示例

在这里插入图片描述

3. 栈操作指令

A. 进栈

stmfd sp!,{寄存器列表}

B. 出栈

Idmfd sp!,{寄存器列表}

注意
在对栈操作之前,必须先设置sp的值,进栈和出栈的方式一样,ATPCS标准规定满减栈

流程图:
在这里插入图片描述

堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈
堆栈指针指向下一个待压入数据的空位置,称为空堆栈

在这里插入图片描述

示例

在这里插入图片描述

七、CPSR/SPSR操作指令

A. 读操作

MRS Rn,CPSR/SPSR
将状态寄存器的值,读到通用寄存器中

B. 写操作

MSR CPSR/SPSR,Rn
将通用寄存器的值,写到状态寄存器

练习

A.写一段代码,将CPSR的第I(7)位清0,其他位不变(使能IRQ异常)
B.写一段代码,将CPSR的第I(7)位置1,其他位不变(禁用IRQ异常)

答案
在这里插入图片描述

八、ARM指令流水线分析及伪指令

在ARM核中,为增加处理器指令流的速度,ARM7系列使用3级流水线。允许多个操作同时处理,而非顺序执行。不同的ARM核,流水线的级数是不一样的,ARM核版本越高,流水线级数越多。对于软件工程师编程而言,统一按照三级流水线来分析就可以了。

PC指向正被取指的指令,而非正在执行的指令

在这里插入图片描述

1. 最佳流水线

在这里插入图片描述

该例中用5个时钟周期执行了5条指令,所有的操作都在寄存器中(单周期执行)
指令周期数(CPI)=1

2. 内存访问指令流水线

在这里插入图片描述

该例中,用6周期执行了4条指令,指令周期数(CPI)=1.5

3. 分支流水线

在这里插入图片描述

4. ARM伪指令、汇编与C混合编程、Volatile关键字

伪指令定义:
为了方便程序员使用,编译器设计的指令,这个指令ARM核无法直接识别,需要编译器对他翻译成ARM核所能识别的指令。

(1)LDR R0,=0x12345678分析

再次强调:PC指向正被取指的指令,而非正在执行的指令

如何看内存中的12345678
正在读取的LDR内存是0x0008 加上 PC所在的地址(因为LDR正在执行 所以pc等于0x0000000C预取的值)
也就是0x0008加上pc的值0x0000000C等于0x00000014

在这里插入图片描述

总结

编译器在编译的时候,将Idr r0,=0x12345678翻译成了ldr r0,[pc,#0x0008]这一条读内存的指令。根据PC的值加上偏移量算出0x12345678这个数据在内存的地址,然后使用Idr指令读取这个地址的数据。

(2)LDR R0,=Label 分析

1) 链接地址指定为0x0情况分析

0x00000018等于0x000C加上pc的值0x000C

注意 0x00000018的值是14 这是个值 是编译器算出来的一个值

在这里插入图片描述

在这里插入图片描述

2) 链接地址指定为0x2000情况分析

修改链接地址
在这里插入图片描述

再运行

label的地址也就是0x000c+pc的值0x0000200c=0x00002018

在这里插入图片描述

3) 总结

LDR r0,=Label指令表示将Label的值写入r0,Label的值由指定的代码段运行地址(-Ttext=地址值)来决定。

编译器做法:

  • 首先根据指定的代码段开始的地址,算出Label标签对应的地址值
  • 然后将这个表示的地址值存放在一个位置
  • 生成内存访问指令,根据pc +固定偏移量,找到标签对应值存放的位置

注意
当代码编译结束的时候,标签表示的地址值(根据指定的代码段地址)已经编译死存放在程序文件中了。

(3)LDR R0,Label

LDR R0,Label 表示读取Label表示的地址对应数据

不带=的时候 存的是标签里的内容

在这里插入图片描述

(4)ADR R0,Label分析

动态方式 根据pc的值+0x00000008

之前是静态的 在编译完的时候 label就已经确定值是什么了
这个是动态

举个例子:如果是用LDR我把这个代码放到A内存和B内存运行
这两块内存的值是一模一样的 因为在编译完的时候 label就已经确定值是什么了
如果是ADR A内存的0x0008 和B内存的0x0008 是不一样的
有点难理解

在这里插入图片描述

ADR R0,Label指令表示根据当前的PC的值 +/-偏移量,动态获取当前Label所表示的内存地址

(5)如何判别代码在实际内存中运行的地址?

ADR r0,_start 可以知道,因为他是根据pc的值,动态获取
LDR r0,=_start 无法知道,这条指令不论在哪里运行,r0的值都是固定(取决于指定的链接地址)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/960535.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像处理算法研究的程序框架

目录 1 程序框架简介 2 C#图像读取、显示、保存模块 3 C动态库图像算法模块 4 C#调用C动态库 5 演示Demo 5.1 开发环境 5.2 功能介绍 5.3 下载地址 参考 1 程序框架简介 一个图像处理算法研究的常用程序逻辑框架&#xff0c;如下图所示 在该框架中&#xff0c;将图像处…

病理AI领域基础模型及多实例学习方法的性能评估|顶刊精析·25-01-27

小罗碎碎念 这篇论文聚焦于组织学全切片图像分析&#xff0c;旨在探究多实例学习&#xff08;MIL&#xff09;与基础模型&#xff08;FMs&#xff09;结合的效果。 由于全切片图像&#xff08;WSI&#xff09;分析面临标注有限和模型直接处理困难等问题&#xff0c;MIL成为常用…

Tensor 基本操作2 理解 tensor.max 操作,沿着给定的 dim 是什么意思 | PyTorch 深度学习实战

前一篇文章&#xff0c;Tensor 基本操作1 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 目录 Tensor 基本操作torch.max默认指定维度 Tensor 基本操作 torch.max torch.max 实现降维运算&#xff0c;基于指定的 d…

以太网详解(六)OSI 七层模型

文章目录 OSI : Open System Interconnect&#xff08;Reference Model&#xff09;第七层&#xff1a;应用层&#xff08;Application&#xff09;第六层&#xff1a;表示层&#xff08;Presentation&#xff09;第五层&#xff1a;会话层&#xff08;Session&#xff09;第四…

Spring MVC异常处理机制

文章目录 1. 异常处理的思路2. 异常处理两种方式3. 简单异常处理器SimpleMappingExceptionResolver 1. 异常处理的思路 系统中异常包括两类&#xff1a;预期异常和运行时异常RuntimeException&#xff0c;前者通过捕获异常从而获取异常信息&#xff0c;后者主要通过规范代码开发…

本地大模型编程实战(03)语义检索(2)

文章目录 准备按批次嵌入加载csv文件&#xff0c;分割文档并嵌入测试嵌入效果总结代码 上一篇文章&#xff1a; 本地大模型编程实战(02)语义检索(1) 详细介绍了如何使用 langchain 实现语义检索&#xff0c;为了演示方便&#xff0c;使用的是 langchain 提供的内存数据库。 在实…

[Dialog屏幕开发] 设置方式对话框

阅读该篇文章之前&#xff0c;可先阅读下述资料 [Dialog屏幕开发] 设置搜索帮助https://blog.csdn.net/Hudas/article/details/145381433?spm1001.2014.3001.5501https://blog.csdn.net/Hudas/article/details/145381433?spm1001.2014.3001.5501上篇文章我们的屏幕已实现了如…

【JavaEE进阶】Spring留言板实现

目录 &#x1f38d;预期结果 &#x1f340;前端代码 &#x1f384;约定前后端交互接口 &#x1f6a9;需求分析 &#x1f6a9;接口定义 &#x1f333;实现服务器端代码 &#x1f6a9;lombok介绍 &#x1f6a9;代码实现 &#x1f334;运行测试 &#x1f384;前端代码实…

1.23学习

misc buuctf-小明的保险箱 打开附件是一个在线图片首先将其另存为&#xff0c;然后仅仅只是一个图片&#xff0c;而无其他信息&#xff0c;那么我们再进行binwalk或者foremost文件分离&#xff0c;得到了一个文件夹&#xff0c;其中含有一个压缩包但是是一个加密的&#xff0…

【Python】第五弹---深入理解函数:从基础到进阶的全面解析

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】【Python】 目录 1、函数 1.1、函数是什么 1.2、语法格式 1.3、函数参数 1.4、函数返回值 1.5、变量作用域 1.6、函数…

【数据结构】(1)集合类的认识

一、什么是数据结构 1、数据结构的定义 数据结构就是存储、组织数据的方式&#xff0c;即相互之间存在一种或多种关系的数据元素的集合。 2、学习数据结构的目的 在实际开发中&#xff0c;我们需要使用大量的数据。为了高效地管理这些数据&#xff0c;实现增删改查等操作&…

大数据Hadoop入门2

第三部分&#xff08;Hadoop MapReduce和Hadoop YARN&#xff09; 1.课程内容-大纲-学习目标 2.理解先分再合、分而治之的思想 3.hadoop团队针对MapReduce的设计构思 map这里不能翻译成地图&#xff0c;翻译为mapping比较好一点 4.Hadoop MapReduce介绍、阶级划分和进程组成 5…

什么是BFF?他有什么用?

BFF&#xff08;Backend for Frontend&#xff09; 是一种架构模式&#xff0c;专门为前端应用提供定制化的后端服务。它的核心思想是为不同的前端客户端&#xff08;如 Web、移动端、桌面端等&#xff09;提供专门的后端服务&#xff0c;而不是让所有客户端共享同一个通用的后…

【深度之眼cs231n第七期】笔记(三十一)

目录 强化学习什么是强化学习&#xff1f;马尔可夫决策过程&#xff08;MDP&#xff09;Q-learning策略梯度SOTA深度强化学习 还剩一点小尾巴&#xff0c;还是把它写完吧。&#xff08;距离我写下前面那行字又过了好几个月了【咸鱼本鱼】&#xff09;&#xff08;汗颜&#xff…

K8S极简教程(4小时快速学会)

1. K8S 概览 1.1 K8S 是什么 K8S官网文档&#xff1a;https://kubernetes.io/zh/docs/home/ 1.2 K8S核心特性 服务发现与负载均衡&#xff1a;无需修改你的应用程序即可使用陌生的服务发现机制。存储编排&#xff1a;自动挂载所选存储系统&#xff0c;包括本地存储。Secret和…

SPDK vhost介绍

目录 1. vhost技术的背景与动机Virtio 介绍virtio-blk数据路径为例 2. vhost技术的核心原理2.1 vhost-kernel2.2 vhost-user举例 2.3 SPDK vhostvhost的优势IO请求处理数据传输控制链路调整 3. SPDK vhost的实现与配置3.1 环境准备3.2 启动SPDK vhost服务3.3 创建虚拟块设备3.4…

【C++数论】880. 索引处的解码字符串|2010

本文涉及知识点 数论&#xff1a;质数、最大公约数、菲蜀定理 LeetCode880. 索引处的解码字符串 给定一个编码字符串 s 。请你找出 解码字符串 并将其写入磁带。解码时&#xff0c;从编码字符串中 每次读取一个字符 &#xff0c;并采取以下步骤&#xff1a; 如果所读的字符是…

[创业之路-270]:《向流程设计要效率》-2-企业流程架构模式 POS架构(规划、业务运营、支撑)、OES架构(业务运营、使能、支撑)

目录 一、POS架构 二、OES架构 三、POS架构与OES架构的差异 四、各自的典型示例 POS架构典型示例 OES架构典型示例 示例分析 五、各自的典型企业 POS架构典型企业 OES架构典型企业 分析 六、各自典型的流程 POS架构的典型流程 OES架构的典型流程 企业流程架构模式…

FFmpeg音视频采集

文章目录 音视频采集音频采集获取设备信息录制麦克风录制声卡 视频采集摄像机画面采集 音视频采集 DirectShow&#xff08;简称DShow&#xff09;是一个Windows平台上的流媒体框架&#xff0c;提供了高质量的多媒体流采集和回放功能&#xff0c;它支持多种多样的媒体文件格式&…

qt-QtQuick笔记之常见项目类简要介绍

qt-QtQuick笔记之常见项目类简要介绍 code review! 文章目录 qt-QtQuick笔记之常见项目类简要介绍1.QQuickItem2.QQuickRectangle3.QQuickImage4.QQuickText5.QQuickBorderImage6.QQuickTextInput7.QQuickButton8.QQuickSwitch9.QQuickListView10.QQuickGridView11.QQuickPopu…