10 ARM 体系
10 ARM 体系
- ARM体系
- 1、基本概念
- 1.1 常见的处理器
- 1.2 ARM7三级指令流水线
- 1.3 初识PC寄存器
- 2、 ARM核的七种工作模式
- 3、ARM核七种异常
ARM体系
1、基本概念
1.1 常见的处理器
PowerPC处理器:飞思卡尔MPC系列
DSP:TI达芬奇系列
FPGA:Xilinx赛灵思的ZYNQ系列
ARM:消费类电子:高通,华为,全志
汽车电子:飞思卡尔
网络:博通,Mavell
工控:Atmel
单片机:51,msp430,stm32(低端ARM处理器)
1.2 ARM7三级指令流水线
- 概念:
流水线:目的提高运算处理的能力
指令:给CPU下发的命令,CPU根据不同的命令做不同的数据运算,存在于编译好的二进制可执行文件中,并且是一条一条指令堆积而成,如果将二进制可执行文件下载到内存中运行,那么每条指令必然有对应的内存存储地址,例如:tftp 0x48000000 shell.bin,那么第一条指令的起始地址就是0x48000000
问:后续的指令,例如第二条指令他们的地址分别是多少呢?
答:这与ARM处理器的工作状态有关系,ARM有两种工作状态:
ARM状态:每条指令的长度是4字节大小,也就是说将来每条指令占用4字节内存大小,所有后续的指令地址依次加4,例如:第二条指令的首地址就是0x48000004
Thumb状态:每条指令的长度是2字节大小,也就是说将来每条指令占用2字节内存大小,所有后续的指令地址依次加2,例如:第二条指令的首地址就是0x48000002
所以每当go 0x48000000,那么CPU就会跑到0x48000000这个地址取出每条指令挨个运行!所谓的三级指令流水线就是CPU核处理一条指令不会一次性处理完毕,而是分成三步骤来处理! - 三步骤:
- 取指F:CPU核内部的取指器硬件单元从内存中获取指令
- 解码D:由CPU核内部的解码器硬件单元对指令进行翻译,翻译成CPU能够识别的命令
- 执行E:CPU核正式处理该指令
1.3 初识PC寄存器
PC寄存器是ARM核内部的一个寄存器,也是用来暂存数据, 此寄存器永远只能存储当前要取的那条指令的内存地址
例如:前提是ARM核处于ARM状态
内存存储地址 指令
0x8000 add加法指令
0x8004 sub减法指令
0x8008 and位与指令
注意:CPU核处理是从上往下跑
当取add这条指令时,PC寄存器的值=0x8000
问:当add指令执行的时候,PC寄存器的值=0x8008
2、 ARM核的七种工作模式
工作模式 | 切换场景 |
---|---|
SVC管理模式 | 系统复位或者代码调用swi/svc指令 |
FIQ中断模式 | 外设给CPU核发送FIQ中断电信号 |
IRQ中断模式 | 外设给CPU核发送IRQ中断电信号 |
Abort中止模式 | 取指F失败(指令没有)或者访问M失败(地址无权限) |
Undef未定义指令模式 | CPU处理一个不认识的指令,例如:lisi |
System系统模式/User用户模式 | 一般应用程序正常运行时,CPU就是处于User用户模式 |
ARM寄存器总共有37个,每个寄存器大小为32位,4字节,又细分为31个通用寄存器和6个程序状态寄存器;
31个通用寄存器的名称:r0,r1,r2…r15不区分大小写
其中:
r13又称sp:永远只能保存栈指针
r14又称lr:永远只能保存返回地址(bl指令和中断)
r15又称pc:永远只能存储取指器要取的那条指令的内存存储地址
r0,r1…r12:剩余寄存器随意存储数据
6个程序状态寄存器又分:
1个cpsr:保存当前程序运行的状态信息
5个spsr:备份cpsr的值,保存cpsr,分别是:spsr_svc,spsr_undef,spsr_irq,spsr_fiq,spsr_abort
3、ARM核七种异常
明确:异常:并不是所有的异常都是不好的,有问题的,有些异常非常棒非常好,当然了有些异常很糟糕!
前提:假设CPU一开始在0x48000000这个内存地址运行(go 0x48000000),就在此时此刻触发以下异常:
异常 | CPU核要切换到的模式 | CPU核立马要跳转到的地址 | 触发场景 |
---|---|---|---|
复位异常 | SVC管理模式 | 0x00 | 系统复位 |
Undef未定义指令异常 | Undef未定义指令模式 | 0x04 | CPU核执行一个非法指令 |
软中断异常 | SVC管理模式 | 0x08 | 代码调用swi/svc指令 |
取指异常 | Abort终止模式 | 0x0C | 取指F失败 |
数据处理异常 | Abort终止模式 | 0x10 | 访存M失败 |
IRQ中断异常 | IRQ中断模式 | 0x18 | 外设给CPU核发送IRQ中断 |
FIQ中断异常 | FIQ中断模式 | 0x1C | 外设给CPU核发送FIQ中断 |
ARM核异常处理的流程 | |||
明确:CPU核一旦触发异常,必须立马处理异常 | |||
前提:一开始CPU核很安静的执行一个QT程序,突然CPU核触发了某种异常,CPU核一旦触发异常,立马开启异常的处理: | |||
首先CPU核硬件上自动做四件事: | |||
1.备份当前被打断的QT程序的cpsr到要切换到的模式下的spsr,即:spsr_mode=cpsr | |||
2.设置cpsr |
bit\[4:0\]=xxxxx 表示设置CPU核将来要切换到的工作模式对应的模式位的值,实现工作模式的切换
bit\[5\]=0,强制CPU核切换到ARM状态
bit\[6\]=1,禁止CPU核以后响应FIQ中断信号
bit\[7\]=1,禁止CPU核以后响应IRQ中断信号
3.保存返回地址到要切换到的工作模式下的lr寄存器中(异常处理完毕将来还要回来的,所以要保存返回地址啊)
即:lr_mode = pc - 4 (硬件自动将pc的值减4保存到lr_mode中,注:mode表示要切换到的工作模式,pc此时还在QT程序中)
问:为何pc-4呢?
答:
此时CPU还在QT中运行,对应的汇编代码如下:
指令 内存地址
add 0x48000000
sub 0x48000004
and 0x48000008
… …
当CPU核执行add时,触发了某种异常,CPU核势必要处理异常,将来处理完毕异常还要进行返回,重新返回到QT程序中运行,只需要返回到sub指令即可继续向下运行,也就是只需将sub指令的地址保存到lr_mode中即可:
lr_mode=0x48000004=pc-4=0x48000008 - 4
4.设置pc为某个异常处理的入口地址,即:pc=0x00/0x04/0x08/0x0c/0x10/0x18/0x1c
切记:只要给pc赋值,就是让CPU核立马跑到这个地址去运行指令,就是取指运行
例如:pc=0x1c,就是让CPU核跑到0x1C地址去取指运行指令
pc=uart_init(函数名就是函数的首地址),就是让CPU核跑到uart_init函数去执行
只要咱们前期在这些异常的处理入口地址的地方埋伏好相关的代码,不就是让CPU核继续执行咱们埋伏好的代码吗?这不就是开启了软件进一步处理异常的流程了吗?
例如:触发一个IRQ中断,此时CPU核就会跑到0x18地址去运行埋伏好的代码!
开启软件进一步处理异常,同样四步骤:
1.提前建立异常向量表
问:如何在七种异常的入口地址放置(埋伏)或者关联对应的软件代码呢?
答:目的是将来异常发生,最终让CPU核能够执行处理到对应的异常处理代码,关联的方法就是通过链接器(arm…ld)搞定,链接器在链接的时候就是从文件的开头依次向下,会给每条指令都指定一个地址,见一条指令一个地址,见一条指令一个地址
vim start.s
.text @告诉链接器,代码段从这里开始
.code 32 @汇编指令采用的时arm
.global _start @ global:声明一个全局函数
_start:b reset @b指令的功能不带返回的跳转指令(一去不复返),跳转到reset标签继续运行b undef_functionb svc_functionb fetch_abort_functionb data_abort_functionb . @ b . 表示死循环b irq_functionb fiq_function
reset: @reset标签相关代码mov r0, #0...
undef_function:mov r1, #1...
...
irq_function:mov r0, #0mov r1, #1mov r2, #2bl do_irq
...
交叉编译:
arm...as -c -o start.o start.s //用汇编器将汇编文件生成目标文件start.o
arm...ld ... -Ttext=0x00 -o start.elf start.o //链接,注:代码段从0x00地址开始链接
链接的结果是:
地址 指令
0x00 b reset
0x04 b undef_function
0x08 b svc_function
0x0c b fetch_abort_function
0x10 b data_abort_function
0x14 b . @占坑
0x18 b irq_function
0x1c b fiq_function
...
例如:将来外设UART控制器给CPU核发送一个IRQ中断信号,最终CPU核跑到0x18地址不就是运行,咱们埋伏好的代码:b irq_function这条指令嘛,最终去执行irq_function标签里面的各种代码,开启软件处理IRQ中断异常的流程
结论:最终形成了8行2列的表格,此表又称异常向量表!
2.保护现场
一旦CPU核跑到异常入口地址执行对应的指令(b xxxxx),此指令对应的标签(xxx_function)对应的代码中首先要做保护现场的工作
问:为何要保护现场呢?
答:概念:就是将被打断的程序(例如QT程序)使用的ARM寄存器(r0~r15)的数据备份保存到栈(就是内存)中,保护现场又称压栈保护(push stack)
举例子阐述为何要备份:
一开始CPU核很安静的执行QT程序(运行的地址例如0x48000000),并且QT程序的汇编代码如下:
mov r0, #100
mov r1, #101
mov r2, #102
…
此时此刻突然UART控制器给CPU核发送一个IRQ中断信号,立马触发IRQ中断异常,CPU核最终跑到0x18地址运行: b irq_function这条指令,而这条指令最终跳转到irq_function标签继续运行,而这个标签里面的汇编代码如下:
irq_function:
mov r0, #0
mov r1, #1
mov r2, #2
…
显然IRQ中断处理的汇编代码把原先QT程序使用的ARM寄存器值进行了修改,将来CPU核再回到QT程序继续运行时势必出错,所以CPU核执行irq_function标签的代码的时候首先做的第一件事就是保护现场,把QT程序使用的ARM寄存器值r0=100…备份到内存中,将来IRQ中断处理代码随意修改,不怕了,反正有备份!
最终:irq_function标签的代码如下:
irq_function:@1.先保护现场,然后后面对ARM寄存器为所欲为mov r0, #0mov r1, #1mov r2, #2....
3.一旦现场保护完毕,软件就可以根据用户需求完成对异常的最终处理
专业叫法:调用异常处理函数
例如:触发IRQ中断异常,实现开关灯操作:
irq_function:@1.保护现场@2.根据用户需求完成开关灯操作,例如:代码如下:mov r0, #0mov r1, #1mov r2, #2....bl led_on @调用开灯函数bl delay @调用延时函数bl led_off @调用关灯函数bl delay @调用延时函数...
4.一旦异常处理完毕,异常处理函数调用完毕,最后让CPU核再回到原先被打断的QT程序继续运行,此过程做三件事:恢复现场,程序状态恢复,跳转返回
恢复现场:又称出栈恢复,将之前栈用保存的QT数据重新恢复到ARM寄存器中供QT使用
例如:r0=100,r1=101,r2=102
程序状态恢复:将之前备份到spsr_mode中的QT的cpsr的值重新恢复到cpsr中供QT使用,cpsr=spsr_mode
跳转返回:就是将之前保存的返回地址直接给pc即可,让CPU核重新回到QT程序继续运行,pc=lr_mode至此一次异常处理完毕!
例如:IRQ中断异常为例,其irq_function标签的代码参考如下:
irq_function:@1.保护现场(QT中的ARM寄存器值保存到栈中)@2.根据用户需求完成开关灯操作mov r0, #0mov r1, #1mov r2, #2....bl led_on @调用开灯函数bl delay @调用延时函数bl led_off @调用关灯函数bl delay @调用延时函数....@3.软件最后处理三步骤:@3.1.恢复现场(将栈中保存的数据恢复到ARM寄存器中),供QT使用@3.2.状态恢复:cpsr = spsr_irq,供QT使用@3.3.跳转返回:pc = lr_irq = QT程序的某个地址,至此IRQ中断异常处理完毕,CPU核又回到了QT程序继续运行,静静地带着下一次异常的触发和处理!
ARM异常处理流程的终极总结:
ARM核硬件上自动做四件事:
1.备份cpsr:spsr_mode=cpsr
2.设置cpsr:cpsr[7:0]=110xxxxx
3.保存返回地址:lr_mode=pc-4
4.设置pc=0x00/0x04/0x08/0x0c/0x10/0x18/0x1c,开启软件的处理四步骤
软件处理的四件事:
1.提前建立异常向量表
2.保护现场
3.根据用户需求调用异常处理函数
4.恢复现场,状态恢复(cpsr=spsr_mode),跳转返回(pc=lr_mode)
相关文章:

