ARM架构

目录

哈佛结构

arm指令格式

 有符号数的溢出(8bit)​

无符号数的进位/借位

CPSR(当前程序状态寄存器)

ARM模式

arm异常类型

 ARMv7架构异常向量表

 arm异常的处理流程

arm寄存器

堆栈指针寄存器

arm模式切换流程

LDR指令、STR指令

指令流水线(三级流水线+冯诺依曼体系)

三级流水线

带有访问存储器指令流水线(LDR/STR)

分支流水线

B/BL

arm立即数编码规则

arm条件码表

arm移位操作

逻辑移位vs算术移位

逻辑移位的本质----无论左移还是右移,空出的位均补零,不保留符号信息

LDM/STM指令

 LDM指令:

软中断指令

软中断的本质

        arm Linux系统调用实现

 STM指令

arm寻址方式

多寄存器寻址

堆栈寻址

 标签label

全局标签

 定义全局函数

 定义全局变量

 使用场景

局部标签

引用方式

引用规则

使用场景

弱标签

 弱标签的覆盖原则

使用场景

静态标签

静态标签的定义

 使用场景

伪指令

NOP伪指令

ADR伪指令

ADRL伪指令

LDR伪指令

LDR伪指令的两种形式

arm伪操作

汇编调用c程序

 c调用汇编程序

内联汇编

饱和算术运算:

协处理器

内联汇编的基本语法


 

哈佛结构

核心特征是将指令存储数据存储完全分离,各自使用独立的存储器和总线

arm指令格式

arm指令集采用固定长度32位的指令格式

 有符号数的溢出(8bit)

无符号数的进位/借位

CPSR(当前程序状态寄存器)

ARM模式

  • 用户模式,用户程序的工作模式,用户模式没有权限去操作其它硬件资源,只能执行处理自己的 数据;

  • 系统模式,首先用户模式与系统模式共用同一套寄存器,系统模式为特权模式,系统模式可以直接访问硬件资源

  • svc模式,主要用于完成系统初始化的工作,cpu上电之后默认的工作模式,当调用swi/svc,cpu处于svc模式;

  • 中止模式,当用户访问非法内存地址或者访问某一块不具有读写权限的内存地址时处于此工作模式;

  • Fiq模式 (快速中断模式),用来处 理对时间要求比较紧急的中断请求,主要用于高速数据传输及通道处理中;

  • IRQ模式(普通中断模式),用于处理一般的中断请求,通常在硬件产生中断信号之后自动进入IRQ模式;

arm异常类型

 ARMv7架构异常向量表

 arm异常的处理流程

arm寄存器

arm处理器在任何工作模式下共用一个PC寄存器(程序计数寄存器)与CPSR寄存器(当前程序状态寄存器)。

堆栈指针寄存器

 栈按照栈的生长方向(递增、递减)与数据的存储方式(满栈、空栈)分为四种类型

1. 满递增栈 2. 满递减栈 3. 空递增栈 4. 空递减栈

栈顶指针(sp): 始终指向当前栈的栈顶,即最后一个入栈元素的地址(满栈)或者 下一个可用空间的地址(空栈)

递增栈:栈顶向高地址方向增长

递减栈:栈顶向低地址方向增长

push操作时处理器先减小SP值然后将指定寄存器存储到SP寄存器指向的存储器地址

 POP操作时处理器先将SP指向的存储器地址存储到指定寄存器中,然后将SP寄存器值增加

arm模式切换流程

在ARM中,当发生异常时,处理器会自动切换到对应的异常模式,每种异常模式都有自己独立的物理寄存器,R13(SP:堆栈寄存器)、R14(LR:链接寄存器)SPSR(备份程序状态寄存器)。

