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.rhkb.cn/news/501879.html

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

相关文章

米哈游可切换角色背景动态壁纸

米哈游可切换角色背景动态壁纸 0. 视频 B站演示: 米哈游可切换角色背景动态壁纸-wallpaper 1. 基本信息 作者: 啊是特嗷桃系列: 复刻系列 (衍生 wallpaper壁纸引擎 用)网站: 网页版在线预览 (没有搞大小适配, 建议横屏看; 这个不能切角色, 只能在wallpaper中切)仓库: GitHub…

Mac iTerm2集成DeepSeek AI

1. 去deepseek官网申请api key,DeepSeek 2. 安装iTerm2 AI Plugin插件,https://iterm2.com/ai-plugin.html,插件解压后直接放到和iTerms相同的位置,默认就在/Applications 下 3. 配置iTerm2 4. 重启iTerm2,使用快捷键呼出AI对话…

HTML——66.单选框

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>单选框</title></head><body><!--input元素的type属性&#xff1a;(必须要有)--> <!--单选框:&#xff08;如所住省会&#xff0c;性别选择&…

深入Android架构(从线程到AIDL)_10 主线程(UI 线程)的角色

目录 4、 细说主线程(UI线程)的角色 近程通信 远程通信 4、 细说主线程(UI线程)的角色 近程通信 在Android里&#xff0c;无论组件在那一个进程里执行&#xff0c;于预设情形下&#xff0c;他们都是由该进程里的主线程来负责执行之。例如下述的范例&#xff0c;由一个Acti…

掌握RabbitMQ:全面知识点汇总与实践指南

前言 RabbitMQ 是基于 AMQP 高级消息队列协议的消息队列技术。 特点&#xff1a;它通过发布/订阅模型&#xff0c;实现了服务间的高度解耦。因为消费者不需要确保提供者的存在。 作用&#xff1a;服务间异步通信&#xff1b;顺序消费&#xff1b;定时任务&#xff1b;请求削…

渗透测试-非寻常漏洞案例

声明 本文章所分享内容仅用于网络安全技术讨论&#xff0c;切勿用于违法途径&#xff0c;所有渗透都需获取授权&#xff0c;违者后果自行承担&#xff0c;与本号及作者无关&#xff0c;请谨记守法. 此文章不允许未经授权转发至除先知社区以外的其它平台&#xff01;&#xff0…

前端-计算机网络篇

一.网络分类 1.按照网络的作用范围进行分类 &#xff08;1&#xff09;广域网WAN(Wide Area Network) 广域网的作用范围通常为几十到几千公里,因而有时也称为远程网&#xff08;long haul network&#xff09;。广域网是互联网的核心部分&#xff0c;其任务是长距离运送主机…

开发培训-慧集通(iPaaS)集成平台脚本开发Groovy基础培训视频

‌Groovy‌是一种基于Java虚拟机&#xff08;JVM&#xff09;的敏捷开发语言&#xff0c;结合了Python、Ruby和Smalltalk的许多强大特性。它旨在提高开发者的生产力&#xff0c;通过简洁、熟悉且易于学习的语法&#xff0c;Groovy能够与Java代码无缝集成&#xff0c;并提供强大…

腾讯云智能结构化 OCR:驱动多行业数字化转型的核心引擎

在当今数字化时代的汹涌浪潮中&#xff0c;数据已跃升为企业发展的关键要素&#xff0c;其高效、精准的处理成为企业在激烈市场竞争中脱颖而出的核心竞争力。腾讯云智能结构化 OCR 技术凭借其前沿的科技架构与卓越的功能特性&#xff0c;宛如一颗璀璨的明星&#xff0c;在交通、…

vulnhub Earth靶机

搭建靶机直接拖进来就行 1.扫描靶机IP arp-scan -l 2.信息收集 nmap -sS -A -T4 192.168.47.132 得到两个DNS; 在443端口处会让我们加https dirb https://earth.local/ dirb https://terratest.earth.local/ #页面下有三行数值 37090b59030f11060b0a1b4e0000000000004312170a…

消息中间件类型都有哪些