10 ARM 体系
10 ARM 体系 ARM体系1、基本概念1.1 常见的处理器1.2 ARM7三级指令流水线1.3 初识PC寄存器 2、 ARM核的七种工作模式3、ARM核七种异常 ARM体系 1、基本概念 1.1 常见的处理器 PowerPC处理器:飞思卡尔MPC系列 DSP:TI达芬奇系列 FPGA:Xilinx赛灵思的ZYN…...
ubuntu中设置开机自动运行的(sudo)指令
ubuntu版本:22.04.4 在Ubuntu中设置开机自动运行某一条(需要sudo权限的)指令,我们可以通过编辑系统的启动脚本来实现: 创建一个新的启动脚本:创建一个新的脚本文件,并将其放置在 /etc/init.d/ 目…...

删掉Elasticsearch6.x 的 .security-6索引会怎么样?
背景 玩了下 Elasticsearch 的认证,启动 ES 并添加认证后,看到索引列表额外多了一个 .security-6 。以为是没用的,手欠就给删掉了,然后 Elasticsearch 就访问不了了。 只好再重新部署,再看索引内容,发现这…...

Navicat Premium15 下载与安装(免费版)以及链接SqlServer数据库
转自:https://blog.csdn.net/m0_75188141/article/details/139842565...

Vue3配置vite.config.js代理解决跨域问题
前言: 当浏览器发出一个请求时,只要请求URL的协议、域名、端口三者之间任意一个与当前页面URL不同,就称为跨域。 跨域一般出现在开发阶段,由于线上环境前端代码被打包成了静态资源,因而不会出现跨域问题,这篇文章主要给大家介绍了关于Vue3配置vite.config.js解决跨域问题的相…...
Solidity面试题,由浅入深
Solidity是Ethereum智能合约的主要编程语言,面试题的设计旨在评估候选人对Solidity语言特性的掌握程度,以及他们对区块链和智能合约的理解。下面列出了一些常见的Solidity面试题,涵盖基础知识到高级概念,并简要说明每个问题的答案…...

