ARMday03(寄存器读写、栈、程序状态寄存器、软中断和异常、混合编程)

单寄存器内存读写指令

将一个寄存器中的数值写入到内存,或者从内存中读取数据放在某一个指定寄存器中

指令码和功能

1.向内存中写:

str{条件码} 目标寄存器,[目标地址]:将目标寄存器的4字节数值写入到目标地址为首地址的空间中

strh{条件码} 目标寄存器,[目标地址]:将目标寄存器的2字节数值写入到目标地址为首地址的空间中

strb{条件码} 目标寄存器,[目标地址]:将目标寄存器的1字节数值写入到目标地址为首地址的空间中

2.从内存中读:

ldr{条件码} 目标寄存器,[目标地址]:从目标地址为首地址的空间中读取4字节数据存放在目标寄存器中

ldrh{条件码} 目标寄存器 ,[目标地址]:从目标地址为首地址的空间中读取2字节数据存放在目标寄存器中

ldrb{条件码} 目标寄存器 ,[目标地址]:从目标地址为首地址的空间中读取1字节数据存放在目标寄存器中

单寄存器内存索引方式 

前索引方式

str{条件码} 目标寄存器,[目标地址,#立即数] //将目标寄存器的数据保存在目标地址+8为起始地址的内存中

ldr{条件码} 目标寄存器,[目标地址,#立即数] //从目标地址+8为起始地址的内存中读取数据保存在目标寄存器

后索引方式

str{条件码} 目标寄存器,[目标地址],#立即数 //将目标寄存器的数据保存在目标地址为起始地址的内存中,接着目标地址自加立即数大小

ldr{条件码} 目标寄存器,[目标地址],#立即数 //从目标地址为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小

自动索引方式 

str{条件码} 目标寄存器,[目标地址,#立即数]! //将目标寄存器的数据保存在目标地址+立即数为起始地址的内存中,接着目标地址自加立即数大小

ldr{条件码} 目标寄存器,[目标地址,#立即数]! //从目标地址+立即数大小为起始地址的内存中读取数据保存在目标寄存器,接着目标地址自加立即数大小

批量寄存器的内存读写方式 

指令码以及格式

向内存写: stm 目标地址,{目标寄存器列表} 将列表中各个寄存器的数值保存在目标地址对应的地址空间中

从内存中读取 ldm 目标地址,{目标寄存器列表} 从目标地址对应的地址空间中拿数据保存到寄存器列表中各个寄存器中

注意:

1.寄存器列表中每一个寄存器之间用','分隔,如果寄存器列表中寄存器的编号连续,那么可以用-表示一定范围内的 寄存器,比如 {r1-r5}

2.无论寄存器列表中的寄存器表现形式如何,在存取数据时始终是小编号寄存器对应低地址

批量寄存器的地址增长方式 

内存读写命令后加ia后缀

先向r0数值为起始地址的内存空间中保存一个数据,然后r0数值往高地址方向增长

内存读写命令后加ib后缀

先r0数值往高地址方向增长,然后向r0数值为起始地址的内存空间中保存一个数据

内存读写命令后加da后缀

先向r0数值为起始地址的内存空间中保存一个数据,然后r0数值往低地址方向增长

内存读写命令后加db后缀

先r0数值往低地址方向增长,然后向r0数值为起始地址的内存空间中保存一个数据

栈内存的读写

栈指针寄存器:SP/R13 保存栈顶的地址

栈:本质上就是一段内存。在内存中选取一段内存作为栈内存,可以用于保存临时数据。

栈的类型

增栈:每次压栈结束,SP保存的栈顶地址往高地址方向增栈

减栈:每次压栈结束,SP保存的栈顶地址往低地址方向增栈

空栈:压栈结束后,SP保存的栈顶空间中没有有效数据

满栈:压栈结束后,SP保存的栈顶空间中有有效数据

空增栈(EA)/空减栈(ED)/满增栈(FA)/满减栈(FD)

当前ARM处理器使用的是哪种栈?满减栈

满减栈压栈出栈操作 

1.

push {寄存器列表}@压栈

pop {寄存器列表}@出栈

2.

stmdb sp!,{r1-r5}@压栈

ldmia sp!,{r6-r10}@出栈

3.

stmfd sp!,{r1-r5}@压栈

ldmfd sp!,{r6-r10}@出栈

 叶子函数

当我们在主函数中调用一个函数,被调用的这个函数中没有别的函数调用,那么 这个函数就叫做叶子函数。栈的应用------保护现场

.text  
.global _start _start:
@初始化栈ldr SP,=0X40000020b main
main:mov r1,#3mov r2,#4bl fun1add r3,r1,r2b main
fun1:
@压栈保护现场stmfd sp!,{r1,r2}mov r1,#7mov r2,#9sub r4,r2,r1@出栈恢复现场ldmfd sp!,{r1,r2}mov pc,lr   @程序返回.end 

非叶子函数

当我们在主函数中调用一个函数,被调用的这个函数中存在别的函数调用,那么 这个函数就叫做非叶子函数

.text  
.global _start _start:
@初始化栈ldr SP,=0X40000020b main
main:mov r1,#3mov r2,#4bl fun1add r3,r1,r2b main
fun1:
@压栈保护现场stmfd sp!,{r1,r2,lr}mov r1,#7mov r2,#9bl fun2sub r4,r2,r1@出栈恢复现场ldmfd sp!,{r1,r2,lr}mov pc,lr   @程序返回
fun2:stmfd sp!,{r1,r2}mov r1,#4mov r2,#8mul r4,r2,r1@出栈恢复现场ldmfd sp!,{r1,r2}mov pc,lr   @程序返回.end 

程序状态寄存器传输指令

指令的作用实现CPSR寄存器数值的读取以及数值的修改

指令码以及格式

格式:

注意:这两条指令只能对特殊功能寄存器进行操作(CPSR),不能对普通寄存器进行操作

msr CPSR,第一操作数 将第一操作数的数值写入到CPSR寄存器中

mrs 目标寄存器,CPSR 读取CPSR数值保存到目标寄存器中

软中断指令

软中断是从软件层次上模拟的硬件中断,原理和硬件中断一样。软中断触发之后CPU进行异常模式的切换(SVC),紧接着执行软中断对应的异常处理程序。

软中断指令码以及使用

swi 中断号

注意:中断号是一个由24位二进制数组成的一个整数,用于区分不同的中断

异常处理过程分析 

异常模式和异常源的对应关系

5种异常模式对应7种异常源

异常的处理过程分析(面试重点)

***********异常的处理过程********

当一个异常源产生之后CPU会进行一些工作用于程序的跳转以及异常模式的切换,这个过程分为四大步三小步

1.保存发生异常之前的CPSR的值到对应异常模式下的SPSR寄存器中

2.修改CPSR的数值

        2.1 根据实际情况设置FIQ和IRQ中断禁止 CPSR[7:6]

        2.2 修改处理器工作状态为ARM状态 CPSR[5]

        2.3 修改处理器的工作模式为对应的异常模式 CPSR[4:0]

3.保存主程序的返回地址到对应模式下的LR寄存器中

4.修改PC的值到对应异常模式下的异常向量表中

*********处理完异常之后现场的恢复过程*********

1.恢复CPSR寄存器的值为未发生异常之前的状态

2.修改PC的值为未发生异常之前的下一条指令地址 PC=LR

异常向量表 

1.异常向量表是内存空间中的一段内存。这段内存占据了32字节。这个内存被平分为8等份,一份是4字节。每一份内存对应一种异常源,有一份保留,在异常向量表内存里存放的是当前异常源对应的异常处理程序的跳转指令。当发生异常之后,CPU会修改PC的值为对应异常源在异常向量中的位置,执行这个位置中的跳转指令,去处理异常处理程序。

2.每一种异常源在异常向量表中的位置是固定,不能随便修改

3.只要设置了异常向量表的基地址,就可以根据不同异常在一场向量表中的位置找到对应异常的跳转指令

混合编程

混合编程的意义

所谓的混合编程就是c语言资源和汇编资源的相互调用

  • 一般工程会有汇编启动程序,启动程序完成堆栈的相关初始化,完毕之后才跳转到c语言的main函数
  • c语言中几乎不可以直接操作寄存器,但是有些特定场景下需要c中操作寄存器,这时候就需要c语言中嵌套汇编的语法

汇编调用C语言的函数

*****汇编文件**********
.text    
.global _start  _start: @ 1. 初始化栈指针,C代码运行必须有栈ldr sp, =0x40000820@ 2. 汇编调用c函数 @ 2.1 给C的函数传递实参值mov r0, #3   @ a = 3mov r1, #4   @ b = 4mov r2, #5   @ c = 5mov r3, #6   @ d = 6@ 2.2 汇编调用c的函数bl add_func@ 2.3 函数的返回通过r0返回,查看r0寄存器中的值loop:   b loop  .end**********c文件********************
// c代码的函数是一个全局的函数
int add_func(int a, int b, int c, int d) 
{return (a+b+c+d);
}

c语言调用汇编标签

********起始汇编文件**********
.text    
.globl _start  _start: @ 1. 初始化栈指针,C代码运行必须有栈ldr sp, =0x40000820@ 2. 汇编调用c,跳转到main函数b main
.end********c文件************
// 使用extern对函数进行声明
extern int add_func(int a, int b, int c, int d);int sum = 0;
int main()
{// 在c代码中调用汇编代码sum = add_func(1,2,3,4);while(1);return 0;
}********汇编文件**********
.text 
.global add_func  @ 将add_func函数声明为全局add_func:add r0, r0, r1add r0, r0, r2add r0, r0, r3mov pc, lr
.end

c语言内联汇编

在某一些特定的场景下需要在c语言中直接使用汇编的语法,此时需要内联汇编。内联汇编的实现需要通过asm关键字进行修饰

asm volatile("汇编指令模板\n\t"     //"\n\t"表示一条指令的结束.....:输出列表  //指令结果的输出值:输入列表  //指令的数据输入:破坏列表  //破坏列表指定我们当前可用的寄存器
);

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

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

相关文章

跟着森老师学React Hooks(1)——使用Vite构建React项目

Vite是一款构建工具,对ts有很好的支持,最近也是在前端越来越流行。 以往的React项目的初始化方式大多是通过脚手架create-react-app(本质是webpack),其实比起Vite来构建,启动会慢一些。 所以这次跟着B站的一个教程,使用…

JavaScript脚本操作CSS

脚本化CSS就是使用JavaScript脚本操作CSS,配合HTML5、Ajax、jQuery等技术,可以设计出细腻、逼真的页面特效和交互行为,提升用户体验,如网页对象的显示/隐藏、定位、变形、运动等动态样式。 1、CSS脚本化基础 CSS样式有两种形式&…

【Ruoyi管理后台】用户登录强制修改密码

近期有个需求,就是需要调整Ruoyi管理后台:用户如果三个月(长时间)未修改过密码,需要在登录时强制修改密码,否则不能登录系统。 一、后端项目调整 从需求来看,我们需要在用户表增加一个字段,用于标记用户最…

Ansible优化大全

文章目录 一、关闭系统信息收集二、开启加速 Ansible 执行速度修改配置文件/etc/ansible/ansible.cfg由于该功能与sudo冲突,必须关闭 requiretty 选项方法一方法二 参考文章: https://blog.csdn.net/o0o0o0D/article/details/110998873 一、关闭系统信息…

【教3妹学编程-算法题】逃离火灾

3妹:2哥,今日都立冬了, 可是天气一点都不冷。 2哥 : 立冬了,晚上要不要一起出去吃饺子?🥟 3妹:好呀好呀,2哥请吃饺子喽 2哥 : 歪歪,我说的是一起出去吃,没说我…

Python|OpenCV-图像的添加和混合操作(8)

前言 本文是该专栏的第8篇,后面将持续分享OpenCV计算机视觉的干货知识,记得关注。 在使用OpenCV库对图像操作的时候,有时需要对图像进行运算操作,类似于加法,减法,位操作等处理。而本文,笔者将针对OpenCV对图像的添加,混合以及位操作进行详细的介绍说明和使用。 下面,…

【慢SQL性能优化】 一条SQL的生命周期 | 京东物流技术团队

一、 一条简单SQL在MySQL执行过程 一张简单的图说明下,MySQL架构有哪些组件和组建间关系,接下来给大家用SQL语句分析 例如如下SQL语句 SELECT department_id FROM employee WHERE name Lucy AND age > 18 GROUP BY department_id其中name为索引&a…

Python算法例9 罗马数字转换为整数

1. 问题描述 给定一个罗马数字,将其转换为整数,要求返回结果的取值为1~3999。 2. 问题示例 Ⅳ→4,Ⅻ→12,ⅩⅪ→21,XCVI→99。 3. 代码实现 def roman_to_int(s):roman_map {I: 1, V: 5, X: 10, L: 50, C: 100, …

Spring Boot中使用Spring Data JPA访问MySQL

Spring Data JPA是Spring框架提供的用于简化JPA(Java Persistence API)开发的数据访问层框架。它通过提供一组便捷的API和工具,简化了对JPA数据访问的操作,同时也提供了一些额外的功能,比如动态查询、分页、排序等。 …

一体化HIS医疗信息管理系统源码:云HIS、云电子病历、云LIS

基于云计算技术的B/S架构的HIS系统,为医疗机构提供标准化的、信息化的、可共享的医疗信息管理系统,实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。系统利用云计算平台的技术优势,建立统一的云HIS、云病历、云LIS,…

【C++】万字一文全解【继承】及其特性__[剖析底层化繁为简](20)

前言 大家好吖,欢迎来到 YY 滴C系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! 目录 一.继承&复用&组合的区别1&…

mongodb分组查询

通过userId分组,得到结果字段为:_id和count db.my_solitaire.aggregate([{$group: {_id: "$userId", count: {$sum: 1}}}])通过userId分组得到分组字段和其他想要的字段,得到_id,userName,count userName 为…

2023年的低代码:数字化、人工智能、趋势及未来展望

本文由葡萄城技术团队发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 前言 正如许多专家预测的那样,低代码平台在2023年将展现更加强劲的势头。越来越多的企业正在纷纷转向低代…

一台电脑生成两个ssh,绑定两个GitHub账号

背景 一般一台电脑账号生成一个ssh绑定一个GitHub,即一一对应的关系!我之前有一个账号也配置了ssh,但是我想经营两个GitHub账号,当我用https url clone新账号的仓库时,直接超时。所以想起了配置ssh。于是有了今天这篇…

Flutter学习:使用CustomPaint绘制路径

Flutter学习:认识CustomPaint组件和Paint对象 Flutter学习:使用CustomPaint绘制路径 Flutter学习:使用CustomPaint绘制图形 Flutter学习:使用CustomPaint绘制文字 Flutter学习:使用CustomPaint绘制图片 drawPath 绘制路…

使用数据分析,识别设备异常

设备健康监测系统在工业领域中扮演着至关重要的角色,它能够帮助企业及时发现设备异常,预防故障,提高设备使用寿命和生产效率。而异常诊断技术则是设备健康监测系统中的核心部分,能够实现对设备异常情况的准确判断。根据设备状态数…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步: 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件,它提供了一个可视化的表格控件,允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

RHCSA --- Linux命令替换

命令替换 把命令中某个子命令替换为其执行结果 $() echo "The current directory is $(pwd)." touch ./file$(date %H-%M-%S).txt 以文件创建时间并以相应格式命名文件 date 显示时间 echo "The current direct…

C++二分算法:水位上升的泳池中游泳

涉及知识点 二分查找 并集查找或BFS。 题目 在一个 n x n 的整数矩阵 grid 中,每一个方格的值 grid[i][j] 表示位置 (i, j) 的平台高度。 当开始下雨时,在时间为 t 时,水池中的水位为 t 。你可以从一个平台游向四周相邻的任意一个平台&…

Oracle Unifier 22.12 ~ 23.10 功能改进清单表

序言 时隔近一年,Oracle Unifier 22还没握熟,新版本23便已迭代到23.10,根据甲骨文常规的发布规律,相信不久之后便会正式迎来正式本地版V23,了解Unfier的朋友或许知晓,本地版是云版迭代一年后的版本&#x…