当从用户模式进入IRQ模式时,保存需要保护的寄存器到IRQ模式的堆栈,步骤如下:

  1. 用户程序在用户模式下运行,使用SP_usr;
  2. 发生中断,处理器自动切换到IRQ模式,此时SP自动变为SP_irq。
  3. 保存返回地址到LR_irqLR_irq = 当前PC + 4)。

  4. 保存当前CPSR到SPSR_irq

  5. 中断处理程序开始执行,使用SP_irq指向的堆栈保存寄存器(如R0-R12, LR_irq)
  6. 处理完中断后,从SP_irq的堆栈中恢复寄存器。
  7. 返回到用户模式,继续使用SP_usr。
IRQ_Handler:; 1. 保存用户模式的寄存器(R0-R12, LR_irq保存的是返回地址)STMFD SP!, {R0-R12, LR}   ; 使用SP_irq压栈(SP_irq -= 56字节); 2. 处理中断(如读取定时器状态)BL Handle_Timer_Interrupt; 3. 恢复寄存器并返回用户模式LDMFD SP!, {R0-R12, LR}   ; 从SP_irq弹栈(SP_irq += 56字节)SUBS PC, LR, #4           ; 返回到用户模式的下一条指令(恢复CPSR)

 

LDR指令、STR指令

LDR指令(Load Register)是用于从内存中加载数据到寄存器的核心指令

 STR指令(Store Register)用于将寄存器中的值存储到内存中

指令流水线(三级流水线+冯诺依曼体系)

冯诺依曼体系:数据总线只有一根,取指令与取数据采用同一根数据线

三级流水线

带有访问存储器指令流水线(LDR/STR)

LDR指令

      step1:访问内存——取数据——数据总线被占用——AND指令被延时(stall)

      step2:数据写回寄存器——写数据——数据总线被占用——其他指令被延时

分支流水线

BL(Branch with Link)指令核心功能是跳转到目标地址执行子程序,同时将返回地址下一条指令地址保存到链接寄存器LR;

B(Branch)指令的核心功能是改变程序执行流程,常用于循环控制(for/while)、条件分支(if-else) 和代码块跳转

B/BL

BL <label> #label中存储的是目标地址

跳转地址计算流程:

 eg:

arm立即数编码规则

ARM立即数采用 "8 位数值 + 4 位循环右移(Rotate Right)"的组合编码:

arm条件码表

假设有符号数AB,比较A ≥ B等价于判断A - B ≥ 0

S = A - B,则

  • S ≥ 0,则S的符号位为 0(N=0)。
  • 若计算过程未溢出(V=0),则N=0直接表示S ≥ 0
  • 若计算过程溢出(V=1),则N=1才表示S ≥ 0(溢出导致符号位反转)。

A ≥ B的充要条件是:N 与 V 状态一致(N⊻V=0)

arm移位操作

逻辑移位vs算术移位

逻辑移位的本质----无论左移还是右移,空出的位均补零,不保留符号信息

算术移位的本质----右移时保留符号位(高位填充原符号位),左移与逻辑左移一致

LDM/STM指令

 LDM指令:

软中断指令

软中断的本质

  • 主动触发:与硬件中断(由外部设备触发,如键盘、时钟)不同,软中断是程序通过显式执行指令主动发起的。

  • 特权级切换:在保护模式下,软中断通常用于从用户态(低特权级)切换到内核态(高特权级),以便执行受保护的操作(如访问硬件、管理内存)。

        arm Linux系统调用实现

系统调用号操作系统内核为每个系统调用分配的唯一编号!

 STM指令

arm寻址方式

指令如何表达 “去哪里找数据” 或 “把结果存到哪里”?这需要一套规则 —— 即寻址模式

寻址是确定指令中操作数位置的过程。操作数可以存储在:

1. 寄存器(如 R0~R15)

2. 内存(如变量、数组)

3. 立即数(指令中直接给出的常数)


多寄存器寻址

 

堆栈寻址

push/pop

 标签label

标签是一个符号化的地址标记,指向代码或数据在内存中的位置;

在 ARM Linux 汇编开发中,标签(Label)的分类主要基于其 作用域(可见性范围)、链接属性(符号在链接阶段的行为)以及 符号强弱性(是否允许被覆盖)可以分为 全局标签局部标签静态标签弱标签

