ARM 汇编基础总结

GNU 汇编语法

编写汇编的过程中,其指令、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用。

1. 汇编语句的格式

label: instruction @ comment

  • label即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到指令的地址,标号也可以用来表示数据地址。注意 label 后面的" : ",任何以" : "结尾的标识符都会被识别为一个标号。在汇编语言中,_start是一个特殊的标号(label),_start是程序执行的入口点,程序执行的起始地址,当程序加载到内存中时,处理器会跳转到_start标签所在的地址,从这里开始执行代码。_start主要作用是初始化程序运行环境,比如栈、全局变量、动态链接环境,然后跳转到用户定义的main函数执行。
  • instruction即指令,也就是汇编指令或伪指令
  • @表示后面的是注释,跟 C 语言的“/*”和“*/”一样,在 GNU 汇编文件中也可以使用“/*”和“*/”来注释
  • comment就是注释内容
2. 预定义段名

.section 伪操作,用于指定汇编代码或数据应当放入哪个段, 或者定义自己的自定义段,每个段以段名开始,以下一段名或者文件结尾结束

.text 表示代码段

.data 初始化的数据段

.bss 未初始化的数据段

.rodata 只读数据段

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

.equ 赋值语句,比如.equ num,0x12,表示num=0x12

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

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

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

.end 表示源文件结束

.global 定义一个全局符号,比如.global _start

.section .data         // 数据段
message:.asciz "Hello, World!"  // 字符串常量.section .text         // 代码段
.global _start         // 声明程序入口
_start:mov eax, 4         // 系统调用号,写操作mov ebx, 1         // 文件描述符(1是标准输出)lea ecx, [message] // 将字符串地址加载到 ecxmov edx, 13        // 要写入的字节数int 0x80           // 调用内核mov eax, 1         // 系统调用号,退出程序xor ebx, ebx       // 返回值为0int 0x80           // 调用内核

Cortex-A7 常用汇编指令

处理器内部数据传输指令

数据传输常用的指令有三个: MOV、 MRS 和 MSR。

指令

目标寄存器

源寄存器

功能

MOV R1, R0

R0

R1

将 R1 里面的数据复制到 R0 中

MRS R0, CPSR

R0

CPSR

将特殊寄存器 CPSR 里的数据复制到 R0

MSR CPSR, R1

CPSR

R1

将 R1 里面的数据复制到特殊寄存器 CPSR

1. MOV(Move)

MOV 指令将一个立即数或一个寄存器的值赋值到另一个寄存器中,只能操作通用寄存器,不能直接访问系统状态寄存器(CPSR)。

MOV R0, #0x1234 //将立即数 0x1234 赋值到寄存器 R0, 即R0 = 0X1234
MOV R1, R0 		//将寄存器 R0 的值复制到寄存器 R1, 即R1 = R0
2. MRS(Move Register from System)

MRS 指令将系统状态寄存器中的值读取到通用寄存器中。

MRS R0, CPSR //将系统状态寄存器 (CPSR) 的值存入 R0, 即R0=CPSR
MRS R1, SPSR //将系统状态寄存器 (SPSR) 的值存入 R1, 即R0=SPSR
3. MSR(Move System Register)

MSR 指令将系统状态寄存器中的值读取到通用寄存器中。

MSR SPSR, R0    //将 R0 的值写入 SPSR 系统寄存器中, 即SPSR=R0

存储器访问指令

常用的存储器访问指令有两种: LDR 和 STR 在编写汇编驱动的时候最常用这两个指令。在 32 位处理器中 LDR 和 STR 都是操作 4 个字节的地址,也就是 32 位数据。

指令

功能

