linux驱动开发-arm汇编基础

目录

写在前面

1、Cortex-A7 处理器有 9 种处理模式

2、Cortex-A 寄存器组

通用寄存器

1、汇编语法

2、Cortex-A7 常用汇编指令

2.1 处理器内部数据传输指令

2.1.1 传输数据操作类型

1、MOV指令

2、MRS指令

3、MSR指令

2.2、存储器访问指令

2.2.1 LDR指令

2.2.2 STR指令

2.3 压栈和出栈指令

2.4 跳转指令

2.4.1 B指令

2.4.2 BL指令

2.5算术运算指令

2.6 逻辑运算指令

相关好的博文:


写在前面

记录下学习arm汇编的一些知识点

1、Cortex-A7 处理器有 9 种处理模式

2、Cortex-A 寄存器组

ARM 架构提供了 16 个 32 位的通用寄存器(R0~R15)供软件使用,前 15 个(R0~R14)可以用作通用的数据存储, R15 是程序计数器 PC,用来保存将要执行的指令。 ARM 还提供了一个当前程序状态寄存器 CPSR 和一个备份程序状态寄存器 SPSR, SPSR 寄存器就是 CPSR 寄存器的备份。

通用寄存器

R0~R15 就是通用寄存器,通用寄存器可以分为以下三类:
①、 未备份寄存器,即 R0~R7。
②、 备份寄存器,即 R8~R14。
③、程序计数器 PC,即 R15。

1、未备份寄存器
        未备份寄存器指的是 R0~R7 这 8 个寄存器,因为在所有的处理器模式下这 8 个寄存器都是同一个物理寄存器,在不同的模式下,这 8 个寄存器中的数据就会被破坏。所以这 8 个寄存器并没有被用作特殊用途。

2、备份寄存器
        备份寄存器中的 R8~R12 这 5 个寄存器有两种物理寄存器,在快速中断模式下(FIQ)它们对应着 Rx_irq(x=8~12)物理寄存器,其他模式下对应着 Rx(8~12)物理寄存器。 FIQ 是快速中断模式,看名字就是知道这个中断模式要求快速执行! FIQ 模式下中断处理程序可以使用 R8~R12寄存器,因为 FIQ 模式下的 R8~R12 是独立的,因此中断处理程序可以不用执行保存和恢复中断现场的指令,从而加速中断的执行过程。备份寄存器 R13 一共有 8 个物理寄存器,其中一个是用户模式(User)和系统模式(Sys)共用的,剩下的 7 个分别对应 7 种不同的模式。 R13 也叫做 SP,用来做为栈指针。基本上每种模式都有一个自己的 R13 物理寄存器,应用程序会初始化 R13,使其指向该模式专用的栈地址,这就是常说的初始化 SP 指针。备份寄存器 R14 一共有 7 个物理寄存器,其中一个是用户模式(User)、系统模式(Sys)和超级监视模式(Hyp)所共有的,剩下的 6 个分别对应 6 种不同的模式。R14 也称为连接寄存器(LR),LR 寄存器在 ARM 中主要用作如下两种用途:

①、每种处理器模式使用 R14(LR)来存放当前子程序的返回地址,如果使用 BL 或者 BLX来调用子函数的话, R14(LR)被设置成该子函数的返回地址,在子函数中,将 R14(LR)中的值赋给R15(PC)即可完成子函数返回。

②、当异常发生以后,该异常模式对应的 R14寄存器被设置成该异常模式将要返回的地址,R14 也可以当作普通寄存器使用。

3、程序计数器 R15

程序计数器 R15 也叫做 PC, R15 保存着当前执行的指令地址值加 8 个字节,这是因为 ARM的流水线机制导致的。 ARM 处理器 3 级流水线:取指->译码->执行,这三级流水线循环执行,比如当前正在执行第一条指令的同时也对第二条指令进行译码,第三条指令也同时被取出存放在R15(PC)中。我们喜欢以当前正在执行的指令作为参考点,也就是以第一条指令为参考点,那么 R15(PC)中存放的就是第三条指令,换句话说就是 R15(PC)总是指向当前正在执行的指令地址再加上 2 条指令的地址。对于 32 位的 ARM 处理器,每条指令是 4 个字节