全局标签

使用 .global 伪指令声明标签为全局,允许其他文件引用

.global 标签名       @ 声明为全局标签
标签名:              @ 标签定义汇编指令
 定义全局函数
@定义一个全局函数 add_two
.global add_two     @ 声明为全局
add_two:ADD R0, R0, R1  @ R0 = R0 + R1BX  LR          @ 返回
 定义全局变量
.data
.global g_counter   @ 声明全局变量
g_counter:.word 0x0       @ 初始值为0
 使用场景

局部标签

在 ARM 汇编中局部标签是仅在 当前代码块或作用域内有效 的临时符号,用于简化循环、条件分支等控制逻辑,避免命名冲突。局部标签通过 数字 + 冒号 定义,并通过 b(backward)和 f(forward) 引用;

  • 定义格式:以数字开头,后跟冒号(如 1:2:);

  • 作用域:仅在当前代码块(如函数或循环体)内有效;

引用方式
  • 1b:向后跳转(Backward),指向 最近的前一个 1: 标签。

  • 1f:向前跳转(Forward),指向 最近的后一个 1: 标签

引用规则
  • 就近原则:根据 b/f 方向,寻找最近的同名标签。

  • 可重复使用:同一代码块内可多次定义同名局部标签(如 1:)。

使用场景
.text
.global _start_start:MOV R0, #5        @ 初始化 R0 = 5loop_start:           @ 全局标签(可选)
1:                    @ 局部标签1(循环入口)SUBS R0, R0, #1   @ R0 = R0 - 1,更新标志位BEQ 1f            @ 若 R0 == 0,向前跳转到局部标签1(循环出口)B   1b            @ 否则,向后跳转到局部标签1(继续循环)1:                    @ 局部标签1(循环出口)MOV R7, #1        @ 退出系统调用号SVC #0            @ 触发系统调用

弱标签

在 ARM 汇编中,弱标签(Weak Label) 是一种允许 同名符号覆盖 的标签类型。它常用于定义 默认实现可选功能,当链接器发现同名的 强标签(Strong Label) 时,会优先使用强标签的定义,弱标签的定义则被忽略。

.weak 标签名       @ 声明为弱标签
标签名:            @ 标签定义汇编指令
 弱标签的覆盖原则
  • 强标签优先:若存在同名的强标签(通过 .global 声明),链接时使用强标签的定义。

  • 无强标签时生效:若未定义强标签,链接器使用弱标签的实现。

  • 允许多个弱标签若多个弱标签同名,链接器随机选择其一(通常报警告)。

使用场景

静态标签

静态标签是仅在 当前汇编文件内有效 的符号,不可被其他文件引用。它的核心作用是 封装内部实现,避免命名冲突,提升代码模块化;

静态标签的定义

 使用场景

在文件 utils.s 中定义静态函数 internal_add,仅在文件内部调用;在 main.s 中尝试调用该函数将失败。

伪指令

NOP伪指令

NOP(No Operation)伪指令 核心功能 1. 实现延时 2. 对齐指令地址

ADR伪指令

ADR伪指令 可以获取程序的运行地址,而不是链接地址

ADRL伪指令

注意: 标签地址必须与ADRL指令位于同一代码段内

LDR伪指令

LDR伪指令(Pseudo-Instruction)主要功能如下:

  • 加载32位立即数到寄存器;
  • 加载标签地址到寄存器;
LDR伪指令的两种形式

 注意:#offset是当前指令地址(PC)到 文字池中目标数据地址 的偏移量

arm伪操作

汇编调用c程序