在消息中间件的专业术语中&#xff0c;我们可以根据其特性和使用场景将其划分为几种主要的类型。这些类型不仅反映了它们各自的技术特点&#xff0c;还决定了它们在不同应用场景下的适用性。 1. 点对点&#xff08;Point-to-Point&#xff09;消息中间件&#xff1a; • 这类中…

服务器迁移中心——“工作组迁移”使用指南

简介 服务器迁移中心&#xff08;Server Migration Center&#xff0c;简称SMC&#xff09;是阿里云提供给您的迁移平台。专注于提供能力普惠、体验一致、效率至上的迁移服务&#xff0c;满足您在阿里云的迁移需求。 工作组迁移是SMC的一项功能&#xff0c;提供标准化迁移流程…

C#调用Lua

目录 xLua导入 打包工具导入 单例基类导入与AB包管理器导入 Lua解析器 文件加载与重定向 Lua解析器管理器 全局变量获取 全局函数获取 对于无参数无返回值 对于有参数有返回值 对于多返回值 对于变长参数 完整代码 List与Dictionary映射Table 类映射Table 接口映射…

Wend看源码-Java-fork/Join并行执行任务框架学习

摘要 本文主要介绍了Java的Fork/Join并行任务执行框架&#xff0c;详细阐述了其工作原理和核心构件&#xff0c;全面解读了Fork/Join框架的运作机制&#xff0c;旨在为学习这一框架的开发者提供一份详实且实用的参考资料。 Java的Fork/Join框架是Java 7引入的一个用于并行执行任…

C++ 中 Unicode 字符串的宽度

首先&#xff0c;什么是 Unicode&#xff1f; Unicode 实际上是一个统一的文字编码标准&#xff0c;它出现目的是为了解决不同计算机之间字符编码不同而导致的灾难性不兼容问题。 Unicode 字符集与 Unicode 编码是两种不同的概念。Unicode 字符集实际是对进入标准的所有文字用…

Python爬虫 - 豆瓣图书数据爬取、处理与存储

文章目录 前言一、使用版本二、需求分析1. 分析要爬取的内容1.1 分析要爬取的单个图书信息1.2 爬取步骤1.2.1 爬取豆瓣图书标签分类页面1.2.2 爬取分类页面1.2.3 爬取单个图书页面 1.3 内容所在的标签定位 2. 数据用途2.1 基础分析2.2 高级分析 3. 应对反爬机制的策略3.1 使用 …

MIPI_DPU 综合(DPU+MIPI+Demosaic+VDMA 通路)

目录 1. 简介 2. 创建 Platform 2.1 Block Design 2.1.1 DPU PFM Lite 2.1.2 DPU prj 2.1.3 DPU MIPI Platform 2.2 pin 约束 2.2.1 GPIO 约束 2.2.2 IIC 约束 2.1.3 DPHY 约束 3. 报错总结 3.1 AXI_M 必须顺序引用 3.2 DPU 地址分配错误 4. Design Example 4.…

Spring系列一:spring的安装与使用

文章目录 ?? 官方资料 ??Spring5下载??文档介绍 ??Spring5 ??内容介绍??重要概念 ??快速入门 ??Spring操作演示??类加载路径??Spring容器结构剖析??Debug配置 ??实现简单基于XML配置程序 ??Spring原生容器结构梳理??作业布置??Spring课堂练习 …

AutoSar架构学习笔记

1.AUTOSAR&#xff08;Automotive Open System Architecture&#xff0c;汽车开放系统架构&#xff09;是一个针对汽车行业的软件架构标准&#xff0c;旨在提升汽车电子系统的模块化、可扩展性、可重用性和互操作性。AUTOSAR的目标是为汽车电子控制单元&#xff08;ECU&#xf…

Kernel Stack栈溢出攻击及保护绕过

前言 本文介绍Linux内核的栈溢出攻击&#xff0c;和内核一些保护的绕过手法&#xff0c;通过一道内核题及其变体从浅入深一步步走进kernel世界。 QWB_2018_core 题目分析 start.sh qemu-system-x86_64 \-m 128M \-kernel ./bzImage \-initrd ./core.cpio \-append "…