ldr、str、ldm、stm、msr、mrs、swi、svc、mrc等ARM指令详解及具体应用

news2024/11/17 16:53:30

文章目录

  • 前言
  • 一、跳转指令
    • 1.1 相对跳转
    • 1.2 绝对跳转
  • 二、内存操作指令
    • 2.1 Load和Store
      • 2.1.1 伪指令
      • 2.1.2 伪操作
    • 2.2 内存操作指令具体应用
  • 三、 寄存器的寻址方式
    • 3.1 前索引寻址
    • 3.2 后索引寻址
    • 3.3 基址变址
  • 四、块拷贝指令(多数据加载)
    • 4.1 块拷贝
    • 4.2 指令应用
      • 4.2.2 多数据操作指令
      • 4.2.3 栈操作指令
  • 五、特殊寄存器操作指令
  • 六、 杂项指令
  • 八、 协处理指令
  • 九、 条件字段
  • 总结


前言


本期和大家主要分享的ARM汇编指令集中的内存操作类指令,涉及到内存操作,不得不说CPSR,SP,LR,PC是非常重要的几个寄存器,所以接下来就来具体观察一下其内存窗口的具体变化!

一、跳转指令

1.1 相对跳转

相对跳转: b fun 基于当前pc前后32M范围寻找标号,跳转到标号处执行代码
     bl fun 基于当前pc前后32M范围寻找标号,跳转到标号处执行代码,保存返回地址到LR

1.2 绝对跳转

修改pc的值(两种修改pc的值)

mov pc, #0x100

ldr pc, =fun ;将fun标号的链接地址给pc

 绝对跳转第一种给pc赋值的缺点是:当pc赋值处的汇编代码之前需要加入代码时,那么pc处的指令就不是原来的指令了,发生了变化;但是绝对跳转的第二种方式与相对跳转其实都是把将要执行指令的地址装载给PC,进而实现指令的跳转;

二、内存操作指令

 接下来是非常重要的一部分,内存操作指令能够实现将某一个值写到指定地址的位置处;这样就能够实现函数的跳转(比如用堆栈记录函数的入口地址等);
内存操作指令:实现寄存器与内存之间的数据交互;

2.1 Load和Store

先从字面上来理解一下:
LDR LD=LoaD(加载) R=Register(寄存器) ;
STR ST=STore(存储)R=Register(寄存器)

LDR:加载指定位置32位数据到目标寄存器;(从固定地址处进行取值)
STR:保存指定位置32位数据到目标位置;(给固定位置进行赋值)

这里给出不同指令下进行数据操作的位数:
ldrb/strb 8位操作
ldrh/strh 16位操作
ldr/str 32位操作
ldrd/strd 64位操作

注意:ldr r0, fun  === 基于当前pc前后4k,寻找标号,将fun标号地址处的内容给r0

2.1.1 伪指令

 伪指令和指令一样都是会生成机器码的指令,但伪指令与指令的区别是:每条汇编指令都有对应的唯一一条机器码,而伪指令可以有很多一条机器码,也可以理解为伪指令是有很多一条汇编指令组合而成。

ldr伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中
ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。ldr伪指令没有这个限制。
如果使用ldr伪指令时,后面跟的立即数没有超过8位,在实际汇编的时候该ldr伪指令是被转换为mov指令的。

2.1.2 伪操作

伪操作:告诉编译器怎么去编译指令,而它本身不生成机器码;

2.2 内存操作指令具体应用

	mov r0, #0x40000010
	mov r1, #3
	str r1, [r0]
	ldr r2, [r0]

 以下代码实现的功能是将0x40000010这个地址赋给寄存器,紧接着将3这个立即数给寄存器r1,接下来str指令将立即数3写入到地址为0x40000010的地址位置处;ldr指令实现的操作是将0x40000010处存放的数取出来存入寄存器r2中,接下来看一下寄存器和内存观察窗口;
在这里插入图片描述
在这里插入图片描述

三、 寄存器的寻址方式

3.1 前索引寻址

