ARM 汇编基础知识

news2024/11/28 8:30:41

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=0X0209C004
 LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中,offset为0
2.STR指令
        LDR 是从存储器读取数据, STR 就是将数据写入到存储器中,同样以 I.MX6UL 寄存器
GPIO1_GDIR 为例:
 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
 LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
 STR 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

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

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

相关文章

【python】实现积分

借助sympy.integrate() 符号运算库,所以里面的exp(),sin()等都要使用sympy库中的函数,如果使用numpy库中的函数时没用的。 import sympy as sp import numpy as np x sp.symbols("x") print(sp.integrate(sp.exp(-x**2), (x, -s…

企业数据加密软件——「天锐绿盾」

「天锐绿盾」是一款企业数据加密软件,主要用于防止企业计算机信息被破坏、丢失和泄密。该软件采用文件过滤驱动实现透明加解密,对用户完全透明,不影响用户操作习惯。 PC访问地址: isite.baidu.com/site/wjz012xr/2eae091d-1b97-4…

makefile开发应用程序的一个通用模板

下面是一个通用的 Makefile 模板,用于开发 C 语言应用程序: # 编译器设置 CC gcc CFLAGS -Wall -Wextra -stdc99# 可执行文件名 TARGET your_program# 源文件和对象文件 SRCS main.c file1.c file2.c OBJS $(SRCS:.c.o)# 默认目标 all: $(TARGET)#…

buildroot修改内核防止清理重新加载办法

当你使用 Buildroot 构建 Linux 内核时,如果对内核文件进行了手动修改,重新执行 Buildroot 的构建过程将会覆盖你所做的修改。这是因为 Buildroot会根据配置重新下载、提取和编译内核。 为了避免在重新构建时覆盖你的修改,可以采取以下两种方…

减量时代下,伊利金领冠DTB新模式凭什么成为母婴行业“破局之道”?

穷则变,变则通,通则久。 当下,许多行业正在穿越不确定性周期,增长放缓成为常态。如何通过创新应对变局,进而实现长期主义,成为摆在所有行业和企业面前的课题。 众多行业中,婴配粉市场的不确定…

lv3 嵌入式开发-3 linux shell命令(文件搜索、文件处理、压缩)

目录 1 查看文件相关命令 1.1 常用命令 1.2 硬链接和软链接 2 文件搜索相关命令 2.1 查找文件命令 2.2 查找文件内容命令 2.3 其他相关命令 3 文件处理相关命令 3.1 cut 3.2 sed 过滤 3.3 awk 匹配 4 解压缩相关命令 4.1 解压缩文件的意义 4.2 解压缩相关命令 1 …

推荐个一行代码的Python可视化神器

学过Python数据分析的朋友都知道,在可视化的工具中,有很多优秀的三方库,比如matplotlib,seaborn,plotly,Boken,pyecharts等等。这些可视化库都有自己的特点,在实际应用中也广为大家使…

数据结构(Java实现)-反射、枚举以及lambda表达式

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分…

内网隧道代理技术(二十一)之 CS工具自带中转技术上线不出网机器

CS工具自带上线不出网机器 如图A区域存在一台中转机器,这台机器可以出网,这种是最常见的情况。我们在渗透测试的过程中经常是拿下一台边缘机器,其有多块网卡,边缘机器可以访问内网机器,内网机器都不出网。这种情况下拿这个边缘机器做中转,就可以使用CS工具自带上线不出网…

shiro550漏洞分析

准备工作 启动该项目 可以看到没有登录时候,cookie中没有rememberme字段 登录时候 当账号密码输入正确时候 登录后存在该字段 shiro特征: 未登陆的情况下,请求包的cookie中没有rememberMe字段,返回包set-Cookie⾥也没有del…

JMeter测试工具

JMeter测试工具 1、下载地址: https://downloads.apache.org/jmeter/binaries/ https://downloads.apache.org/jmeter/binaries/2、启动 解压: 点击bin目录下的jmeter.bat就可以运行 jmeter.bat3、流控规则测试

蓝牙发展现状

目录 一、产品分类1、Bluetooth经典2、Bluetooth低能耗(LE)3、二者差异 二、出货量三、未来需要加强的方向四、技术行业细分五、学习资料1、蓝牙官网2、大神博客——于忠军 一、产品分类 1、Bluetooth经典 Bluetooth Classic无线电,也被称为Bluetooth 基本速率/增强…

EasyExcel导出模板实现下拉选(解决下拉超过50个限制)

学习地址:https://d9bp4nr5ye.feishu.cn/wiki/O3obweIbgi2Rk1ksXJncpClTnAfB站视频:https://www.bilibili.com/video/BV1H34y1T7Lm 先来看看最终实现效果,如果效果是你想要的,再看看实现逻辑。 EasyExcel本身是支持设置下拉校验的…

大学物理 之 安培环路定理

文章目录 前言什么是安培环路定理安培环路定理有什么作用 深入了解深入学习 前言 什么是安培环路定理 安培环路定理的物理意义在于描述了电流和磁场之间的相互作用,以及如何在一个封闭的回路中分析这种相互作用。 简单的来说 , 用环路定理来解决在磁场中B对任意封…

教你如何让iPhone电池更健康,不容错过的10个技巧

iPhone是一款功能强大的设备,但与许多电子产品一样,它需要一些维护才能确保正常工作。就像一艘可以永远航行的船,只要人们愿意维护它,只要你保持电池健康,你的iPhone就会继续工作。 以下是为什么维护iPhone电池至关重要,以及如何做到这一点,让你的设备使用更长时间。 …

数据结构 -作用及基本概念

为什么要使用数据结构 学习数据结构是计算机科学和软件工程领域中非常重要的一门课程。以下是学习数据结构的几个重要原因: 组织和管理数据:数据结构提供了一种组织和管理数据的方式。通过学习不同的数据结构,你可以了解如何有效地存储和操作…

【项目经验】:elementui表格中表头的多选框换成文字

一.项目需求 表格可以多选,表头都是汉字。。。。类似于这种 二.实现功能 用到的方法 Table Attributes 参数说明类型可选值默认值header-cell-class-name表头单元格的 className 的回调方法,也可以使用字符串为所有表头单元格设置一个固定的 className。…

在STS里使用Gradle编译Apache POI5.0.0

1、到官方下面地址下载Gradle最新的版本 Gradle Distributions 2、解压后拷贝到D盘下D:\gradle-8.3-rc-4里 3、配置环境变量 新建系统变量 GRADLE_HOME ,值为 路径 4、在 Path 中添加上面目录的 bin 文件路径 (可以用 %GRADLE_HOME%\bin&#xff0c…

Web3 solidity编写cancelorder取消订单函数 并梳理讲述逻辑

上文 Web3 solidity订单池操作 中 我们讲述了订单池的基本概念 并手动编写了创建订单的操作 最近的 我们还是先将 ganache 环境起起来 然后 我们打开项目 上文中 我们写了makeOrder创建订单的函数 但是 也带出一个问题 我们创建之后 如果不要了 怎么干掉呀? js中我…

CS420 课程笔记 P2 - 内存编辑和基础的 GameHacking 尝试

文章目录 IntroductionOperating SystemToolsMemory ScanningMemory ScanExamples!Conclusion Introduction 本节将介绍操作系统的基础知识和内存扫描,这可以说是 game hacking 中最重要的技能,我们不会深入讨论操作系统,因为这本身就是一门…