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

ARM 汇编基础知识

1.为什么学习汇编?

        我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编,因为 Cortex-A 芯片一
上电 SP 指针还没初始化, C 环境还没准备好,所以肯定不能运行 C 代码,必须先用汇编语言设置好 C 环境,比如初始化 DDR 、设置 SP 指针等等,当汇编把 C 环境设置好了以后才可以运行 C 代码。
        我们要编写的是 ARM 汇编,编译使用的 GCC 交叉编译器,所以我们的汇编代码要符合 GNU 语法。

 2.GNU 语法

1.语法结构

        GNU 汇编语法适用于所有的架构,并不是 ARM 独享的, GNU 汇编由一系列的语句组成,
每行一条语句,每条语句有三个可选部分:
        
label:instruction @ comment
  • label 即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到指令的地址,标号也可以用来表示数据地址。注意 label 后面的“:”,任何以“:”结尾的标识 符都会被识别为一个标号。
  • instruction 即指令,也就是汇编指令或伪指令。@符号,表示后面的是注释,就跟 C 语言里面的“/*”和“*/”一样,其实在 GNU 汇编文件中我们也可以使用“/*”和“*/”来注释。
  • comment 就是注释内容。

for example:

add:           @标号
MOVS R0, #0X12 @指令:设置 R0=0X12
        注意!ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用
小写,但是不能大小写混用

2.section 伪操作

用户可以使用 .section 伪操作来定义一个段,汇编系统预定义了一些段名:
.text 表示代码段。
.data 初始化的数据段。
.bss 未初始化的数据段。
.rodata 只读数据段。
也可以自己定义段,每个段以段名开始,以下一段名或者文件结尾结束
.section .testsection   @定义一个 testsetcion 段

3.汇编程序入口

        汇编程序的默认入口标号是_start ,不过我们也可以在链接脚本中使用 ENTRY 来指明其它
的入口点,下面的代码就是使用 _start 作为入口标号:
/*.global是伪操作,表示_start是全局标号*/
.global _start   
_start:
ldr r0, =0x12 @r0=0x12

类似C语言,常见的伪操作有:

.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 汇编函数返回语句不是必须的

 for example:

/* SVC 中断 */
SVC_Handler:           @函数名ldr r0, =SVC_Handler  @函数体  bx r0                 @返回语句

3.Cortex-A7 常用汇编指令

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

常用:MOVMRS MSR 

1.MOV指令

将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄 存器里面
MOV R0,R1
@将寄存器 R1 中的数据传递给 R0,即 R0=R1
MOV R0, #0X12
@将立即数 0X12 传递给 R0 寄存器,即 R0=0X12

2.MRS指令

将特殊寄存器 ( CPSR SPSR) 中的数据传递给通用寄存器,要读取特殊寄存器的数据只能使用 MRS 指令!
MRS R0, CPSR @将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR

3.MSR指令

MSR 指令和 MRS 刚好相反, MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就
是写特殊寄存器,写特殊寄存器只能使用 MSR。
MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0

3.2 存储器访问指令

        ARM 不能直接访问存储器,比如 RAM 中的数据, I.MX6UL 中的寄存器就是 RAM 类型 的,我用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值写入到 Rx(x=0~12) 寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器。读取 I.MX6UL 寄存器也是一样的,只是过程相反。
        常用的存储器访问指令有两种:LDR 和 STR。
1.LDR指令
        LDR 主要用于从存储加载数据到寄存器 Rx 中,LDR 也可以将一个立即数加载到寄存器 Rx 中,LDR 加载立即数的时候要使用“ = ”,而不是“ # ”。
        在嵌入式开发中,LDR 最常用的就是读 取 CPU 的寄存器值。
例如:如 I.MX6UL 有个寄存器 GPIO1_GDIR,其地址为 0X0209C004,我们现在要读取这个寄存器中的数据,代码: 
 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中,offset为0
2.STR指令
        LDR 是从存储器读取数据, STR 就是将数据写入到存储器中,同样以 I.MX6UL 寄存器
GPIO1_GDIR 为例:
 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中
LDR 和 STR 都是按照进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、 半字进行操作的话可以在指令“LDR ”后面加上 B H ,比如按字节操作的指令就是 LDRB 和 STRB,按半字操作的指令就是 LDRH STRH

3.3压栈和出栈指令

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

 例如:将R0~R3、R12寄存器压栈操作当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,使用的汇编代码如下:

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