R15 (PC)值 = 当前执行的程序位置 + 8 个字节。
 

4、程序状态寄存器

所有的处理器模式都共用一个 CPSR 物理寄存器,因此 CPSR 可以在任何模式下被访问。CPSR 是当前程序状态寄存器,该寄存器包含了条件标志位、中断禁止位、当前处理器模式标志等一些状态位以及一些控制位。所有的处理器模式都共用一个 CPSR 必然会导致冲突,为此,除了 User 和 Sys 这两个模式以外,其他 7 个模式每个都配备了一个专用的物理状态寄存器,叫做 SPSR(备份程序状态寄存器),当特定的异常中断发生时, SPSR 寄存器用来保存当前程序状态寄存器(CPSR)的值,当异常退出以后可以用 SPSR 中保存的值来恢复 CPSR。

1、汇编语法

label: instruction @ comment
label 即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过标号得到这个指令的地址,标号也可以用来表示数据地址。 注意 label 后面的 “ :” ,任何以“ : ”结尾的标识符都会被识别为一个标号。

 instruction 即指令 即汇编指令或者伪指令

@ 符号 , 表示后面的是注释,

comment 就是注释内容

 注意:arm中的指令,伪指令,伪操作,寄存器名都可以全部使用大写,也可以全部使用小写,但是不能大小写混用

开发者可以使用 .section 伪操作来定义一个段,汇编系统预定义了一些段名

.text 表示代码段

.data 表示初始化的数据段

.bss 表示未初始化的数据段

.rodata 表示只读数据段

.section 来定义一个段,每个段以段名开始,以下一个段名或者文件结尾结束·

.section .testsection @定义一个 testsection

汇编程序的默认入口标号是 _start ,通常在链接脚本中使用 ENTRY 来指明其他入口

.global_start

_start:

    ldr r0,=0x12 @r0=0x12

上面代码中 .global 是伪操作,表示 _start 是一个全局标号,常见伪操作包括

.byte 定义单字节数据 ,比如 .byte 0x12

.short 定义双字节数据,比如 .short 0x1234

.long 定义一个4字节数据 比如.long 0x12345678

.equ 赋值语句,格式是 .equ 变量名,表达式,比如 .equ num 0x12,表示 num=0x12

.align 数据字节对齐 比如:.align 4 表示4 字节对齐

.end 表示源文件结束

.global 定义一个全局符号,格式为 .global symbol ,比如 .global_start

GNU 汇编同时支持函数

函数名:

        函数体

        返回语句

GNU 汇编函数返回语句不是必须的,

/* 未定义中断 */

Undefined_Handler:

        ldr r0, =Undefined_Handler

        bx r0

其中 Undefined_Handler 是函数名,“ldr r0,=Undefined_Handler”是函数体,“bx r0”是函数返回语句,“bx”指令是返回指令,函数返回语句不是必须的。

2、Cortex-A7 常用汇编指令

2.1 处理器内部数据传输指令

2.1.1 传输数据操作类型

1、寄存器到寄存器

2、寄存器到特殊寄存器

3、立即数到寄存器

常用的数据传输指令: MOV  MRS MSR

指令目的描述
MOVR0 R1将R1中数据传输到R0中
MRSR0CPSR将特殊寄存器CPSR中的数据复制到R0中
MSRCPSRR1将R1里面的数据复制到特殊寄存器CPSR中
1、MOV指令

MOV指令通常是将数据从一个寄存器拷贝到另一个寄存器中,或者将一个立即数传递到寄存器里面

MOV R0,R1                         @寄存器R1中的数据传递给R0

MOV R0, #0x12                  @将立即数0x12传递给R0寄存器

2、MRS指令

MRS指令用于将特殊寄存器的值复制给普通寄存器

MSR R0,CPSR                @将CPSR中的数据复制到R0中

3、MSR指令

MSR指令和MRS指令相反,MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就是写特殊寄存器只能使用 MSR指令