变量的注意或许需要调试
输入一个自然数N(1<N<9),从小到大输出用1~N组成的所有排列,也就说全排列。例如输入3则输出 123 132 213 231 312 321 输入格式: 输入一个自然数N(1<N<9) 输出格式: N的全排列,每行一…...

C# 增删改查教程 代码超级简单
目录 一.留言 二 .帮助类 三 .增删改查代码展示 一.留言 大家好,前几篇文章我们更新了 C# 三层架构的相关代码,主要写了登录,以及增删改查的相关代码,用的三层架构的框架,那么本篇文章一次性更新C#的增删改查相关代…...
OceanBase V4.2特性解析:OB Oracle模式下的 SDO_GEOMETRY 空间数据类型
1. 背景 1.1. SDO_GEOMETRY的应用场景及能力 在数字化城市、物联网和新能源汽车等领域蓬勃发展的背景下,空间数据类型的存储和分析需求日益增长;对于涉及位置信息服务和地理位置信息应用而言,数据库中具备对sdo_geometry数据类型的支持无疑…...
简介面向对象的封装、继承、多态和抽象
面向对象(Object-Oriented)的特点通常归纳为四个核心概念:封装、继承、多态和抽象。 1. 封装(Encapsulation) 定义: 封装是将对象的属性(数据)和方法(操作)打包在一起&…...

