【物联网】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的值都是固定(取决于指定的链接地址)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

星火大模型接入及文本生成HTTP流式、非流式接口(JAVA)

文章目录 一、接入星火大模型二、基于JAVA实现HTTP非流式接口1.配置2.接口实现&#xff08;1&#xff09;分析接口请求&#xff08;2&#xff09;代码实现 3.功能测试&#xff08;1&#xff09;测试对话功能&#xff08;2&#xff09;测试记住上下文功能 三、基于JAVA实现HTTP流…

lightweight-charts-python 包 更新 lightweight-charts.js 的方法

lightweight-charts-python 是 lightweight-charts.js 的 python 包装&#xff0c;非常好用 lightweight-charts 更新比较频繁&#xff0c;导致 lightweight-charts-python 内置的 lightweight-charts 经常不是最新的。 新的 lightweight-charts 通常可以获得性能改进和bug修复…

记录 | Docker的windows版安装

目录 前言一、1.1 打开“启用或关闭Windows功能”1.2 安装“WSL”方式1&#xff1a;命令行下载方式2&#xff1a;离线包下载 二、Docker Desktop更新时间 前言 参考文章&#xff1a;Windows Subsystem for Linux——解决WSL更新速度慢的方案 参考视频&#xff1a;一个视频解决D…

2025年01月27日Github流行趋势

项目名称&#xff1a;onlook项目地址url&#xff1a;https://github.com/onlook-dev/onlook项目语言&#xff1a;TypeScript历史star数&#xff1a;5340今日star数&#xff1a;211项目维护者&#xff1a;Kitenite, drfarrell, iNerdStack, abhiroopc84, apps/dependabot项目简介…

【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…

海外问卷调查渠道查如何设置:最佳实践+示例

随着经济全球化和一体化进程的加速&#xff0c;企业间的竞争日益加剧&#xff0c;为了获得更大的市场份额&#xff0c;对企业和品牌而言&#xff0c;了解受众群体的的需求、偏好和痛点才是走向成功的关键。而海外问卷调查才是获得受众群体痛点的关键&#xff0c;制作海外问卷调…

《STL基础之vector、list、deque》

【vector、list、deque导读】vector、list、deque这三种序列式的容器&#xff0c;算是比较的基础容器&#xff0c;也是大家在日常开发中常用到的容器&#xff0c;因为底层用到的数据结构比较简单&#xff0c;笔者就将他们三者放到一起做下对比分析&#xff0c;介绍下基本用法&a…

一组开源、免费、Metro风格的 WPF UI 控件库

前言 今天大姚给大家分享一个开源、免费、Metro风格的 WPF UI 控件库&#xff1a;MahApps.Metro。 项目介绍 MahApps.Metro 是一个开源、免费、Metro风格的 WPF UI 控件库&#xff0c;提供了现代化、平滑和美观的控件和样式&#xff0c;帮助开发人员轻松创建具有现代感的 Win…

网易云音乐歌名可视化:词云生成与GitHub-Pages部署实践

引言 本文将基于前一篇爬取的网易云音乐数据, 利用Python的wordcloud、matplotlib等库, 对歌名数据进行深入的词云可视化分析. 我们将探索不同random_state对词云布局的影响, 并详细介绍如何将生成的词云图部署到GitHub Pages, 实现数据可视化的在线展示. 介绍了如何从原始数据…

通义灵码插件保姆级教学-IDEA(安装及使用)

一、JetBrains IDEA 中安装指南 官方下载指南&#xff1a;通义灵码安装教程-阿里云 步骤 1&#xff1a;准备工作 操作系统&#xff1a;Windows 7 及以上、macOS、Linux&#xff1b; 下载并安装兼容的 JetBrains IDEs 2020.3 及以上版本&#xff0c;通义灵码与以下 IDE 兼容&…

工业级 RAG 实现 - QAnything