MSR CPSR,R0                @将R0中的数据复制到CPSR中

2.2、存储器访问指令

arm 不能直接访问存储器,也就是需要将存储器中的数据读到寄存器中,常用的存储器访问指令主要有 LDR 和 STR

指令       描述
LDR Rd, [Rn , #offset]从存储器Rn+osset的位置读取数据存放到Rd中
STR Rd, [Rn,#offset]将 Rd 中的数据写入到存储器中的 Rn+offset 位置

2.2.1 LDR指令

LDR是将数据从存储器加载到寄存器 Rx中,LDR 也可以将立即数加载到寄存器 Rx中,LDR 加载立即数的时候要用 = ,不能使用 # 来描述立即数 。嵌入式开发中,LDR 最常用的就是读取 CPU 的寄存器值,加入有个寄存器 REG0 ,其地址为 0x81000000 ,我们要读取这个寄存器中数据,示例代码如下:

LDR R0, =0x81000000 @将寄存器地址加载到 R0 中,
LDR R1,[R0]         @读取地址0x81000000 中的数据到 R1 寄存器中

没有用到 offset ,则代表 offset 值为0

2.2.2 STR指令

LDR指令是从存储器读取数据,STR 指令是将数据写入到存储器中

LDR R0, =0x81000000
LDR R1,  =0x81000008
STR R1, [R0]    @将R1中的值写入到 R0 中保存的地址中

LDR 和 STR 都是按照字进行读取和写入的,也就是操作的是 32位的数据,如果要按照字节、半字操作的话,可以在 LDR 指令后加上 B或者 H ,字节操作的指令就是 LDRB 和 STRB,按半字进行操作的指令就是 LDRH 和 STRH

2.3 压栈和出栈指令

        会在 A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。要想再跳回 A 函数以后代码能够接着正常运行,那就必须在跳到 B 函数之前将当前处理器状态保存起来(就是保存 R0~R15 这些寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复R0~R15 即可。保存 R0~R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做恢复现场。在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。压栈的指令为 PUSH,出栈的指令为 POP, PUSH 和 POP 是一种多存储和多加载指令,即可以一次操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址。

指令描述
PUSH <reg list>将寄存器列表存入栈中
POP <reg list>从栈中恢复寄存器列表

假如我们现在要将 R0~R3 和 R12 这 5 个寄存器压栈,当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,使用的汇编代码如下:

PUSH {R0~R3,R12}        @将R0~R3和R12 压栈

PUSH {LR}         @将 LR 进行压栈

POP {LR} @先恢复 LR
POP {R0~R3,R12} @在恢复 R0~R3,R12

2.4 跳转指令

跳转操作通常可以使用 跳转指令 B、BL、BX;也可以直接往 PC 寄存器中写值,下面详细介绍一下汇编指令

指令        描述
B <label>   跳转到label ,如果跳转了超过 +、- 2KB ,可以指定 B.W <label>指令使用32位版本的跳转指令
BX <Rm>间接跳转,跳转到存放在 Rm 中的地址处,并切换指令集
BL <label>     跳转到标号位置,并将返回地址保存在 LR 中
BLX <Rm>结合 BX 和 BL的特点,跳转到 Rm 指定的地址,并将返回地址保存到 LR 中,切换指令集

2.4.1 B指令

B指令会将 PC 寄存器的值设置为跳转目标地址,但是不会再返回原来的执行处

 _start:
        dr sp,=0X80200000 @设置栈指针
        b main @跳转到 main 函数

在汇编中初始化C运行环境,然后跳转到C语言的main函数处

2.4.2 BL指令

BL指令相较于 B指令,在跳转之前会在寄存器 LR(R14)中保存当前PC寄存器的值,所以可以通过 LR 寄存器恢复现场

push {r0, r1} @保存 r0,r1
cps #0x13 @进入 SVC 模式,允许其他中断再次进去
bl system_irqhandler @加载 C 语言中断处理函数到 r2 寄存器中
cps #0x12 @进入 IRQ 模式
pop {r0, r1}
str r0, [r1, #0X10] @中断执行完成,写 EOIR
 

2.5算术运算指令

2.6 逻辑运算指令

相关好的博文:

GNU风格 汇编语法总结_gnu汇编语法-CSDN博客

https://www.cnblogs.com/zhumengke/articles/10643032.html

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

行车记录仪内存卡无法读取:问题解析与高效数据恢复策略

在智能出行的时代&#xff0c;行车记录仪作为车辆安全的守护者&#xff0c;其重要性不言而喻。然而&#xff0c;当行车记录仪的内存卡遭遇无法读取的困境时&#xff0c;不仅会影响行车记录仪的正常工作&#xff0c;更可能导致关键证据和美好回忆的丢失。本文将深入探讨行车记录…

基础 Web 开发

1. 构建项目&#xff1a; 2.添加依赖 <dependencies> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupI…

Vue3 : ref 与 reactive

目录 一.ref 二.reactive 三.ref与reactive的区别 四.总结 一.ref 在 Vue 3 中&#xff0c;ref 是一个用于创建可读写且支持数据跟踪的响应式引用对象。它主要用于在组件内部创建响应式数据&#xff0c;这些数据可以是基本类型&#xff08;如 number、string、boolean&…

【卷起来】VUE3.0教程-09-整合Element-plus

最后一次课了&#xff0c;给个关注和赞呗 &#x1f332; 简介 Element Plus 是一个基于 Vue 3 的高质量 UI 组件库。它包含了丰富的组件和扩展功能&#xff0c;例如表格、表单、按钮、导航、通知等&#xff0c;让开发者能够快速构建高质量的 Web 应用。Element Plus 的设计理念…

在 Mac 上安装虚拟机怎么样,安装虚拟机与直接安装 Windows 系统有区别吗?

随着跨系统操作的不断发展&#xff0c;虚拟机技术在生产力领域扮演着越来越重要的角色。Mac作为一款主流的操作系统&#xff0c;也有着运行虚拟机的能力。接下来给大家介绍Mac装虚拟机好不好&#xff0c;Mac装虚拟机和装Windows系统一样吗的具体内容。 Mac装虚拟机好不好 Mac…

Flip动画的实现示例demo

Flip动画的实现示例demo 文章说明核心代码效果展示Flip动画工具类的封装 文章说明 文章主要为了学习flip动画的实现思路&#xff0c;并且采用此示例效果来理解该实现思路的含义 参考渡一前端袁老师的讲解视频 核心代码 采用简单的y轴变化的动画效果为示例 <!DOCTYPE html>…

Spring Boot 3项目使用Swagger3教程

Spring Boot 3项目使用Swagger3教程 Swagger&#xff1a;自动生成接口文档 添加依赖(pom.xml) <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.1…

基于双向RRT算法的三维空间最优路线规划matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 单向RRT算法 4.2 双向RRT算法 5.完整程序 1.程序功能描述 基于双向RRT&#xff08;Randomly Exploring Random Trees, 随机探索随机树&#xff09;算法的三维空间最优路径规划是一种解…

Linux 文件与目录操作命令详解

文章目录 前言创建文件1. touch2. vim 文件内容显示3. cat4. more5. less6. head7. tail 文件&#xff08;目录&#xff09;复制、删除和移动8. cp9. rm10. mv 压缩文件与解压缩11. gzip12. zip 和 unzip 创建目录13. mkdir 删除目录14. rmdir 改变工作目录15. cd16. pwd 显示目…

碰撞检测 | 图解线段几何与线段相交检测原理(附ROS C++可视化)

目录 0 专栏介绍1 线段与线段相交检测2 线段与圆相交检测3 线段与矩形相交检测4 算法仿真与可视化4.1 核心算法4.2 仿真实验 0 专栏介绍 &#x1f525;课设、毕设、创新竞赛必备&#xff01;&#x1f525;本专栏涉及更高阶的运动规划算法轨迹优化实战&#xff0c;包括&#xf…

吸浮毛宠物空气净化器推荐,希喂、小米、有哈宠物空气净化器测评

养猫需谨慎&#xff0c;不然就要做猫奴一辈子啦&#xff01;上次堂妹来我家住几天&#xff0c;刚开始还担心和猫处不来&#xff0c;不敢去摸它&#xff0c;走的时候已经约好下次来看它的时间&#xff0c;笑死我了。毕竟猫咪这么可爱&#xff0c;很少有人可以抵抗它的魅力。 这不…

想要一劳永逸地消除 AI 幻觉,该如何做?

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话: 尽管 LLMs 基于存储、检索和生成(RAG)的方法在某些情况下能够提供准确的回答,但在面对名词短语碰撞时,RAG方法可能会因为语义相似性而失效。为了解决这个问题,本文提出了命名实体过滤(NEF)作…

SpringBoot启动成功,但端口启动失败

目录 一、问题展示 二、问题分析 2.1.端口与Tomcat的关系 2.2.问题分析 三、SpringBoot常见知识记录 3.1.SpringBoot项目常用jar包 3.1.1.必要性jar包 3.1.2.选择性jar包 3.2.标签的作用及取值 3.2.1.compile&#xff08;编译范围&#xff09; 3.2.2.provided…

Maya---机械模型制作

材质效果&#xff08;4&#xff09;_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模&#xff08;几千个面&#xff09; 动漫及影视是高模 机械由单独零件组合而成&#xff0c;需独立制作 低面模型到高面模型 卡线是为了将模型保…

[JavaEE] 网络初识(网络通信 及 TCP / UDP / IP 封装分用 )

Author&#xff1a;MTingle major:人工智能 --------------------------------------- Build your hopes like a tower! 文章目录 目录 文章目录 一. 网络通信基础 1. 局域网LAN 2. ⼴域⽹WAN 3. IP地址 4. 端口号 二.协议 1. 五元组 2. 协议分层 协议分层的优点: 3. OSI七层协…

mongoDB-1

文章目录 一、疑似坑1.11.2 mongo ops manager1.3 mongo features视图固定大小集合&#xff08;有点类似ringbuffer数据结构&#xff0c;capped collections&#xff09;(聚簇集合)clustered collection(类比到Mysql的聚簇索引)聚合管道 aggregation pipelineWiredTiger (默认存…

STM32中的计时与延时

前言 在裸机开发中,延时作为一种规定循环周期的方式经常被使用,其中尤以HAL库官方提供的HAL_Delay为甚。刚入门的小白可能会觉得既然有官方提供的延时函数,而且精度也还挺好,为什么不用呢?实际上HAL_Delay中有不少坑,而这些也只是HAL库中无数坑的其中一些。想从坑里跳出来…

【3D打印】使用simplify 3D切片更改Gcode手动断电续打、掉电、未打完继续打印、补救

一、问题描述 有些时候会遇到3D打印机没料但机器还在继续打、掉电重启后未正常恢复打印、挤出机端没有料但断料检测未触发等情况。我们又不想打印放弃&#xff0c;但又想继续之前的进度打印。 这时候我们需要更改3D打印文件的Gcode参数来进行继续打印。 至于什么是Gcode&…

帕金森遗传给子女的概率大吗?揭开真相,守护健康未来

在健康话题日益受到关注的今天&#xff0c;帕金森病这一神经系统疾病常常引发公众的广泛讨论。尤其是当谈及帕金森病是否会遗传给子女时&#xff0c;许多家庭都充满了担忧和疑惑。那么&#xff0c;帕金森病遗传给子女的概率究竟有多大&#xff1f;今天&#xff0c;我们就来揭开…

2024 年浙江省网络安全行业网络安全运维工程师项目 职业技能竞赛网络安全运维工程师(决赛样题)

2024年浙江省网络安全行业网络安全运维工程师项目 职业技能竞赛网络安全运维工程师&#xff08;决赛样题&#xff09; 应急响应&#xff1a;1 通过流量分析&#xff0c;找到攻击者的 IP 地址2 找到攻击者下载的恶意文件的 32 位小写 md5 值3 找到攻击者登录后台的 URI4 找到攻击…