汇编调用c程序流程
@1 		c文件中实现c语言函数
@2 		.extern伪操作声明c函数 .extern my_add
@3.1 	根据ATPCS标准,R0,R1,R2,R3用于传递参数,由于c语言函数的参数可能超过4个
@3.2  	采用伪指令ldr初始化栈空间
@4    	传递参数 mov r0,#0x01
@5    	调用函数 BL/B my_add
 @start.s文件.text.global _start @将_start声明为全局的.extern my_add_start:@先初始化要使用的栈空间ldr sp, =0x400mov r0, #10mov r1, #20mov r2, #30mov r3, #40mov r5, #50push {r5}bl my_addloop:b loop.data.align 4 @按2^4字节对齐
.space 4096.end
 //add.c文件int my_add(int x, int y, int z, int m, int n) {return x + y + z + m + n;}

 c调用汇编程序

1. 定义汇编函数my_add, 注意传递的参数、返回值满足ATCPS规则
2. 汇编文件中通过.global 把my_add声明为全局函数
3. C语言中通过extern声明外部函数my_add
@start.s文件
.text
.global _start
.extern main
_start:ldr sp,=0x400bl main 
.data.align 4.space 4096
loop:b loop
.end
//main.c文件
extern int my_add(int x,int y,int z);
int main()
{int ret=my_add(10,20,30);return ret;
}
@ add.s文件
.arm
.text
.global my_add
my_add:add r5,r0,r1add r5,r5,r2mov r0,r5 @函数的返回值通过R0传递
.end

内联汇编

内联汇编允许在高级语言(如C/C++)中直接嵌入汇编代码,内联汇编的应用场景:

  • 程序中使用饱和算术运算(Saturating Arithmetic)
  • 程序需要操作协处理器;
  • C程序中需要操作程序状态寄存器;
饱和算术运算:

饱和算术运算是一种在数值运算中防止溢出的处理方式。当运算结果超出数据类型的表示范围时,结果会被“饱和”到该数据类型能表示的最大值或最小值;

协处理器

ARM架构通过支持协处理器来扩展处理器的功能。ARM架构的处理器支持最多16个协处理器,通常称为CP0~CP15;

CP15,提供系统控制功能,主要用于配置MMU、TLB和Cache、异常向量表的地址设置;

内联汇编的基本语法
//__asm__告知编译器不用检查后面的内容,只需要交给汇编器进行处理
__asm__ volatile ("asm code" : 输出操作数列表 : 输入操作数列表 : 破坏列表(Clobber List)
);

1. volatile 关键字禁止编译器优化内联汇编代码;

2. "asm code"主要用于填写汇编代码,用\n\t分隔多行汇编指令;

__asm__ volatile ("add r0, r1, r2\n\t""add r0, r0, r3\n\t""mov r0, r0": /* 输出操作数列表 */: /* 输入操作数列表 */: /* 破坏列表 */
);

3. 输出操作数列表(asm->c/c++)用于指定汇编代码执行后需要传递回 C/C++ 变量的结果,通常只能为变量;

__asm__ volatile ("mov r0, #0xFF":=r(value)       // 将r0的值写入value:                // 输入操作数列表:                // 破坏列表
);

每个输出操作数的格式为 "约束"(变量),多个操作数用逗号分隔,其中约束由两部分构成,一部分方向修饰符(+,=,&),方向修饰符用于指定该操作数是输入还是输出,输出操作数必须包含 =(表示操作数仅用于输出等价于只写)或  +(表示操作数既是输入又是输出等价于可读可写)& 必须通过 +& 或者 =& 进行使用,另一部分为约束符(r,m),约束符用于指定操作数的存放位置,其中 r 约束(寄存器约束)要求操作数存储在通用寄存器中,m 约束(内存约束)要求操作数直接存储在内存地址中,避免通过寄存器中转;

=r : 输出到通用寄存器,操作数仅用于写入

__asm__ volatile ("mov r0, #42" : "=r" (result)
);

结果写入寄存器 r0,再传递给 result

4. 输入操作数列表(c/c++ -> asm)用于c/c++程序向汇编代码传递数据,输入操作数的值在汇编代码中不应被修改只能读取,因此输入操作数无需方向修饰符,常用约束符 r(变量值存入通用寄存器)m(变量直接通过内存地址访问)i(立即数(整数常量)),此外用于定义输入的参数,可以是变量也可以是立即数;