ldr r0, [r1, #4]  === r0=*(r1+4)   r1=r1
str r0, [r1, #4]  === *(r1+4)=r0   r1=r1
ldr r0, [r1, r2]  === r0=*(r1+r2)  r1=r1
str r0, [r1, r2]  === *(r1+r2)=r0  r1=r1

3.2 后索引寻址

ldr r0, [r1], #4  === r0=*(r1)  r1=r1+4
str r0, [r1], #4  === *(r1)=r0  r1=r1+4
ldr r0, [r1], r2  === r0=*(r1)  r1=r1+r2
str r0, [r1], r2  === *(r1)=r0  r1=r1+r2

3.3 基址变址

ldr r0, [r1, #4]! === r0=*(r1+4)  r1=r1+4
str r0, [r1, #4]! === *(r1+4)=r0  r1=r1+4
ldr r0, [r1, r2]! === r0=*(r1+4)  r1=r1+r2
str r0, [r1, r2]! === *(r1+4)=r0  r1=r1+r2
注意:这里!表示地址一定会发生变化;

四、块拷贝指令(多数据加载)

4.1 块拷贝

快拷贝:完成多个寄存器和连续内存空间数据交互,小编号寄存器对应低地址空间, 大编号寄存器对应高地址空间

ldm:(load  much)多数据加载,将地址上的值加载到寄存器上
stm:(store much)多数据存储,将寄存器的值存到地址上

(1)IA:(Increase After) 每次传送后地址加4,其中的寄存器从左到右执行,例如:STMIA R0,{R1,LR} 先存R1,再存LR;
(2)IB:(Increase Before)每次传送前地址加4,同上;
(3)DA:(Decrease After)每次传送后地址减4,其中的寄存器从右到左执行,例如:STMDA R0,{R1,LR} 先存LR,再存R1;
(4)DB:(Decrease Before)每次传送前地址减4,同上;
(5)FD: 满递减堆栈 (每次传送前地址减4);
(6)FA: 满递增堆栈 (每次传送后地址减4);
(7)ED: 空递减堆栈 (每次传送前地址加4);
(8)EA: 空递增堆栈 (每次传送后地址加4);
此处借鉴文章:多数据操作指令

4.2 指令应用

4.2.2 多数据操作指令

ldm  r0, {r1,r2,r3}   === r1=*r0 r2=*(r0+4) r3=*(r0+8)  r0=r0(这里如果不是按照r1,r2,r3进行顺序排布,那么CPU也会自动进行从小到大进行排列)
stm  r0, {r1-r3}      === *r0=r1 *(r0+4)=r2 *(r0+8)=r3  r0=r0

ldmia/stmia  先内存操作,后地址+4
ldmda/stmda  先内存操作,后地址-4
ldmib/stmib  先地址+4,后内存操作
ldmdb/stmdb  先地址-4,后内存操作

4.2.3 栈操作指令

默认 的栈是满减栈;
满减栈 sp(stack pointer)指向的内存空间不能直接使用,栈的生长方向向下;
满增栈 sp指向的内存空间不能直接使用,栈的生长方向向上;
空减栈 sp指向的内存空间可以直接使用,栈的生长方向向下 ;
空增栈 sp指向的内存空间可以直接使用,栈的生长方向向上;

ldmfd、stmfd  满减
ldmfa、stmfa  满增
ldmed、stmed  空减 
ldmea、stmea  空增

入栈: stmfd  sp!, {r0-r12, lr}	    sp为栈指针,把r0-r12, lr中的数据依次入栈;*(sp-4)=r0,*(sp-4*2)=r1,*(sp-4*3)=r2,........,*(sp-4*15)=lr;
出栈: ldmfd  sp!, {r0-r12, lr}		r0-r12, lr中的数据依次出栈;lr=[sp-1*4],r13=[sp-2*4],r12=[sp-3*4],......,r0=[sp-15*4]
出栈: ldmfd  sp!, {r0-r12, lr}^ 	^表示模式恢复(因为没对pc赋值,所以^的表示将数据恢复到User模式的[r0-lr]寄存器组中)

五、特殊寄存器操作指令

特殊寄存器 cpsr 的读写访问只能使用 msr 和 mrs 指令
msr:将普通寄存器中的数据写到特殊寄存器中;
mrs:将特殊寄存器中的数据写到普通寄存器中;

msr  cpsr, r0  			=== cpsr=r0
msr  cpsr_c, r0  		=== keil中使用
mrs  r0, cpsr  			=== r0=cpsr

mrs 指令: 对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以获得当前处理器的工作状态。读SPSR寄存器可以获得进入异常前的处理器状态(因为只有异常模式下有SPSR寄存器)。
msr指令: 对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读、修改、写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。

MRS 指令允许将 CPSR 或 SPSR_<mode>的内容移动到一个通用寄存器中去。
MSR 指令允许将一个通用寄存器中的内容移动到 CPSR 或 SPSR_<mode>寄存器中去。

以下顺序执行了一个模式的改变:

MRS R0, CPSR 				;复制 CPSR 到 R0
BIC R0, R0, #0x1F 			;清零模式位
ORR R0, R0, #new_mode 		;选择新的模式
MSR CPSR, R0			    ;写回到修改了的 CPSR

六、 杂项指令

swi  #12   软件中断指令,数值存放在机器码的低24位,可以利用数值进行区分
svc #12		目前将swi更新为svc指令

该指令可以用来触发软件中断;

八、 协处理指令

协处理器操作:辅助主处理器进行电路管理的处理器;(比如计算一些浮点型的数据)
一般处理器有p0—p15的某一些,arm9 只有p15 协处理器;c0-c15 寄存器 32位;

MRC p2, 5, R3, C5, C6,       ;请求协处理器 2 用 c5 和 c6 执行操作数 5,将结果(有符号 32 位字)传输回 R3
MRCEQ p3, 9, R3, c5, c6 2    ;条件请求协处理器 3 用 c5 和 c6 执行操作数 9(类型 2),将结果传输回 R3

九、 条件字段

  在 ARM 状态,所有的指令都可以按照 CPSR 状态码和指令条件字段的状态来有条件地执行。此字段(位[31:28])确定了在什么情况下哪一个指令被执行。如果 C,N,Z 和 V 标志位的状态符合字段的条件码,将执行指令,否则忽略不执行。
  有 16 种可能的条件,每种表示为在指令助记符后附加两个字符后缀。例如,一个分支(汇编语言中的 B)跳
转指令变成 BEQ 为“如果相等则分支跳转”,这意味着只有 Z 标志位被置位了才会执行分支跳转。
在这里插入图片描述

总结

本期和大家主要分享的是ldr、str、ldm、stm、msr、mrs、swi、svc、mrc等ARM指令的具体介绍,对这些基础概念掌握后,接下来就能够读懂基本的2440A的启动代码了,也有助于自己去独立的书写启动代码,依次更好的实现自己想要实现的功能,更好的理解正式启动代码设计流程的巧妙之处,对CPU处理事务的流程以及处理细节会有更深的认识;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nacos 源码分析全系列

Nacos 源码分析全系列 学习目标 主线任务 代码解析画图git库(中文注释)设计思想多版本迭代讨论群(私聊进群) 主要的大纲路线 主要拆解的是nacos的1.4.1版本和2.1.0版本,还有nacos 的一些已知的bug 正确的学习源码的姿势 服务端是如何处理客户度的请求 注册中心服务 内存…

【备战秋招】每日一题:华东师范大学保研机试-2022-差分计数

为了更好的阅读体检&#xff0c;可以查看我的算法学习博客差分计数 题目内容 给定n个整数,...,和一个整数x。求有多少有序对(i,j)满足 输入格式 第一行两个整数,分别代表整数的个数和题目中的x。 第二行n个用空格隔开的整数&#xff0c;第i个代表 输出格式 一行一个整数…

1745_Perl中的switch结构

全部学习汇总&#xff1a; GreyZhang/perl_basic: some perl basic learning notes. (github.com) 用了很久时间的Perl了&#xff0c;但是一直没有使用过switch结构。即使有的时候&#xff0c;基本上也通过其他的形式完成了相关工作。虽说有时候可能会效率低一些&#xff0c;但…

【Python】使用pyside2时qt designer 设计窗口显示图标icon但是运行后不显示(图文说明)

目录 错误情况解决方法总结 欢迎关注 『Python』 系列&#xff0c;持续更新中 欢迎关注 『Python』 系列&#xff0c;持续更新中 平时用的不多&#xff0c;也不知道这个报错有没有偶然性&#xff0c;或者是我自己搞错了仅供参考。 错误情况 toolBar中的图标在designer中显示正…

【备战秋招】每日一题:华东师范大学保研机试-2022-位运算

为了更好的阅读体检&#xff0c;可以查看我的算法学习博客位运算 题目内容 给定一个int型整数x,将x的二进制表示中第i位和第j位的值互换。 注意: x的二进制表示的最右边为第0位。 输入格式 在一行中输入三个整数&#xff0c;x,i,j, 整数之间用一个空格分隔。 输出格式 在…

【开启微前端新时代】微前端:构建可扩展、可维护的现代 Web 应用

文章目录 第1章&#xff1a;微前端简介微前端是什么微前端的优势和劣势微前端有以下优势1. 独立部署2. 技术栈无关3. 更好的扩展性4. 短生命周期 微前端的劣势&#xff1a;1. 系统复杂度2. 通信机制3. 部署成本 微前端的历史和现状 第2章&#xff1a;微前端架构模式容器和子应用…

软考A计划-网络工程师-系统架构师案例分析知识点整理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff…

Linux串口编程

文章目录 前言一、Linux下的TTY体系介绍二、行规层三、Linux串口编程步骤四、代码编写总结 前言 本篇文章将讲解如何在Linux下使用串口。 一、Linux下的TTY体系介绍 在Linux系统中&#xff0c;tty&#xff08;Teletypewriter&#xff09;是指一种终端设备&#xff0c;它提供…

Fiddler之Replay功能详解

今天就先来看看Fiddler的功能。 Fiddler&#xff0c;最容易看到的就是快捷工具栏中的 Replay 按钮 解释下&#xff1a; Reissue the selected requests. 重发选中的请求Hold CTRL to reissue unconditionallly. 选中请求按住 CTRL 键&#xff0c;点击Replay时无条件重发选中…

【MySQL函数】:让你的数据库操作更高效(一)

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL字符串函数和数学函数的讲解✨ 目录 前言一、字符串函数二、数学函数三、总结 一、字符串函数 函数作用UPPER(列|字符串)将字符串每个字符转为大写LOWER(列|字符串)将字符串每个字符转为小写CONCAT(str1,str2,…

CSS的学习2

这几天复习了英语&#xff0c;高数&#xff0c;也考完四级了。 这两天开始写了课设的项目&#xff0c;选的是捷住宝&#xff0c;我打算用链表和搜索树。写着写着总是出问题&#xff0c;然后改Bug。还差删除信息和文件操作&#xff0c;还是尽量写好一些。 明天考英语&#xff…

TX-1C单片机实现多功能电子时钟

实验报告 电子时钟实验 一、实验要求&#xff1a;二、实验结果三、实验思路&#xff08;一&#xff09;模块整理&#xff08;二&#xff09;流程图绘制&#xff08;三&#xff09;C51编程 四、实验总结&#xff08;一&#xff09;未完成的部分&#xff08;二&#xff09;待优化…

layui框架实战案例(22):多附件上传实战开发实录(php后端、文件删除、数据库删除)

layUI框架实战案例系列文章 layui框架实战案例(21)&#xff1a;layui上传的哪些事(layui.upload组件、 file文件域、php后台上传)layui框架实战案例(20)&#xff1a;常用条件判断和信息展示技巧(图片预览、动态表格、短信已读未读、链接分享、信息脱敏、内置框架页)layui框架实…

【Spring Cloud系列】-Eureka服务端高可用详解

【Spring Cloud系列】-Eureka服务端高可用详解 文章目录 【Spring Cloud系列】-Eureka服务端高可用详解一. 序言二. 什么是高可用性三. 什么是CAP一致性&#xff08;Consistency&#xff09;可用性&#xff08;Availability&#xff09;分区容错&#xff08;Partition-toleranc…

2.8 基于DPDK的UDP用户态协议栈实现

目录 一、网络协议栈1、**网络通信过程**2、**dpdk** 二、dpdk环境1、dpdk环境开启2、Windowe下配置IP和MAC地址的映射 三、实现用户态协议栈ustack1、UDP协议2、代码 四、dpdk一些基本函数接口rte_eal_init()rte_pktmbuf_pool_create()rte_socket_id()rte_eth_dev_configure()…

Java连接MySQL对数据实现增删改查

在实现好的窗口实现 添加修改删除查询数据的方法 以如下数据实验 statement自带的函数使用说明execute &#xff08;SQL&#xff09;执行给定的SQL语句返回一个或多个结果结果集 execute方法应该仅在语句能返回多个ResultSet对象、多个更新计数或ResultSet对象与更新计数的组…

Verilog | 基4 booth乘法器

上接乘法器介绍 原理 跟基2的算法一样&#xff0c;假设A和B是乘数和被乘数&#xff0c;且有&#xff1a; A ( a 2 n 1 a 2 n ) a 2 n − 1 a 2 n − 2 … a 1 a 0 ( a − 1 ) B b 2 n − 1 b 2 n − 2 … b 1 b 0 \begin{align}A&(a_{2n1}a_{2n})a_{2n−1}a_{2n−2}……

安卓期末考试知识总结(3)

文章目录 第五章 数据存储文件存储(非重点)内部存储获取或者打开目录操作文件 外部存储区 SharedPreferences存储写入Shared Preferences读取数据 SQLite数据库SQLite数据库的创建操作数据库数据Curosr数据库的事务 第五章 数据存储 简述Android数据存储的方式 Android平台提供…

FreeRTOS:任务通知

目录 一、任务通知简介二、发送任务通知2.1 函数xTaskNotify()2.2函数xTaskNotifyFromISR()2.3函数xTaskNotifyGive()2.4函数vTaskNotifyGiveFromISR()2.5函数xTaskNotifyAndQuery()2.6函数xTaskNotifyAndQueryFromISR() 三、获取任务通知3.1函数ulTaskNotifyTake()3.2函数xTas…

[进阶]Java:打印流、Properties、common-io框架

打印流&#xff1a; 作用&#xff1a;打印流可以实现方便、高效的打印数据到文件中去。打印流一般是&#xff1a;PrintStream&#xff0c;PrintWriter两个类。可以实现打印什么数据就是什么数据&#xff0c;例如打印整数97写出去就是97&#xff0c;打印boolean的true&#xff…