ARM 汇编语言基础
目录
汇编指令代码框架
汇编指令语法格式
数据处理指令
数据搬移指令 mov
示例
立即数的本质
立即数的特点
立即数的使用
算术运算指令
指令格式
add 普通的加法指令
adc 带进位的加法指令
跳转指令
Load/Store指令
状态寄存器指令
基础概念
-
C 语言与汇编指令的关系
- 语句:带有分号 (
;) 的 C 语言语句可以被编译成汇编指令。 - 预处理指令:以井号 (
#) 开头的行称为预处理指令,它们告诉编译器如何处理源代码。
- 语句:带有分号 (
-
汇编语言的整体分类
- 指令:编译后生成一条机器码,存储在内存中供 CPU 执行。
- 伪操作:不生成机器码也不占用内存,用于控制汇编过程。
(相当于c中的’#‘的内容)告诉编译器怎么编译)
- 伪指令:在编译时被替换为一系列等效的指令,用于实现某些高级功能。
(如:cpu中没有乘法器,对应没有乘法指令,3*3 ---》用加法器实现3+3+3,替换实现)
-
注释
- 单行注释:使用
@符号开始。 - 多行注释:使用
/**/包围。
- 单行注释:使用
-
指令分类
- 数据处理指令:对数据进行逻辑和算术运算。
- 跳转指令:改变程序流程,即修改程序计数器 PC。
- Load/Store 指令:读取和写入内存。
- 状态寄存器传送指令:读写 CPSR(当前程序状态寄存器)。
- 异常中断产生指令:触发软件中断(SWI),用于系统调用。
- 协处理器指令:操作协处理器,比如浮点运算单元 FPU。
汇编指令代码框架
.text
.global _start
_start:; 汇编代码段
.end
汇编指令语法格式
<opcode><code>{s} Rd, Rn, operand2
- opcode:指令名称。
- code:条件码,可选,默认无条件执行。
- s:是否更新 CPSR 的标志位。
- Rd:目标寄存器。
- Rn:第一个操作寄存器。
- operand2:第二个操作数,可以是寄存器或立即数。
- 注:指令的名字,条件码,s连到一起写,指令名和目标寄存器之间使用空格,寄存器和数据之间使用逗号隔开,指令中的字符不区分大小写
数据处理指令
数据搬移指令 mov
- 格式:
<opcode><code>{s} Rd, operand2 - 立即数形式:
mov{<code>}{s} Rd, #immediate
示例
在这个示例中,我们首先声明了一个 .text 段,然后定义了一个全局符号 _start,这是程序的入口点。接下来我们初始化寄存器 R0 为 0x1234,然后将 R0 的值复制给 R1。最后,通过 bx lr 返回到调用者
.text
.global _start_start:; 初始化寄存器 R0 为 0x1234mov r0, #0x1234; 将 R0 的值移动到 R1mov r1, r0; 结束程序bx lr.end
- 1》数据搬移指令 mov
- @ 格式:<opcode><code>{s} Rd, oprand2
- 如果是立即数,前边必须加#

PC寄存器详细讲解:


指令的执行三步:取指,译码,执行(PC永远指向当前正在取指指令的地址)。
立即数在 ARM 汇编语言中是一个重要的概念。立即数是直接编码在指令中的数值,它与普通变量不同,后者通常存储在内存中。下面是关于立即数的一些详细说明和优化后的格式:
立即数的本质
立即数是直接嵌入在指令中的数据,作为指令的一部分。这意味着当指令被加载到处理器中时,立即数也会同时被加载。
立即数的特点
- 优点:
- 快速访问:因为立即数是与指令一同加载的,所以不需要额外的时间去内存中获取。
- 节省空间:如果立即数足够小,那么可以减少对寄存器的需求,从而节省空间。
- 缺点:
- 数量有限:立即数的大小受到指令格式的限制,ARM 架构中立即数通常被限制在一定范围内。
- 表达能力受限:由于立即数大小的限制,有时候无法直接表示较大的数值。
立即数的使用
在 ARM 汇编语言中,立即数通常用于简单的数值操作,例如赋值或者与寄存器进行逻辑运算。立即数只能是某些特定的值,并且这些值通常被限制为可以由指令直接处理的形式。
如:MOV ,#0x12345678 @报错,不合法
0x1234 是一个有效的立即数,因为它可以通过位移得到。但是 0x12345678 则不是一个有效的立即数,因为它超过了 8 位的限制,并且不能通过简单的位移得到。 

注:使用mov 给寄存器里面存放值的时候,#号后面需是有效数(1:立即数,2:取反之后是立即数),如果不是立即数需要用ldr指令进行存放。

算术运算指令
常见的算术运算指令包括:
- add:加法
- adc:带进位的加法
- sub:减法
- sbc:带借位的减法
- mul:乘法
指令格式
算术运算指令的一般格式如下:
<opcode>{<code>}{s} Rd, Rn, operand2 其中:
<opcode>是指令名称。<code>是条件码,可选。{s}表示是否更新 CPSR 的标志位。Rd是目标寄存器。Rn是第一个操作寄存器。operand2是第二个操作数,可以是寄存器或立即数。
add 普通的加法指令

adc 带进位的加法指令
假设2个64位的数相加
- 第一个64位的数,R0存放低32位,R1存放高32位,
- 第二个64位的数,R2存放低32位,R3存放高32位
- 结果R4存放低32位,R5存放高32位
add和ADC的区别,例如是64位的字符,如果低位大小满足进1的话用ADD只会显示在C进1,但是存储的地址并不进1,ADC的话则会将存储的地址进1

注意:mul r2, r0, #0x4 @ 错误
乘法指令的第二个操作数只能是一个寄存器
mul r2, r1,r0

跳转指令
1》修改PC,不建议使用,因为需要查询指令的地址

2》 b bl :指令跳转
- 格式:b/bl Label
- Label: 指令
- 相当C语言的函数调用
- B指令(不带返回的跳转)
不保存返回地址的跳转(返回地址不保存到lr中)

- BL指令(带返回的跳转指令),将LR的值修改成跳转指令下一条指令的地址,再将PC的值修改成跳转标识符下指令的地址

补充了解:
RM指令条件码表:可跟的判断条件成立跳转(NZCV在用于判断两者之间关系使用比较多)

如:c代码如下:
练习:
实现以下逻辑unsigned int r1 = 9;unsigned int r2 = 15;while(1){if(r1 == r2)goto stop;if(r1 > r2)
r1 = r1 - r2;if(r1 < r2)
r2 = r2 - r1;}
stop:while(1);汇编指令练习答案如下:
mov r1,#9
mov r2,#15
loop:
cmp r1,r2 @cmp 比较指令
beq stop
subhi r1,r1,r2
subcc r2,r2,r1
b loop
stop:
b stop Load/Store指令
对内存的读写操作//如 a++ 读a的值,将运算结果从cpu写道内存
可用地址查找:(我们不用查找,脚本文件中配置了内存空间的分配)
查看内存中内容:

1>单寄存器操作指令 ldr/str
- 格式:ldr/str Rm, [Rn]
- Rm: 存储是数据
Rn:存储的数据,地址
将CPU中r1寄存器中的数据存储到内存中r0地址的空间中

- 将r0指向的地址空间中的内容,读到r2寄存器中
- ldr r2, [r0]

- 将r1中的值存储到r0+4指向的地址空间中,R0中的值不变
- str r1, [r0, #4];

- 将r2中的值存储到r0指向的地址空间中,r0 = r0 + 4
- str r2, [r0], #4

- 将R3中的值存储到R0+4指向的地址空间中,并且r0 = r0 + 4
- str r3, [r0, #4]!

- 2>多寄存器操作指令 stm ldm
- 将r1到r4中的值存储到r0指向地址空间中,连续16个字节的地址空间
- stm r0, {r1-r4}

- 将r0指向的地址空间中,连续的16个字节的数据,读到r5-r8寄存器中
- ldm r0, {r5-r8}

- 如果寄存器列表中的寄存器编号既有连续又有不连续,连续的使用“-”隔开,不连续的使用“,”
- stm r0, {r1-r3,r4}

- 2. 不管寄存器列表中的寄存器编号顺序如何变化,都是小地址对应小编号的寄存器高地址对应大编号的寄存器
- stm r0, {r4,r3,r2,r1}
- ldm r0, {r8,r7,r6,r5}

- 3>栈的操作指令 stmfd ldmfd
- 栈的种类
- 空栈(Empty)
栈指针指向的地址是空的,在栈中存储数据时,可以直接存储,存储完成之后需要将栈指针再次指向空的位置。 
- 满栈(Full)
栈指针指向的地址有数据,在栈中存储数据时,需要先将栈指针,指向一个空的位置,然后在存储数据。

- 增栈(Ascending)
栈指针向高地址方向移动
- 减栈(Descending)
栈指针向低地址方向移动
操作栈的方式有四种
- 满增栈 满减栈 空增栈 空减栈
- FA:Full Ascending 满增(FA)
- FD:Full Descending 满减(FD)
- EA:Empty Ascending 空增(EA)
- ED:空减
- ARM默认采用的是满减栈

- stmfd/ldmfd<code> sp!, {寄存器列表}
- stmfd sp!, {r1-r5}(写) (压栈)

更新栈指针指向的地址空间
- ldmfd sp!, {r6-r10}(读) (出栈)

特殊:
stmfd sp!, {r1-r5,lr}(写) (压栈)
ldmfd sp!, {r6-r10,pc}(读) (出栈) //r1-r5出栈给r6-r10, 将lr的值出栈给pc
状态寄存器指令
对CPSR进行读写操作//其他都不能动CPSR (SWI 指令是linux内核有,所以arm为了匹配才有的指令)(CPSR保存cpu的状态、模式、中断中断开关、运算状态,非常重要,不能任意更改,只有一类指令能操作这个寄存器)
1》读cpsr 指令mrs 
2》写cpsr 指令 msr :一般情况不能修改cpsr,只能用msr命令修改,user模式下不能切换到其他模式。


注:修改CPSR的控制域(bit[7:0]),修改CPSR时必须指定修改哪个区域
USER模式下不能修改CPSR的值,防止应用程序修改CPU状态,保护操作系统
CPSR_C修改的是CPSR的低八位ctrl(控制)域,一般都只修改C域
OK,就分享到这,如果帮到你那就点个关注吧~
相关文章:
ARM 汇编语言基础
目录 汇编指令代码框架 汇编指令语法格式 数据处理指令 数据搬移指令 mov 示例 立即数的本质 立即数的特点 立即数的使用 算术运算指令 指令格式 add 普通的加法指令 adc 带进位的加法指令 跳转指令 Load/Store指令 状态寄存器指令 基础概念 C 语言与汇编指令的关…...
c语言小知识点小计
c语言小知识点小计 1、运算符的优先级 运算符的优先级是和指针解引用*的优先级相同的,但在代码运行中执行顺序是从后往前的。因此下面代码 int a[10] {1,2,3,4}; int* arr a; printf("%d",*arr);//访问的值是2 //注意:printf("%d&qu…...
《C#面向语言版本编程》C# 13 中的新增功能
将C#语言版本升级为预览版 C# 13 包括一些新增功能。 可以使用最新的 Visual Studio 2022 版本或 .NET 9 预览版 SDK 尝试这些功能。若想在.NET项目中尝试使用C#的最新预览版特性,可以按照以下步骤来升级你的项目语言版本: .打开项目文件: 找…...
0成本通过Hugo和GitHub Pages搭建博客
版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/ 使用 Chocolatey 安装 Hugo Chocolatey 是一个 Windows 软件包管理器,使用 PowerShell 和 NuGet 作为基础。它可以自动化软件的安装、升级和卸载过…...
Ollama 可以玩 GLM4和CodeGeeX4了
最近这一两周看到不少互联网公司都已经开始秋招提前批了。 不同以往的是,当前职场环境已不再是那个双向奔赴时代了。求职者在变多,HC 在变少,岗位要求还更高了。 最近,我们又陆续整理了很多大厂的面试题,帮助一些球友…...
浅析C++指针与引用的关系
前言: 在实践中指针与引用相辅相成,功能相互叠加,但各有各的特点,互相不可替代!!!...
Python面试宝典第31题:字符串反转
题目 编写一个函数,其作用是将输入的字符串反转过来,输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组,并使用O(1)的额外空间解决这一问题。备注:s[i]都是ASCII码表中的可打印…...
【深入理解SpringCloud微服务】深入理解微服务中的远程调用,并手写一个微服务RPC框架
【深入理解SpringCloud微服务】深入理解微服务中的远程调用,并手写一个微服务RPC框架 远程过程调用微服务中的RPC框架如何实现一个微服务中的RPC框架接口扫描生成代理对象代理对象处理逻辑 手写一个微服务RPC框架RPCClientEnableRPCClientMicroServiceRPCClientRegi…...
数据结构----二叉树
小编会一直更新数据结构相关方面的知识,使用的语言是Java,但是其中的逻辑和思路并不影响,如果感兴趣可以关注合集。 希望大家看完之后可以自己去手敲实现一遍,同时在最后我也列出一些基本和经典的题目,可以尝试做一下。…...
通过python管理mysql
打开防火墙端口: 使用 firewall-cmd 命令在防火墙的 public 区域中永久添加 TCP 端口 7500(FRP 控制台面板端口)、7000(FRP 服务端端口)以及端口范围 6000-6100(一组客户端端口)。这些端口是 FR…...
Run the OnlyOffice Java Spring demo project in local
Content 1.Download the sample project in java2.Run the project3.Test the example document 1.Download the sample project in java Link: download the sample code in official website document properties setting spring 项目所在的服务器 server. Address192.168…...
11. Rancher2.X部署多案例镜像
**部署springboot项目 : ** **部署中间件Mysql8.0 : ** 名称:service-mysql 端口 :3306:3306 镜像:mysql:8.0 环境变量: MYSQL_ROOT_PASSWORDxdclass.net168路径映射 /home/data/mysql/data /var/lib/mysql:rw /etc/localtime…...
探索Linux世界之Linux环境开发工具的使用
目录 一、yum -- Linux软件包管理器 1、什么是yum 2、yum的使用 2.1 yum一些经常见的操作 1.查看软件包 2. 安装软件包 3. 删除软件包 3、yum的周边知识 3.1 yum的软件包都是从哪里来的?是从哪里能下载到这些软件包? 3.2 yum的拓展软件源 二、…...
探索Spring Boot微服务架构的最佳实践
目录 引言 一、Spring Boot简介 二、微服务架构的关键要素 三、Spring Boot在微服务中的最佳实践 3.1 清晰的服务边界 3.2 自动化配置与依赖管理 3.3 服务注册与发现 3.4 配置管理 3.5 安全与认证 3.6 监控与日志 3.7 分布式事务 四、总结 引言 在当今快速迭代的软…...
[论文泛读]zkLLM: Zero Knowledge Proofs for Large Language models
文章目录 介绍实验数据实验数据1实验数据2实验数据3 介绍 这篇文章发在CCS2024,CCS是密码学领域的顶会。作者是来自加拿大的University of Waterloo。文章对大语言模型像GPT和LLM等大语言模型实现了零知识可验证执行,但不涉及零知识可验证训练。个人觉得…...
vscode插件中的图标怎么设置
首先在ts文件目录下和package.json同级的目录下加入一张图片,后缀是jpg、png、jpeg都可以。 然后package.json中加入该行 重新 vsce package即可 如果出现报错 The specified icon xxx/xxx/icon.jpg wasnt found in the extension. 那就是没有放正确文件夹的位…...
Study--Oracle-08-oracle数据库的闪回技术
一、闪回恢复区(Flash Recovery Area) 1、什么是闪回恢复区 闪回恢复区是Oracle数据库中的一个特殊存储区域,用于集中存放备份和恢复数据库所需的所有文件,包括归档日志和闪回日志。这个区域可以帮助数据库在遇到介质故障时进行完全恢复。通过将备份数…...
获取客户端真实IP
出于安全考虑,近期在处理一个记录用户真实IP的需求。本来以为很简单,后来发现没有本来以为的简单。这里主要备忘下,如果服务器处于端口回流(hairpin NAT),keepalived,nginx之后,如何取得客户端的…...
韩式告白土味情话-柯桥生活韩语学习零基础入门教学
你们韩国人别太会告白了! 1、너 얼굴에 뭐가 조금 묻었어! 你的脸上有点5376东西! 뭐가 조금 묻었1585757는데? 有点什么? 이쁨이 조금 묻었네. 有点漂亮。 2、돌잡이 때 뭐 잡았어요? 你抓周的时候抓了什么? 쌀 잡았…...
Linux安全与高级应用(一)深入探讨Linux安全与高级应用
文章目录 深入探讨Linux安全与高级应用引言目录一、Linux安全与应用概述1.1 Linux的应用现状1.2 Linux的安全需求 二、构建LAMP企业网站平台2.1 LAMP平台简介2.2 安装和配置Apache服务器2.2.1 安装Apache2.2.2 配置Apache 2.3 安装和管理MySQL数据库2.3.1 安装MySQL2.3.2 配置M…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀” 在JavaScript中,我们经常需要处理文本、数组、对象等数据类型。但当我们需要处理文件上传、图像处理、网络通信等场景时,单纯依赖字符串或数组就显得力不从心了。这时ÿ…...