int a = 10, b = 20;
__asm__ volatile ("add r0, %1, %2\n\t"   // %0, %1, ..., %n表示占位符,先按照输出操作数的顺序进行引用//再按照输入操作数的顺序进行引用"mov %0, r0"           // result = r0: "=r" (result)        // 输出操作数: result -> %0: "r" (a), "r" (b)     // 输入操作数:a -> %1, b-> %2: "r0"                 // 破环列表用于告知编译器哪些寄存器或资源被隐式修改
);

5. 破坏列表告知编译器哪些寄存器或资源被隐式修改,常见值如下:

  • "cc":条件码寄存器(CPSR);

  • "memory":表示内存被修改(强制刷新内存缓存);

  • "r0", "r1":指定被破坏的寄存器;

__asm__ volatile ("mov r0, %1\n\t""str r0, [%0]": : "r" (addr), "r" (value): "r0", "memory"  // 声明破坏 r0 和 memory
);

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

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

相关文章

canvas(三)-动画3d

在 <canvas> 中实现 3D 动画通常需要借助 WebGL 技术,因为原生的 2D 上下文(CanvasRenderingContext2D)无法直接支持 3D 渲染。WebGL 是基于 OpenGL ES 2.0 的 JavaScript API,可以直接在浏览器中实现高性能的 3D 图形渲染。以下是关于 <canvas> 3D 动画的概念…

右键打开 pycharm 右键 pycharm

文件夹右键打开pycharm aaa.reg notepad 右下角把文件格式改为&#xff1a;ansi Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Directory\Background\shell\PyCharm] "Open with PyCharm" "Icon""\"D:\\soft\\PyCharm 2024.1.4\\bi…

一张纸决定的高度

从我捧起《格局》这个本书开始&#xff0c;转眼间两个月过去了。 回头望一望&#xff0c;好似还在昨天。 这两个月&#xff0c;心态在变&#xff0c;前进的方向在变&#xff0c;但唯一不变的就是每天晚上睡前&#xff0c;留给自己十分钟的读书时光。 我也从来没想过&#xf…

R 语言科研绘图 --- 热力图-汇总

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…

新手到资深的Java开发编码规范

新手到资深的开发编码规范 一、前言二、命名规范&#xff1a;代码的 “第一印象”2.1 标识符命名原则2.2 命名的 “自描述性” 原则2.3 避免魔法值 三、代码格式规范&#xff1a;结构清晰的视觉美学3.1 缩进与空格3.2 代码块规范3.3 换行与断行 四、注释规范&#xff1a;代码的…

鸿蒙仓颉开发语言实战教程:实现商城应用详情页

昨天有朋友提到鸿蒙既然有了ArkTs开发语言&#xff0c;为什么还需要仓颉开发语言。其实这个不难理解&#xff0c;安卓有Java和Kotlin&#xff0c;iOS先后推出了Objective-C和Swift&#xff0c;鸿蒙有两种开发语言也就不奇怪了。而且仓颉是比ArkTs更加灵活的语言&#xff0c;虽然…

CNN手写数字识别/全套源码+注释可直接运行

数据集选择&#xff1a; MNIST数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST)。训练集&#xff08;training set&#xff09;由来自250个不同人手写的数字构成&#xff0c;其中50%是高中学生&#xff0c;50%来自人口普查局&…

探秘谷歌Gemini:开启人工智能新纪元

一、引言 在人工智能的浩瀚星空中&#xff0c;每一次重大模型的发布都宛如一颗璀璨新星闪耀登场&#xff0c;而谷歌 Gemini 的亮相&#xff0c;无疑是其中最为耀眼的时刻之一。它的出现&#xff0c;犹如在 AI 领域投下了一颗重磅炸弹&#xff0c;引发了全球范围内的广泛关注与热…