文章目录 1. QAnything简介2. QAnything 安装教程2. 1 安装软件包2.2 运行QAnything框架2.3 访问前端页面 3. QAnything 简单使用3.1 创建知识库3.2 创建聊天机器人3.3 关联知识库3.4 测试 4. QAnything 的分析&#xff1a;4. 1 QAnything 架构4. 2 两阶段检索4. 2.1 一阶段检索…

Cross-Resolution知识蒸馏论文学习

TPAMI 2024&#xff1a;Pixel Distillation: Cost-Flexible Distillation Across Image Sizes and Heterogeneous Networks 教师模型使用高分辨率输入进行学习&#xff0c;学生模型使用低分辨率输入进行学习 学生蒸馏损失&#xff1a;Lpkd和Lisrd Lpkd&#xff1a;任务损失lo…

Versal - 基础3(AXI NoC 专题+仿真+QoS)

目录 1. 简介 2. 示例 2.1 示例说明 2.2 创建项目 2.2.1 平台信息 2.2.2 AXI NoC Automation 2.2.3 创建时钟和复位 2.3 配置 NoC 2.4 配置 AXI Traffic 2.5 配置 Memory Size 2.6 Validate BD 2.7 添加观察信号 2.8 运行仿真 2.9 查看结果 2.9.1 整体波形 2.9…

【PostgreSQL内核学习 —— (WindowAgg(一))】

WindowAgg 窗口函数介绍WindowAgg理论层面源码层面WindowObjectData 结构体WindowStatePerFuncData 结构体WindowStatePerAggData 结构体eval_windowaggregates 函数update_frameheadpos 函数 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊…

RubyFPV开源代码之系统简介

RubyFPV开源代码之系统简介 1. 源由2. 工程架构3. 特性介绍&#xff08;软件&#xff09;3.1 特性亮点3.2 数字优势3.3 使用功能 4. DEMO推荐&#xff08;硬件&#xff09;4.1 天空端4.2 地面端4.3 按键硬件Raspberry PiRadxa 3W/E/C 5. 软件设计6. 参考资料 1. 源由 RubyFPV以…

MySQL(单表访问)

今天是新年&#xff0c;祝大家新年快乐&#xff0c;但是生活还是得继续。 后面也会持续更新&#xff0c;学到新东西会在其中补充。 建议按顺序食用&#xff0c;欢迎批评或者交流&#xff01; 缺什么东西欢迎评论&#xff01;我都会及时修改的&#xff01; 大部分截图和文章采…

汇编的使用总结

一、汇编的组成 1、汇编指令&#xff08;指令集&#xff09; 数据处理指令: 数据搬移指令 数据移位指令 位运算指令 算术运算指令 比较指令 跳转指令 内存读写指令 状态寄存器传送指令 异常产生指令等 2、伪指令 不是汇编指令&#xff0c;但是可以起到指令的作用&#xff0c;伪…

汇编基础语法及其示例

1.汇编指令 1.1汇编指令的基本格式 <opcode>{<cond>}{s} <Rd> , <Rn> , <shifter_operand> <功能码>{<条件码>}{cpsr影响位} <目标寄存器> , <第一操作寄存器> , <第二操作数> 注&#xff1a;第一操作寄存器…

FLTK - FLTK1.4.1 - 搭建模板,将FLTK自带的实现搬过来做实验

文章目录 FLTK - FLTK1.4.1 - 搭建模板&#xff0c;将FLTK自带的实现搬过来做实验概述笔记my_fltk_test.cppfltk_test.hfltk_test.cxx用adjuster工程试了一下&#xff0c;好使。END FLTK - FLTK1.4.1 - 搭建模板&#xff0c;将FLTK自带的实现搬过来做实验 概述 用fluid搭建UI…

基于物联网设计的疫苗冷链物流监测系统

一、前言 1.1 项目开发背景 随着全球经济的发展和物流行业的不断创新&#xff0c;疫苗和生物制品的运输要求变得越来越高。尤其是疫苗的冷链物流&#xff0c;温度、湿度等环境因素的控制直接关系到疫苗的质量和效力&#xff0c;因此高效、可靠的冷链监控系统显得尤为重要。冷…