压栈完成以后的堆栈如图

 由于32位处理器,每个寄存器为32位,占用4个字节,这里5个寄存器占用20个字节,转换为十六进制是0x14,需要在堆栈上分配连续的地址空间长度为0x14,

        故SP指针的位置变化为:0x800000 - 0x14 = 0x7FFFFFEC

 LR 进行压栈完成以后的堆栈模型如图:

这里使用LR寄存器来存放程序的返回地址,同理, LR寄存器(备份寄存器R14)占4个字节,

SP变化:0x7FFFFFEC-0X04 = 0X7FFFFFE8

接下来作出栈操作:

POP {LR}                @先恢复 LR
POP {R0~R3,R12}  @ 在恢复 R0~R3,R12
 出栈的就是从栈顶,也就是 SP 当前执行的位置开始,地址依次减小来提取堆栈中的数据到要恢复的寄存器列表中。

        PUSH 和 POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”。STM LDM 就是多存储和多加载,可以连续的读写存储器中的多个连续数据。

3.4跳转指令

有多种跳转操作,比如:
①、直接使用跳转指令 B BL BX 等。
②、直接向 PC 寄存器里面写入数据。

一般常用的还是 BBL 或 BX

如果要在汇编中进行函 数调用使用的就是 B 和 BL 指令

1 B 指令
        这是最简单的跳转指令,B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指 令,ARM 处理器就会立即跳转到指定的目标地址,如果要调用的函数不会再返回到原来的执行
处,那就可以用 B 指令,例如:
  _start :                        @入口标号
 ldr sp ,= 0X80200000 @ 设置栈指针
 b main                        @跳转到 main 函数  跳转到 C 文件以后再也不会回到汇编了。
2 BL 指令
        BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值所以可以 通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行这是子程序调用的一个基本但常用的手段。比如 Cortex-A 处理器的 irq 中断服务函数都是汇编写的,主要用汇编来实现现场的保护和恢复、获取中断号等。但是具体的中断处理过程都是 C 函数,所以就会存在汇编中调用 C 函数的问题。而且当 C 语言版本的中断处理函数执行完成以后是需要返回到irq 汇编中断服务函数,因为还要处理其他的工作,一般是恢复现场。这个时候就不能直接使用B 指令了,因为 B 指令一旦跳转就再也不会回来了,这个时候要使用 BL 指令。

3.5算术运算指令

掌握加法运算。

3.6逻辑运算指令

具体案例再补充。

参考:

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6》

ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》和《 ARM Cortex-A(armV7) 编程手册 V4.0.pdf

相关文章:

ARM 汇编基础知识

1.为什么学习汇编? 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编,因为 Cortex-A 芯片一 上电 SP 指针还没初始化, C 环境还没准备好,所以肯定不能运行 C 代码,必须先用汇编语言设置好 C 环境…...

CRM 自动化如何改善销售和客户服务?

许多 B2B 和 B2C 公司都使用 CRM 系统来组织业务流程,使复杂的任务更容易完成。企业可以使用 CRM 自动化来自动化工作流程,让团队有更多的时间来执行高价值的任务,而不是陷于一堆琐碎事情中。 什么是CRM自动化? CRM 自动化是指 C…...

Bean 的六种作用域

目录 一、作用域是什么? 1、singleton(单例作用域) 2、prototype(原型作用域) 3、request(请求作用域) 4、session(回话作用域) 5、application(全局作用域&a…...

go语言--锁

锁的基础,go的锁是构建在原子操作和信号锁之上的 原子锁 原子包实现协程的对同一个数据的操作,可以实现原子操作,只能用于简单变量的简单操作,可以把多个操作变成一个操作 sema锁 也叫信号量锁/信号锁 核心是一个uint32值&#…...

再见,CSDN

从我2018年1月31日加入CSDN,到现在已经5年多的时间了。在这5年里,陆陆续续在CSDN上发布了很多论文阅读笔记、教程、技术文章等等,记录了我从大四到研究生再到工作这段时间的学习和成长轨迹。 我一直有备份个人资料的习惯,尤其是耗…...

MySQL总复习

目录 登录 显示数据库 创建数据库 删除数据库 使用数据库 创建表 添加数据表数据 查询表 添加数据表多条数据 查询表中某数据 增insert 删delete 改update 查select ​ where like ​编辑 范围查找 order by 聚合函数 count max min sum avg g…...

桌面平台层安全随手记录

声明 本文是学习桌面云安全技术要求. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 桌面平台层安全 桌面接入安全 用户标识 一般要求 本项要求包括: a) 系统应为用户提供唯一的身份标识,同时将用户的身份标识与该用户的所…...