LDR Rd, [Rn, #offset]

从 Rn+offset 的地址读取数据存到 Rd 中

STR Rd, [Rn, #offset]

将 Rd 寄存器中的数据写入到 Rn+offset 地址

1. LDR(Load Register)

LDR 指令用于从内存中加载一个值到寄存器,[ R1 ] 表示以 R1 存储的数字为地址。

LDR R0, = 0x20000000 //将立即数 0x20000000 加载到寄存器 R0 中//如果地址 0x20000000 存储的值是 0x1234, 则执行后 R0 = 0x1234
LDR R0, [R1]     //将内存地址 R1 指向的数据加载到寄存器 R0 中//带偏移量的加载, 如果地址 0x20000004 存储的值是 0x6789, 则执行后 R0 = 0x6789
LDR R0, [R1, #4] //将 R1 + 4 的地址处的数据加载到 R0 中
2. STR(Store Register)

STR 指令用于将寄存器中的值存储到内存地址中。

STR R0, [R1]     //将 R0 的值存储到内存地址 R1 指向的地址
STR R0, [R1, #4] //将 R0 的值存储到 R1 + 4 的地址处

栈指针

SP 指针(Stack Pointer,栈指针)是计算机体系结构中一个重要的寄存器 ,在不同的处理器架构中,SP寄存器是硬件层面预定义的,处理器会专门保留一个寄存器用来表示栈指针。在 ARM 架构中 R13 是专门的寄存器,SP是它的别名。SP指向栈的当前顶部或下一条可用地址。

1. 栈的应用

在程序执行过程中,栈通常用于管理函数调用、局部变量和保存寄存器内容等任务。当函数被调用时,局部变量、返回地址、保存的寄存器等会被压入栈中,SP指针会自动调整,指向栈的最新位置,当函数返回时,这些数据会被弹出,SP指针恢复到调用前的位置。

2. 栈指针位置

SP设置栈指针(C 语言运行的时候需要出栈和入栈,所以需要栈内存),SP指针可以指向内部 RAM 也可以指向 DDR,以指向 DDR 为例,假设 DDR 的大小是 512MB,起始地址为 0x80000000,那么 DDR 的地址范围是 0x8000_0000~0x9FFF_FFFF,设置栈大小为 2MB=0x0020_0000(对于裸机运行已经够大了),栈的增长方式是向下增长,即高地址向低地址增长,所以设置栈地址为 0x8020_0000,保证栈不会溢出。

.global _start          // 声明程序入口
_start:ldr sp, =0X80200000  // 设置栈指针的起始地址
b main 				          //跳转到main函数

压栈和出栈指令

常用的栈操作指令是 PUSH 和 POP 。压栈和出栈指令通常用于保存和恢复寄存器的值,或者用于函数调用的返回地址。

1. PUSH(压栈)

PUSH 指令将寄存器的值压入栈中,并自动更新栈指针。它是对栈操作的简化形式,常用于保存寄存器的值。例如: PUSH {R0, R1, R2, R3}

2. POP(出栈)

POP 指令从栈中弹出寄存器的值,恢复寄存器的内容,并自动更新栈指针。例如:POP {R0, R1, R2, R3}

在压栈出栈的过程中,要保证先进后出的特性,最后压入栈中的寄存器最先出栈。例如,压栈的顺序为R0 -> R1 -> R2 -> R3,那么出栈的顺序为R3 -> R2 -> R1 -> R0。下面以中断场景举例压栈和出栈,在中断服务例程中,保存和恢复多个寄存器的值也非常常见。由于中断会打断程序的正常执行流程,所以需要保存现场,确保中断处理完成后能够正确地恢复执行。

ISR_Handler:PUSH {R0, R1, R2, R3}   // 保存现场, 保存 R4, R5, R6, R7 到栈中//中断处理逻辑POP {R0, R1, R2, R3}    // 恢复现场, 恢复 R4, R5, R6, R7BX LR                   // 返回到调用者

跳转指令

常用的跳转指令有 B 和 BK,其中 B 指令跳转后不会回到原来位置,BK 跳转后待函数执行完还会回到原来位置。

1. B(Branch)

B 指令这是最简单的跳转指令, B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指令, ARM 处理器就会立即跳转到指定的目标地址。如果要调用的函数不会再返回到原来的执行处,那就可以用 B 指令,如下示例

_start:
ldr sp, =0X80200000 //设置栈指针
b main             //跳转到 main 函数//用 B 指令实现 loop 死循环
loop:b loop
2. BL(Branch with Link )

BL 指令相比 B 指令的区别是 BL 会跳转到指定函数,待函数执行完再返回原来位置继续执行,因为在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。比如 Cortex-A 处理器的 irq 中断服务函数都是汇编写的,主要用汇编来实现现场的保护和恢复、获取中断号等。但是具体的中断处理过程都是 C 函数,所以就会存在汇编中调用 C 函数的问题。

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

算术运算指令

常用加法、减法,乘除很少用

指令

计算公式

说明

ADD Rd, Rn, Rm

Rd = Rn + Rm

加法运算,指令为 ADD

ADD Rd, Rn, #immed

Rd = Rn + #immed

ADC Rd, Rn, Rm

Rd = Rn + Rm + 进位

带进位的加法运算,指令为 ADC

ADC Rd, Rn, #immed

Rd = Rn + #immed +进位

SUB Rd, Rn, Rm

Rd = Rn – Rm

减法

SUB Rd, #immed

Rd = Rd - #immed

SUB Rd, Rn, #immed

Rd = Rn - #immed

SBC Rd, Rn, #immed

Rd = Rn - #immed – 借位

带借位的减法

SBC Rd, Rn ,Rm

Rd = Rn – Rm – 借位

MUL Rd, Rn, Rm

Rd = Rn * Rm

乘法(32 位)

UDIV Rd, Rn, Rm

Rd = Rn / Rm

无符号除法

SDIV Rd, Rn, Rm

Rd = Rn / Rm

有符号除法

在 CPU 运行过程中,如果想执行运算操作,必须要先将数据加载到寄存器中,然后才能执行运算操作!

// 实现 DDR 两个地址数据相加
LDR R0, [#0x20000000]   // 从地址 0x20000000 加载数据到 R0
LDR R1, [#0x20000004]   // 从地址 0x20000004 加载数据到 R1
ADD R2, R0, R1          // 将 R0 和 R1 的值相加,结果存入 R2// 实现两个立即数相加
MOV R0, #0x1          // 将立即数 0x1 加载到 R0
MOV R1, #0x2          // 将立即数 0x2 加载到 R1
ADD R2, R0, R1        // 将 R0 和 R1 的值相加,结果存入 R2

逻辑运算指令

指令

计算公式

说明

AND Rd, Rn

Rd = Rd &Rn

按位与

AND Rd, Rn, #immed

Rd = Rn &#immed

AND Rd, Rn, Rm

Rd = Rn & Rm

ORR Rd, Rn

Rd = Rd | Rn

按位或

ORR Rd, Rn, #immed

Rd = Rn | #immed

ORR Rd, Rn, Rm

Rd = Rn | Rm

BIC Rd, Rn

Rd = Rd & (~Rn)

位清除

BIC Rd, Rn, #immed

Rd = Rn & (~#immed)

BIC Rd, Rn , Rm

Rd = Rn & (~Rm)

ORN Rd, Rn, #immed

Rd = Rn | (#immed)

按位或非

ORN Rd, Rn, Rm

Rd = Rn | (Rm)

EOR Rd, Rn

Rd = Rd ^ Rn

按位异或

EOR Rd, Rn, #immed

Rd = Rn ^ #immed

EOR Rd, Rn, Rm

Rd = Rn ^ Rm

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

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

相关文章

【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库

**前言:**本节内容介绍使用C/C访问数据库, 包括对数据库的增删查改操作。 主要是学习一些接口的调用, 废话不多说, 开始我们的学习吧! ps:本节内容比较容易, 友友们放心观看哦! 目录 准备mysql…

华为配置 之 RIP

简介: RIP(路由信息协议)是一种广泛使用的内部网关协议,基于距离向量算法来决定路径。它通过向全网广播路由控制信息来动态交换网络拓扑信息,从而计算出最佳路由路径。RIP易于配置和理解,非常适用于小型网络…

1.GPU简介及英伟达开发环境配置

前言 This book shows how, by harnessing the power of your computer’s graphics process unit (GPU), you can write high-performance software for a wide rangeof applications.Although originally designed to render computer graphics ona monitor (and still used…

电脑cxcore100.dll丢失怎么办?

电脑运行时常见问题解析:应对DLL文件丢失、文件损坏与系统报错的实用指南 在数字时代,电脑已成为我们工作、学习和娱乐不可或缺的工具。然而,正如任何精密机械都可能遇到故障,电脑在运行过程中也难免会遇到各种问题,如…

【无线传感网】时间同步技术

文章目录 时间同步模型时钟模型1. 节点本地时钟模型2. 节点逻辑时钟模型 通信模型1. 单向报文传递2. 双向报文交换3. 广播参考报文4. 参数拟合技术 时钟同步的误差来源 时间同步协议时钟同步的类别1. 时钟速率同步与偏移同步2. 同步期限:长期同步与按需同步3. 同步范…

C# 实用工具分享(1)

大家好,今天分享一些在开发过程中比较实用的工具。 首先在软件开发的过程中不可避免的要使用截图这样的功能,以前这样的功能我自己也是选择开发出新功能。但是自己开发还是非常费时费力的,并且效果也不一定特别好。 于是我找到了一个现成的…

积分图(Integral Image)与均值滤波的快速实现

积分图(Integral Image)也称为求和图(Summed Area Table),是一种用于快速计算图像中任意矩形区域像素值总和的技术。 基本概念 积分图的每个位置(i, j)存储的是从图像左上角(1, 1)到当前位置(i, j)所有像素值的累积和…

curl+openssl 踩坑笔记

curl编译:点击跳转 踩坑一 * SSL certificate problem: unable to get local issuer certificate * closing connection #0 curl: (60) SSL certificate problem: unable to get local issuer certificate More details here: https://curl.se/docs/sslcerts.html …

[AI] 深度学习的“黑箱”探索:从解释性到透明性

目录 1. 深度学习的“黑箱”问题:何为不可解释? 1.1 为什么“黑箱”问题存在? 2. 可解释性研究的现状 2.1 模型解释的方法 2.1.1 后置可解释性方法(Post-hoc Explanations) 2.1.2 内在可解释性方法(I…

python-Flask:SQLite数据库路径不正确但是成功访问到了数据库,并对表进行了操作

出现了这个问题,就好像是我要去找在南方的人,然后我刚好不分南北,我认为的方向错了,实则方向对了。 在我针对复盘解决:sqlite3.OperationalError: unrecognized token: “{“-CSDN博客这个内容的时候,又出现…

对称密码算法(分组密码算法 序列密码算法 密码杂凑算法)中的基本操作

对称密码算法(分组密码算法 序列密码算法 密码杂凑算法)中的基本操作 相比非对称加密算法,对称加密算法因为加解密效率较高,因而在日常使用中更加广泛。为了让大家更加熟悉常见的对称加密算法,本文列举出了对称密码算法设计中经常用到的13种基…

大数据治理,数字化转型运营平台建设方案(PPT完整版)

1、大数据治理整体运营思路 2、数据资产定义及流程规范 3、治理规范及质量管控 4、质量考核标准及提升方案 软件全套资料部分文档清单: 工作安排任务书,可行性分析报告,立项申请审批表,产品需求规格说明书,需求调研计划…

专题十四——BFS

目录 一BFS解决FloodFill算法 1图像渲染 2岛屿数量 3岛屿的最大面积 4被环绕的区域 二BFS解决蛋源最短路径问题 1迷宫中离入口最近的出口 2最小基因变化 3单词接龙 4为高尔夫比赛砍树 三BFS解决多源最短路径问题 1 01矩阵 2飞地的数量 3地图中的最高点 4地图分…

DMDRS部署:搭建DM8-DM8数据同步

一、部署要求 1.1 硬件要求 DMDRS服务描述源DMDRS 内存要求至少2GB的内存空间。推荐配置4GB及以上的内存空间。 源DMDRS对内存空间的需求主要与装载的并发数相关。当内存空间配置低于2GB时,可以调整装载的线程数来降低源DMDRS对内存空间的需求。 磁盘要求至少10GB…

仓颉笔记——windows11安装启用cangjie语言,并使用vscode编写“你好,世界”

2025年1月1日第一篇日记,大家新年好。 去年就大致看了一下,感觉还不错,但一直没上手,这次借着元旦的晚上安装了一下,今年正式开动,公司众多的应用国产化正等着~~ 第一步:准备 官网:…

datalist的作用?怎么用的?

在 HTML 中&#xff0c;<datalist> 元素用于为 <input> 元素提供一个可选项列表&#xff0c;帮助用户通过预定义的选项进行快速选择。它是一个增强输入体验的功能&#xff0c;类似于自动完成&#xff08;autocomplete&#xff09;&#xff0c;但与传统的 <selec…

Cocos2dx Lua绑定生成中间文件时参数类型与源码类型不匹配

这两天维护的一个项目&#xff0c;使用arm64-v8a指令集编译时遇到了报错&#xff0c;提示类型不匹配&#xff0c;具体报错的代码【脚本根据C源文件生成的中间文件】如下&#xff1a; const google::protobuf::RepeatedField<unsigned long long>& ret cobj->equi…

1、ELK的架构和安装

ELK简介 elk&#xff1a;elasticsearch logstash kibana&#xff0c;统一日志收集系统。 elasticsearch&#xff1a;分布式的全文索引引擎的非关系数据库&#xff0c;json格式&#xff0c;在elk中存储所有的日志信息&#xff0c;架构有主和从&#xff0c;最少需要2台。 …

常用的数据库类型都有哪些

在Java开发和信息系统架构中&#xff0c;数据库扮演着存储和管理数据的关键角色。数据库种类繁多&#xff0c;各有特色&#xff0c;适用于不同的应用场景。 1. 关系型数据库&#xff08;RDBMS&#xff09;&#xff1a; • 关系型数据库是最为人熟知的数据库类型&#xff0c;数据…

百度贴吧的ip属地什么意思?怎么看ip属地

在数字化时代&#xff0c;IP地址不仅是网络设备的唯一标识符&#xff0c;更承载着用户的网络身份与位置信息。百度贴吧作为广受欢迎的社交平台&#xff0c;也遵循相关规定&#xff0c;在用户个人主页等位置展示账号IP属地信息。那么&#xff0c;百度贴吧的IP属地究竟意味着什么…