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

ARM编程指令一

预备知识

1. 寻找地址表现形式
  1. 立即数地址(Immediate Addressing)
LDR R0, =0x2000  // 将立即数 0x2000 作为地址加载到寄存器 R0 中
  1. 寄存器间接寻址(Register Indirect Addressing)
    使用寄存器的值作为内存地址进行数据存取。
LDR R0, [R1]    // 从寄存器 R1 指向的内存地址加载数据到寄存器 R0
STR R2, [R3]    // 将寄存器 R2 中的数据存储到寄存器 R3 指向的内存地址
  1. 寄存器间接加偏移量(Register Indirect with Offset)
    功能:在寄存器指定的基地址上加上一个立即数偏移量来计算实际的内存地址。
LDR R0, [R1, #4]    // 从寄存器 R1 加上偏移量 4 指向的地址加载数据到寄存器 R0
STR R2, [R3, #8]    // 将寄存器 R2 中的数据存储到寄存器 R3 加上偏移量 8 指向的内存地址
  1. 寄存器间接加寄存器偏移(Register Indirect with Register Offset)
    功能:使用一个寄存器的值作为基地址,并将另一个寄存器的值作为偏移量来计算实际的内存地址。偏移量是数而不是地址。
LDR R0, [R1, R2]    // 从寄存器 R1 加上寄存器 R2 指向的地址加载数据到寄存器 R0
STR R3, [R4, R5]    // 将寄存器 R3 中的数据存储到寄存器 R4 加上寄存器 R5 指向的内存地址
  1. 寄存器间接加偏移量与基地址寄存器的递增(Pre-indexed Addressing)
    功能:在访问内存之前,先将一个立即数偏移量加到基地址寄存器的值上。这种方式会修改基地址寄存器的值。
LDR R0, [R1, #4]!    // 从寄存器 R1 加上偏移量 4 指向的地址加载数据到寄存器 R0,并递增寄存器 R1
STR R2, [R3, #8]!    // 将寄存器 R2 中的数据存储到寄存器 R3 加上偏移量 8 指向的内存地址,并递增寄存器 R3
2. #和=的区别
  1. #4是一个立即数
  2. =address,用途:表示一个常量地址或数据值,用于将较大的数值加载到寄存器中。是伪指令
3.

一、数据传输指令

1.MOV指令 Move Register

功能:将一个值从一个寄存器或立即数传输到另一个寄存器

MOV R0, #5      // 将立即数5加载到寄存器R0
MOV R1, R0      // 将寄存器R0的值传输到寄存器R1

二、访存指令

唯二

1.LDR指令 Load Register

功能:从内存中加载数据到寄存器。左<-右

LDR R0, [R1]    // 从寄存器R1指向的内存地址加载数据到寄存器R0
LDR R2, =0x1000 // 将地址0x1000加载到寄存器R2
LDR R3, [R2]    // 从寄存器R2指向的内存地址加载数据到寄存器R3
2. STR指令 Store Register

功能:将寄存器中的数据存储到内存中。左->右

STR R0, [R1]     // 将寄存器 R0 中的数据存储到寄存器 R1 指向的内存地址
STR R2, [R3]     // 将寄存器 R2 中的数据存储到寄存器 R3 指向的内存地址

三、多寄存器访存指令

1. LDM指令 Load Multiple (LDM)

功能:从内存中加载多个寄存器的值。

  • 递增模式(IA):在每次数据加载后,基地址寄存器的值递增。
LDMIA R0!, {R1, R2, R3}//从内存地址 R0 指向的地址开始,依次加载内存中的值到寄存器 R1、R2 和 R3。
R0 在每次加载后递增,直到所有寄存器加载完毕。
  • 递减模式(DA)
LDMDA R0!, {R1, R2, R3}//从内存地址 R0 指向的地址开始(地址递减),依次加载内存中的值到寄存器 R1、R2 和 R3。R0 在每次加载前递减,直到所有寄存器加载完毕。
  • 不更新基地址寄存器
LDMIA R0, {R1, R2, R3}//从内存地址 R0 指向的地址开始,依次加载内存中的值到寄存器 R1、R2 和 R3。基地址寄存器 R0 的值不更新(即没有 !)。
2. STM指令 Store Multiple (STM)

功能:将多个寄存器的值存储到内存中。类似于LDM指令

STMIA R0!, {R1, R2, R3}  // 将寄存器 R1、R2、R3 的值存储到寄存器 R0 指向的内存地址,并在存储后递增 R0

四、栈操作指令

1.PUSH和POP指令

后进先出
功能:PUSH:将寄存器的值压入栈中。
POP:从栈中弹出数据到寄存器。

PUSH {R0, R1}    // 将寄存器 R0 和 R1 的值压入栈中。值得注意是R1先压入栈中
POP {R2, R3}     // 从栈中弹出数据到寄存器 R2 和 R3POP {R2, R3}//从栈中弹出数据到寄存器 R2 和 R3 中。R3存放最先出栈的元素

五、立即数处理指令

1.MOVT Move Top (移动顶部)和MOVW Move Wide (移动宽度)指令

功能:
MOVW:将一个16位立即数加载到寄存器的低16位。
MOVT:将一个16位立即数加载到寄存器的高16位。

MOVW R0, #0x1234  // 将立即数 0x1234 加载到寄存器 R0 的低 16 位
MOVT R0, #0x5678  // 将立即数 0x5678 加载到寄存器 R0 的高 16 位

六、系统控制寄存器操作指令

1. MRS和MSR指令
  1. MRS 和 MSR 是用于处理系统控制寄存器(如程序状态寄存器(CPSR)、控制寄存器等)的指令。它们用于读写这些寄存器的值,从而影响系统的状态和控制。
  2. MRS 指令,全称:Move Register to Status Register
  • 功能:将系统控制寄存器的值读取到通用寄存器中。主要用于从程序状态寄存器(CPSR)或其他控制寄存器读取数据。
  1. MSR 指令,全称:Move Status Register to Register
  • 功能:将通用寄存器的值写入到系统控制寄存器中。主要用于设置程序状态寄存器(CPSR)或其他控制寄存器的值。
MRS R0, CPSR  // 将当前程序状态寄存器 (CPSR) 的值加载到寄存器 R0 中
MSR CPSR, R0  // 将寄存器 R0 的值写入当前程序状态寄存器 (CPSR)

七、汇总

ARM汇编指令汇总

类别指令功能描述示例代码
数据传输指令MOV将数据从一个寄存器或立即数传输到另一个寄存器MOV R0, #5
MOV R1, R0
访存指令LDR从内存中加载数据到寄存器LDR R0, [R1]
LDR R2, =0x1000
LDR R3, [R2]
STR将寄存器中的数据存储到内存中STR R0, [R1]
STR R2, [R3]
多寄存器访存指令LDM从内存中加载多个寄存器的值LDMIA R0!, {R1, R2, R3}
LDMDA R0!, {R1, R2, R3}
LDMIA R0, {R1, R2, R3}
STM将多个寄存器的值存储到内存中STMIA R0!, {R1, R2, R3}
栈操作指令PUSH将寄存器的值压入栈中PUSH {R0, R1}
POP从栈中弹出数据到寄存器POP {R2, R3}
立即数处理指令MOVW将一个 16 位立即数加载到寄存器的低 16 位MOVW R0, #0x1234
MOVT将一个 16 位立即数加载到寄存器的高 16 位MOVT R0, #0x5678
系统控制寄存器操作指令MRS将系统状态寄存器(如 CPSR)的值读取到通用寄存器中MRS R0, CPSR
MSR将通用寄存器中的值写入到系统状态寄存器(如 CPSR)中MSR CPSR, R0

相关文章:

  • STM32--HAL库--定时器篇
  • 堆的基本实现
  • mysql中提供的函数
  • 独孤思维:长线副业,越做越香
  • C语言常见字符函数和字符串函数精讲
  • connect的非阻塞模式
  • Discourse 如何通过终端工具访问 PGSQL
  • 多模态
  • Android APP 音视频(02)MediaProjection录屏与MediaCodec编码
  • java找不到符号解决办法
  • 《Programming from the Ground Up》阅读笔记:p75-p87
  • css更改图片颜色
  • ReadAgent,一款具有要点记忆的人工智能阅读代理
  • Vue3点击按钮实现跳转页面并携带参数
  • openFeign配置okhttp
  • __proto__ 和 prototype的关系
  • 《深入 React 技术栈》
  • 【Amaple教程】5. 插件
  • 【翻译】babel对TC39装饰器草案的实现
  • 2017届校招提前批面试回顾
  • Angular数据绑定机制
  • Debian下无root权限使用Python访问Oracle
  • ES6系列(二)变量的解构赋值
  • mongodb--安装和初步使用教程
  • nginx 负载服务器优化
  • Unix命令
  • 从0到1:PostCSS 插件开发最佳实践
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 汉诺塔算法
  • 回顾 Swift 多平台移植进度 #2
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 离散点最小(凸)包围边界查找
  • 那些被忽略的 JavaScript 数组方法细节
  • 前嗅ForeSpider教程:创建模板
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 手写一个CommonJS打包工具(一)
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 问题之ssh中Host key verification failed的解决
  • 赢得Docker挑战最佳实践
  • 中文输入法与React文本输入框的问题与解决方案
  • zabbix3.2监控linux磁盘IO
  • 我们雇佣了一只大猴子...
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (二) 初入MySQL 【数据库管理】
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (一)UDP基本编程步骤
  • .java 9 找不到符号_java找不到符号
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • [12] 使用 CUDA 进行图像处理
  • [2018][note]用于超快偏振开关和动态光束分裂的all-optical有源THz超表——