【Docker】 08-Dockerfile

什么是Dockerfile Dockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的教程,主要作用是用来构建docker镜像的构建文件。 Dockerfile解析过程 Dockerfile的保留命令 保留字作用FROM当前镜像是基于哪个镜像的 第一个指令必须是FROMMA…...

【二等奖方案】大规模金融图数据中异常风险行为模式挖掘赛题「Aries」解题思路

第十届CCF大数据与计算智能大赛(2022 CCF BDCI)已圆满结束,大赛官方竞赛平台DataFountain(简称DF平台)正在陆续释出各赛题获奖队伍的方案思路,欢迎广大数据科学家交流讨论。 本方案为【大规模金融图数据中…...

Github 下载指定文件夹(git sparse-checkout)

比如要下载这里的 data_utils 步骤 1、新建空文件夹,并进入新建的空文件夹。 2、git init 初始化 3、git remote add origin 添加远程仓库 4、git config core.sparsecheckout true 允许稀疏检出 5、git sparse-checkout set 设置需要拉取的文件夹(可…...

蚂蚁集团SQLess 开源,与内部版有何区别?

当我们使用关系型数据库时,SQL 是联系起用户和数据库的一座桥梁。 SQL 是一种高度非过程化的语言,当我们在编写SQL 时,表达的是想要什么数据,而不是怎么获取数据。因此,我们往往更关心SQL 有没有满足业务逻辑&#xff…...

An Efficient Memory-Augmented Transformer for Knowledge-Intensive NLP Tasks

本文是LLM系列文章,针对《An Efficient Memory-Augmented Transformer for Knowledge 一种用于知识密集型NLP任务的高效内存增强转换器 摘要1 引言2 相关工作3 高效内存增强Transformer4 EMAT的训练流程5 实验6 分析7 结论局限性 摘要 获取外部知识对于许多自然语言…...

Java项目中jar war pom包的区别

1、pom&#xff1a;用在父级工程或聚合工程中&#xff0c;用来做jar包的版本控制&#xff0c;必须指明这个聚合工程的打包方式为pom。 <project ...> <modelVersion>4.0.0</modelVersion> <groupId>com.wong.tech</groupId> <artifactI…...

整理mongodb文档:分页

个人博客 整理mongodb文档:分页 个人博客&#xff0c;求关注&#xff0c;如果文章不够清晰&#xff0c;麻烦指出。 文章概叙 本文主要讲下在聚合以及crud的find方法中如何使用limit还有skip进行排序。 分页的情况很经常出现&#xff0c;这也是这篇博客诞生的理由。 数据准备…...

社区团购新玩法,生鲜蔬菜配货发货小程序商城

在当前的电商市场中&#xff0c;生鲜市场具有巨大的潜力和发展空间。为了满足消费者的需求&#xff0c;许多生鲜店正在寻找创新的方法来提高销售和客户满意度。其中&#xff0c;制作一个个性且功能强大的生鲜小程序商城是一个非常有效的策略。以下是在乔拓云平台上制作生鲜小程…...

shell bash中设置命令set

1 Preface/Foreword set命令用于shell脚本在执行命令时候&#xff0c;遇到异常的处理机制。 2 Usage 2.1 set -e 当执行命令过程中遇到异常&#xff0c;那么就退出脚本&#xff0c;不会往下执行其它命令。 #!/bin/bash #set -eroot GIT_TAG${CI_BUILD_TAG-NOTAG} GIT_REV…...

机器学习---预剪枝、后剪枝(REP、CCP、PEP、)

1. 为什么要进行剪枝 横轴表示在决策树创建过程中树的结点总数&#xff0c;纵轴表示决策树的预测精度。 实线显示的是决策树 在训练集上的精度&#xff0c;虚线显示的则是在⼀个独⽴的测试集上测量出来的精度。 随着树的增⻓&#xff0c;在 训练样集上的精度是单调上升的&…...

Python 爬虫—scrapy

scrapy用于从网站中提取所需数据的开源协作框架。以一种快速、简单但可扩展的方式。 该爬虫框架适合于那种静态页面&#xff0c; js 加载的话&#xff0c;如果你无法模拟它的 API 请求&#xff0c;可能就需要使用 selenium 这种使用无头浏览器的方式来完成你的需求了 入门 imp…...

ABB机器人20032转数计数器未更新故障报警处理方法

ABB机器人20032转数计数器未更新故障报警处理方法 ABB的机器人上面安装有电池,需要定期进行更换(正常一年换一次),如果长时间不更换,电量过低,就会出现转数计数器未更新的报警,各轴编码器的位置就会丢失,在更换新电池后,需要更新转数计数器。 具体步骤如下: 先用手动…...

C# 记事本应用程序

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System...

模型训练:优化人工智能和机器学习,完善DevOps工具的使用

作者&#xff1a;JFrog大中华区总经理董任远 据说法餐的秘诀在于黄油、黄油、更多的黄油。同样&#xff0c;对于DevOps而言&#xff0c;成功的三大秘诀是自动化、自动化、更高程度的自动化&#xff0c;而这一切归根结底都在于构建能够更快速地不断发布新版软件的流程。 尽管人…...

WorldCoin 运营数据,业务安全分析

WorldCoin 运营数据&#xff0c;业务安全分析 Worldcoin 的白皮书中声明&#xff0c;Worldcoin 旨在构建一个连接全球人类的新型数字经济系统&#xff0c;由 OpenAI 创始人 Sam Altman 于 2020 年发起。通过区块链技术在 Web3 世界中实现更加公平、开放和包容的经济体系&#…...

Java之Calender类的详细解析

Calendar类 3.1 概述 java.util.Calendar类表示一个“日历类”&#xff0c;可以进行日期运算。它是一个抽象类&#xff0c;不能创建对象&#xff0c;我们可以使用它的子类&#xff1a;java.util.GregorianCalendar类。 有两种方式可以获取GregorianCalendar对象&#xff1a; …...

uniapp 微信小程序 锚点跳转

uniapp文档 以下是我遇到的业务场景&#xff0c;是点击商品分类的某一类 然后页面滚动至目标分类&#xff0c; 首先第一步是设置锚点跳转的目的地&#xff0c;在目标的dom上面添加id属性 然后给每个分类每一项添加点击事件&#xff0c;分类这里的item数据里面有一字段是和上…...

主成分分析笔记

主成分分析是指在尽量减少失真的前提下&#xff0c;将高维数据压缩成低微的方式。 减少失真是指最大化压缩后数据的方差。 记 P P P矩阵为 n m n\times m nm&#xff08; n n n行 m m m列&#xff09;的矩阵&#xff0c;表示一共有 m m m组数据&#xff0c;每组数据有 n n n…...

android studio 的 adb配置

首先在 Android Studio 中 打开 File -> Settings: 下载 “Google USB Driver” 这个插件 (真机调试的时候要用到), 并且记一下上面的SDK路径: 右键桌面上的 “我的电脑”, 点击 “高级系统设置”, 配置计算机的高级属性, 有两步: 添加一个新的环境变量 ANDROID_HOME, 变量…...

【HTML5高级第一篇】Web存储 - cookie、localStorage、sessionStorage

文章目录 一、数据存储1.1 cookie1.1.1 概念介绍1.1.2 存储与获取1.1.3 方法的封装1.1.4 总结 1.2 localstorage 与 sessionstorage1.2.1 概述1.2.2 操作数据的属性或方法1.2.3 案例-提交问卷1.2.4 Web Storage带来的好处 附录&#xff1a;1. HTML5提供的数据持久化技术&#x…...

Flink---1、概述、快速上手

1、Flink概述 1.1 Flink是什么 Flink的官网主页地址&#xff1a;https://flink.apache.org/ Flink的核心目标是“数据流上有状态的计算”(Stateful Computations over Data Streams)。 具体说明&#xff1a;Apache Flink是一个“框架和分布式处理引擎”&#xff0c;用于对无界…...

QT实现TCP通信(服务器与客户端搭建)

一、TCP通信框架 二、QT中的服务器操作 创建一个QTcpServer类对象&#xff0c;该类对象就是一个服务器调用listen函数将该对象设置为被动监听状态&#xff0c;监听时&#xff0c;可以监听指定的ip地址&#xff0c;也可以监听所有主机地址&#xff0c;可以通过指定端口号&#x…...

云备份项目

云备份项目 1. 云备份认识 自动将本地计算机上指定文件夹中需要备份的文件上传备份到服务器中。并且能够随时通过浏览器进行查看并且下载&#xff0c;其中下载过程支持断点续传功能&#xff0c;而服务器也会对上传文件进行热点管理&#xff0c;将非热点文件进行压缩存储&…...