OpenCV + CUDA + cuDNN模块编译
简介 在追求高端性能与资源优化并重的应用场景中,如边缘计算设备或资源受限的开发板上运行YOLO等复杂深度学习模型,采用C结合OpenCV与GPU加速技术相较于传统的Python环境展现出显著优势。这种策略不仅极大地提升了执行效率,还显著降低了运行时…...

Redis 缓存预热、雪崩、穿透、击穿
缓存预热 缓存预热是什么 缓存预热就是系统上线后,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!解决方案 使用 PostConstr…...

仿RabbiteMq简易消息队列基础篇(gtest的使用)
TOC gtest介绍 gtest是google的一个开源框架,它主要用于写单元测试,检查自己的程序是否符合预期行为。可在多个平台上使用(包含Linux,MAC OC,Windows等)。它提供了丰富的断言,致命和非致命失败…...

图像处理中的图像梯度和幅值是什么???(通俗讲解)
在边缘检测和特征提取等任务中,图像的梯度和幅值是图像处理中非常重要的概念。 目录 一、图像的梯度1.1 专业解释1.2 通俗理解1.3 计算方式 二、梯度的幅值2.1 专业解释2.2 通俗理解2.3 计算方式 一、图像的梯度 1.1 专业解释 图像的梯度可以看作是图像中亮度或颜…...
01.计算机网络导论
引言 协议分层 协议分层使我们可以将大任务化简成几个更小、更简单的任务。模块化指的是独立的协议层。一个协议层(模块)可以定义为一个具有输入和输出而不需要考虑输入是如何变成输出的黑匣子。当向两台机器提供相同输入得到相同输出时,它…...