小白场成长之路-计算机网络(三)

文章目录 一、网络参数配置1.图形化配置2.命令行配置2.1、ifconfig命令2.2ifup和ifdown子接口配置 2.3 多ip地址配置2.4子接口配置 总结 一、网络参数配置 1.图形化配置 NetworkManager&#xff0c;Linux7系统中&#xff0c;一般建议停止该管理方式&#xff1b;Linux8以上操作…

WireShark网络抓包—详细教程

本文仅用于技术研究&#xff0c;禁止用于非法用途。 Wireshark入门指南&#xff1a;从零开始掌握网络抓包分析 一、Wireshark是什么&#xff1f; Wireshark 是全球最受欢迎的开源网络协议分析工具&#xff0c;被广泛应用于网络故障排查、协议学习、网络安全分析等领域。它支…

区块链DApp的开发技术方案

区块链DApp开发技术方案&#xff1a;架构设计与实践指南 引言&#xff1a;DApp的技术革新与生态价值 区块链技术的去中心化特性与智能合约的自动化执行能力&#xff0c;推动DApp&#xff08;去中心化应用&#xff09;成为Web3.0的核心载体。截至2025年&#xff0c;全球DApp用…

Linux(3)——基础开发工具

目录 一、软件包管理器——yum 1.Linux下安装程序的方式 2.什么是yum 3.查找软件包 4.安装软件 5.本地与服务器端进行文件互传 6.卸载软件 二、Linux的编辑器——vim 1.基本概念 2.vim下各个模式之间的切换 3.vim在命令行模式下的命令汇总 4.vim在底行模式下的命令…

大数据学习(121)-sql重点问题

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

【QT】QString和QStringList去掉空格的方法总结

目录 一、QString去掉空格 1. 移除字符串首尾的空格&#xff08;trimmed&#xff09; 2. 移除字符串中的所有空格&#xff08;remove&#xff09; 3. 仅移除左侧&#xff08;开头&#xff09;或右侧&#xff08;结尾&#xff09;空格 4. 替换多个连续空格为单个空格 5. 移…

电脑 IP 地址修改工具,轻松实现异地登陆

在互联网时代&#xff0c;异地登陆需求日益频繁 —— 访问区域限制内容、跨区协作、优化游戏体验等场景&#xff0c;都需要通过修改 IP 地址实现。 一、IP 地址基础认知 IP 地址是设备的网络身份标识&#xff0c;不同地区分配不同 IP 段。通过修改 IP&#xff0c;可模拟目标地…

[BUG]Debian/Linux操作系统中 安装 curl等软件显示无候选安装(E: 软件包 curl 没有可安装候选)

本文内容组织形式 问题描述失效原因解决方案首先修改源列表为国内确认当前系统的版本Debian 11 (Bullseye)Debian 12 (Bookworm) 执行系统升级更新系统重新安装curl 结语 问题描述 日期&#xff1a;20250526 操作系统&#xff1a; debian darkchunkdebian:/home$ sudo apt i…

leetcode hot100刷题日记——12.反转链表

解答&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(n…

JavaSE核心知识点04工具04-01(JDK21)

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 JavaSE核心知识点04工具04-01&#xff08;JD…

数据库入门:以商品订单系统为例

数据库入门&#xff1a;以商品订单系统为例 一、前言 数据库是现代软件开发中不可或缺的基础&#xff0c;掌握数据库的基本概念和操作&#xff0c;是每个开发者的必经之路。本文将以“商品-品牌-客户-订单-订单项”为例&#xff0c;带你快速入门数据库的核心知识和基本操作。…

UE失落方舟特效学习 笔记01

通过法线扭曲贴图 Begin Object Class/Script/UnrealEd.MaterialGraphNode Name"MaterialGraphNode_0" ExportPath"/Script/UnrealEd.MaterialGraphNode/Engine/Transient.M_RadialUV_01:MaterialGraph_0.MaterialGraphNode_0"Begin Object Class/Script/E…