API网关:SpringCloud GateWay
一. 网关的作用及背景 1.API网关的作用 请求路由 在我们的系统中由于同一个接口新老两套系统都在使用,我们需要根据请求上下文将请求路由到对应的接口。 统一鉴权 对于鉴权操作不涉及到业务逻辑,那么可以在网关层进行处理,不用下层到业务…...
【Leetcode 383】赎金信 —— 哈希表 有注解
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1: 输入&#…...

Linux 常见的冷知识集锦
一、前言 本文旨在记录那些常见的Linux概念和名词,但这些又没经常直接使用到,更多在底层运行,见过却又不是特别清楚的碎片知识,以温故知新。 二、知识点和概念说明 2.1、POSIX标准/协议 POSIX(Portable Operating S…...

【喜报】科大睿智祝贺青岛海信网络科技通过CMMI5级评估
青岛海信网络科技股份有限公司成立于1998年,是海信集团B2B产业的核心力量。其主要从事城市交通、公共交通、智慧公路、交通枢纽、智慧停车、智能网联、大数据管理、城市治理、应急管理、轨道交通智能化和医院、校园、园区等智能化建设领域的产品和解决方案开发、…...
2024全国大学生电子设计大赛全国初赛 E题 三子棋游戏装置 一等奖满分最简方案
感想:电赛初赛控制类题还是蛮简单的,别被五花八门的硬件搞懵了(决赛当我没说)。抓住核心,理念都是通用的。我是计科专业的,因此选择的控制类E题,相对来说背的知识要少很多,更考验智商…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...