ARM编程——ARM架构及汇编

简介: ARM编程——ARM架构及汇编

文章目录

ARM体系结构与编程

ARM7(ARMV4)和ARM9之后的指令操作流程

ARM7(ARMV4)三级指令流水线

三级流水线

**PC**

ARM7三级流水线特例——ldr指令

ARM7三级流水线特例——bl指令

ARM7三级流水线特例——中断

ARM9(ARMV4)以后的ARM核的五级指令流水线

ARM编程模型

ARM核的七种工作模式

ARM核的两种工作状态

ARM核的37个寄存器

ARM支持的数据类型

ARM支持大端和小端模式,默认小端模式

ARM汇编语法格式:

ARM异常

ARM一旦触发异常会如何处理

ARM核跳转的方式

ARM指令——分支跳转指令


ARM体系结构与编程

当前ARM核的版本划分,


  • ARMV4:这其中包含的小版本有:
  • ARM720T
  • ARM920T
  • ARMV5:
  • Xscale
  • ARM10
  • ARMV6:
  • ARM11
  • ARMV7:
  • ARM-CORTEX-A8
  • ARM-CORTEX-A9
  • ARM-CORTEX-A15
  • ARM-CORTEX-M3/M0 STM32(M3)主打控制处理
  • ARMV8:(正式支持64位)
  • ARM-CORTEX-A53
  • ARM-CORTEX-A57

ARM7(ARMV4)和ARM9之后的指令操作流程

ARM7使用的是三级指令流水线,但是ARM9和ARM9之后的版本都使用五级指令流水线。其中需要说明:


  • 指令:给CPU核下发的命令,CPU核根据命令完成一个功能。(例如:给CPU核发一个add指令,就是告诉CPU核做数据的加法运算)
  • 指令在哪里呢:指令就是存在于二进制可执行文件中,CPU核要想执行指令,首先将指令对应的二进制文件加载到内存中,指令最终存在于内存中,内存的访问以地址的执行访问,所以每一条指令也有对应的内存存储地址,当CPU要想运行一条指令,首先从内存中获取到指令。
  • 注意: CPU核工作在ARM状态下:一条指令的宽度为32位(4字节);CPU核工作在THUMB状态下:一条指令的宽度为16位(2字节)。

ARM7(ARMV4)三级指令流水线

三级流水线

  • 取指:CPU核中的取指器(硬件)从内存中读取要运行的指令。
  • 解码:CPU核取完指令后,该指令还不能直接运行(CPU核不识别),需要使用解码器进行解码成机器码。
  • 执行:解码完成后,CPU核最终执行指令。
  • 总结: 取指(F)->解码(D)->执行(E)


网络异常,图片无法展示
|

网络异常,图片无法展示
|

PC

  • PC是个寄存器,位宽为32位。它是ARM核(CPU核)中的寄存器,用来保存取指器要取的那条指令对应的内存存储地址。

例如:

#内存存储地址  指令
0x48000000  add
0x48000004  sub
0x48000008  and
....


当上述add指令呗执行的时候,取指器取得and指令,所以此时PC=0x48000008。


ARM7三级流水线特例——ldr指令

ldr指令功能:CPU核利用此指令能够从外设中加载数据到CPU核中。

ldr指令流水线分为五级:

取指(F)->解码(D)->执行(E)->访存(M)->写回(W)


说明:


  • 访存:CPU核寻找外设地址。
  • 写回:CPU核一旦找到了外设地址,将外设的数据加载到CPU核中。
  • 注意:ARM7的ldr指令在M和W的时候,跟在其后的两条指令的处理需要延后两个指令周期。

ARM7三级流水线特例——bl指令

bl指令的功能:CPU核执行bl指令,能够跳转到bl指令指定的内存位置去运行(取指->解码->执行)。

bl指令处理流水线需要五级:

取指(F)->解码(D)->执行(E)->保存返回地址(L)->正式跳转(A)


说明:


  • 保存返回地址(L):CPU核跳转到bl指令指定的地址运行之前先把返回地址(bl治疗的下一条指令)进行保存处理。
  • 正式跳转(A):CPU核跑到bl执行指定的地址去运行。

ARM7三级流水线特例——中断

中断定义:中断是计算机非常重要的机制

问:计算机中为什么有中断呢?


  • 中断产生的根本原因就是CPU的数据除了速度远远快于外设的数据处理速度。举个例子:以CPU核读取UART接收缓冲区的数据为例,当CPU核发现UART接收缓冲区没有数据,通常的操作都是轮询方式(死等),判断接收缓冲区有没有数据到来,但是这种放松会大大消耗CPU的利用率,此时此刻就需要用到中断方式操作UART接收缓冲区。当接收缓冲区有数据,UART控制器会给CPU发送一个中断信号告诉CPU有数据到来,CPU就会停止手上的工作转而去处理UART接收数据,之后在回到之前的流程中继续处理刚刚的事情。这样大大提高了CPU的利用率。

CPU核接收到中断信号后,开始处理中断,中断处理流水线需要四级:

切记: 当CPU核正在执行某个处理时,CPU核受到中断信号,CPU核处理中断一定是在当前处理执行完之后再去处理。

解码中断(DI)->执行中断(EI)->保存返回地址(L)->正式跳转(A)


说明:


  • 保存返回地址:中断产生之前,CPU在执行别的指令,当中断到来,CPU核转而执行中断处理函数,处理完还需要再回来继续处理之前的指令,所以需要保存返回地址。

ARM9(ARMV4)以后的ARM核的五级指令流水线

ARM9以后的所有ARM核指令流水线一律采用五级流水线,也就是将访存(M)和写回(W)给每一条指令都添加上。


  • F->D->E->M->W

ARM编程模型

ARM核的七种工作模式

  • SVC管理模式: 当系统复位或者软件执行swi指令,CPU核切换到此模式下。
  • FIQ快速中断模式: 外设给CPU核发送一个FIQ快速中断信号,CPU核会切换到此模式下。
  • IRQ中断模式: 外设给CPU核发送一个IRQ普通中断信号,CPU核切换到此模式。
  • Abort中止模式: 当CPU核取指失败或者访存失败,CPU核进入此模式。
  • undef未定义指令模式: 当CPU核执行一个不认识的指令(lisi),CPU核进入此模式。
  • system系统模式:
  • user用户模式: system和user一样,CPU核正常运行情况下,CPU就会处于这两个模式其中之一。Linux系统下,当CPU处理一个进程时就工作在user模式下。

ARM核的两种工作状态

ARM状态:


  • ARM指令:位宽 32 位。
  • Thumb状态:
  • thumb指令:位宽 16 位。

ARM核的37个寄存器

  • 寄存器:暂存数据的硬件,类似内存
  • 寄存器分类:特殊功能寄存器和ARM寄存器。
  • 特殊功能寄存器:各种硬件控制器内核的寄存器,也就是之前说的CPU通过访问这样一类寄存器都是通过地址指针形式访问。
  • ARM寄存器:仅仅存在于ARM核内部,CPU核访问内部的ARM寄存器通过名字(不论大小写),总共37个ARM寄存器。

ARM核37个寄存器:


  • 31个通用寄存器:r0, r1, r2, … … r15,每一种工作模式下又有自己独立的寄存器。
  • r15又称gc:永远只保存取指器要取的那条指令的内存存储地址。
  • r14又称lr:永远只保存返回地址。
  • r13又称sp:永远只保存栈指针。

6个状态寄存器:


  • 1个cpsr和5个spsr
  • cpsr:又称当前程序状态寄存器,也就是保存当前程序运行状态。
  • spsr:又称备份程序状态寄存器,本质目的就是为了保存cpsr的值。

详解CPSR程序状态寄存器:


  • BIT[4:0]:模式位mode
  • 10000 ,表示当前CPU核处于用户模式。
  • 10011 ,表示当前CPU核处于SVC管理模式。
  • BIT[5]:状态位T
  • 0 - ARM核处于ARM状态
  • 1 - ARM核处于thumb状态
  • BIT[6]:FIQ配置位F
  • 0 - 使能FIQ中断功能
  • 1 - 禁止FIQ中断功能
  • BIT[7]:IRQ配置位T
  • 0 - 使能IRQ中断功能
  • 1 - 禁止IRQ中断功能
  • BIT[28]:溢出标志位V
  • 0 - 表示程序运行结果没有发送溢出。
  • 1 - 表示程序运算结果发送溢出
  • BIT[29]:进位或者借位表示C
  • 0 - 表示程序运算没有发送进位或者借位。
  • 1 - 表示程序运算时发送了进位或者借位。
  • BIT[30]:零位Z
  • 0 - 表示程序运算结果为非0
  • 1 - 表示程序运算结果为0
  • BIT[31]:负或者小于位N
  • 0 - 表示程序运算结果不为负数或者不小于
  • 1 - 表示程序运算结果为负数或者小于
  • BIT[31:28]简称NZCV,只要程序运行,CPSR的值会随时随刻发生改变。

注意:


  • 现在有一个进程获取到CPU资源,此进程就可以投入运行,此时对应的CPU核的工作模式为User用户模式,此时由于CPU核执行进程对应的代码cpsr时刻进行改变,突然UART控制器给CPU核发送一个IRQ中断电信号,此时CPU核就会由 User用户模式切换到IRQ普通中断模式,紧接着CPU核开始去处理IRQ中断,本质就是CPU核去执行这个IRQ中断对应的一个函数而已,此函数也是一个程序,如果此程序运行,将来势必也会影响cpsr,但是将来中断处理完毕CPU核还要返回到原先被打断的进程继续运行,为了让原先的进程能够继续正确运行,所以CPU核在处理中断之前,先把当前进程的cpsr的值备份到IRQ模式下的spsr,将来中断返回 只需从IRQ模式下的spsr恢复原先进程的cpsr。

ARM支持的数据类型

Byte:1字节

HalfWord:2字节

Word:4字节

DoubleWord:8字节


ARM支持大端和小端模式,默认小端模式

X86是小端,PowerPC是大端。


ARM汇编语法格式:

参考代码:


.text @代码段的起始
.code 32 @使用ARM指令
.global start @声明一个全局标签start
start: @全局标签的内容如下
  mov r0, #10 @r0=10
  ldr r1, =3  @r1=3
  add r0, r0, r1@r0=r0+r1
  b .  @while(1);
.end @代码段的结束


切记:影响CPSR的NZCV位的两种情形:


  • 1.指令后面加s,运算结果影响CPSR的NZCV

add r0, r0, r1 #@r0=1,r1=-1
  #@r0保存运算结果,不影响CPSR的NZCV
   adds r0, r0, r1 #@r0=1,r1=-1 @CPSR的Z=1


  • 2.cmp比较指令后面不加s,运算结果同样影响cpsr

cmp比较指令本质做减法运算

cmp r0, r1 #@本质:运算结果=r0-r1


ARM异常

ARM核有7种异常:


异常 工作模式 CPU核运行地址 场景

复位异常 SVC管理模式 0x00 系统复位

undef未定义指令异常 undef未定义指令模式 0x04 CPU核执行一个不认识的指令

软中断异常 SVC管理模式 0x08 CPU核执行swi指令

预取指令异常 abort中止模式 0x0C CPU核取指失败

数据处理异常 abort中止模式 0x10 CPU核访存失败

IRQ中断异常 IRQ中断模式 0x18 外设给CPU发送IRQ中断电信号

FIQ中断异常 FIQ快速中断模式 0x1C 外设给CPU核发送FIQ快速中断电信号异常

  • 注意:一旦异常发生,CPU核会毫无条件的必须强制跑到对应的入口地址去执行。

ARM一旦触发异常会如何处理

以UART控制器给CPU核发送IRQ中断电信号为例,

理清IRQ异常的处理流程:


  • 1.当UART控制器准备好数据以后,首先会给中断控制器发送一个中断电信号。
  • 2.中断控制器接收到这个中断电信号以后经过一番的判断之后,中断控制器最终以IRQ的形式给CPU核发送一个IRQ中断电信号。
  • 3.CPU核一旦接收到IRQ中断电信号,就会触发一个IRQ异常,CPU核立马要处理这个IRQ异常。

CPU核硬件上自动完成以下工作:


  • 1.把当前程序对应的cpsr的值保存到IRQ中断模式下的spsr_irq

  • 2.设置cpsr,将cpsr的:
  • bit[4:0]=IRQ工作模式对应的值,让CPU核
  • 切换到IRQ中断模式
  • bit[5]=0,让ARM核切换到ARM状态下
  • bit[7:6]=11,禁止ARM核响应IRQ和FIQ中断

  • 3.保存返回地址:lr=pc-4


  • 问:为什么是lr=pc-4呢?
  • 答:例如:
  • 内存地址 指令
  • 0x8000 add
  • 0x8004 sub
  • 0x8008 orr
  • 当add指令执行的时候:pc=0x8008
  • 当add指令执行的时候,触发IRQ异常
  • 将来IRQ异常处理完毕,CPU核返回到0x8004
  • 去运行,所以lr=pc-4=0x8008-4=0x8004
  • 4.设置pc=0x18

  • 问:为什么0x18呢?
  • 答:因为IRQ异常处理的入口地址为0x18
  • 问:pc=0x18代表什么含义呢?
  • 答:本质就是让CPU核跑到0x18地址去运行(F->D->E->M->W)。
  • 问:0x18地址放什么东西?
  • 答:0x18势必放自己编写的软件代码

切记:只要给pc赋值(地址),那么CPU核就会跑到对应的地址去运行。


  • 结论:一旦ARM核做pc=0x18,让CPU核跑到0x18地址去运行,至此正式开启了软件进一步处理IRQ异常的流程。

软件处理IRQ异常的流程:


  • 软件如何处理IRQ异常完全有程序员自行决定,软件处理IRQ异常结束以后,最后让CPU核返回到原先被打断的地方(某个程序)继续执行,软件只需完成以下两个动作即可
  • 实现返回:
  • cpsr=spsr_irq:将IRQ模式下的spsr的值归还给cpsr,spsr_irq保存原先被打断的程序运行的状态。
  • pc=lr:lr保存的返回地址,让CPU核跑到原先被打断的地方继续执行
  • 至此:IRQ异常处理完毕!

ARM核跳转的方式

ARM核跳转的方式有三种:


  • ARM核发生异常,一旦发生异常,ARM核跑到对应的异常入口地址去。
  • ARM核执行b或者bl跳转指令。
  • 直接向pc赋值(此方法最直接)

ARM指令——分支跳转指令

ARM指令集之分支跳转指令:b/bl/bx


b为不带返回的跳转指令


  • 跳转范围相对PC,±32MB

b loop 无条件跳转

beq loop 有条件跳转

bl为待返回的跳转指令


  • 跳转范围相对PC,±32MB

切记:当CPU核执行bl指令时,CPU核硬件上自动将

下一条指令的地址保存在lr中

所以将来软件返回的指令为:mov pc, lr

例如:

内存地址 指令

0x8000 bl strcmp @当bl执行时,pc=0x8008,lr=0x8004

0x8004 add r0, r0, r1

0x8008 sub r0, r0, r1

strcmp:

一大堆指令

mov pc, lr @pc=lr=0x8004,让CPU核跑到0x8004去运行

bx带状态切换的指令(了解)


  • bx跳转的地址的bit[0]=0:切换到ARM状态

bx跳转的地址的bit[0]=1:切换到Thumb状态

例如:

ldr r0, =0x48000000

bx r0 @让CPU核切换到ARM状态并且跳转到0x48000000去运行

ldr r0, =0x48000001

bx r0 @让CPU核切换到Thumb状态并且跳转到0x48000001去运行


相关文章
|
2月前
|
Ubuntu Linux
查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
查看Linux系统架构的命令,查看linux系统是哪种架构:AMD、ARM、x86、x86_64、pcc 或 查看Ubuntu的版本号
237 3
|
5天前
|
设计模式 人工智能 算法
编程之旅:从代码到架构的感悟
【9月更文挑战第33天】在编程的世界里,代码不仅是实现功能的工具,更是连接思想与现实的桥梁。本文将通过个人的编程经历,分享从编写第一行代码到设计系统架构的旅程,探索编程背后的哲学和技术演变。我们将一起思考,如何在代码的海洋中找到自己的航向,以及在这个过程中如何不断成长和适应变化。
|
2月前
|
机器学习/深度学习 算法 数据库
阿里云服务器架构区别解析:从X86计算、Arm计算到高性能计算架构的区别参考
在我们选择阿里云服务器的架构时,选择合适的云服务器架构对于提升业务效率、保障业务稳定至关重要。阿里云提供了多样化的云服务器架构选择,包括X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器以及高性能计算等。本文将深入解析这些架构的特点、优势及适用场景,以供参考和选择。
阿里云服务器架构区别解析:从X86计算、Arm计算到高性能计算架构的区别参考
|
15天前
|
存储 缓存 Java
JAVA并发编程系列(11)线程池底层原理架构剖析
本文详细解析了Java线程池的核心参数及其意义,包括核心线程数量(corePoolSize)、最大线程数量(maximumPoolSize)、线程空闲时间(keepAliveTime)、任务存储队列(workQueue)、线程工厂(threadFactory)及拒绝策略(handler)。此外,还介绍了四种常见的线程池:可缓存线程池(newCachedThreadPool)、定时调度线程池(newScheduledThreadPool)、单线程池(newSingleThreadExecutor)及固定长度线程池(newFixedThreadPool)。
|
2月前
|
设计模式 算法 PHP
深入理解PHP中的数组操作探索编程之美:从代码到架构的思维转变
【8月更文挑战第24天】在PHP编程中,数组是基础且强大的数据结构。本文将通过浅显易懂的方式,介绍如何在PHP中高效地操作数组,包括创建、遍历、排序和过滤等常见任务。无论你是初学者还是有经验的开发者,这篇文章都会带给你新的启示。 【8月更文挑战第24天】在编程的世界中,代码不仅仅是冰冷的字符排列,它承载着思想、解决问题的智慧和创新的灵魂。本文将通过个人的技术感悟,带领读者从编写单一功能的代码片段出发,逐步深入到整个软件架构的设计哲学,探索如何将代码块转化为高效、可维护和可扩展的系统。我们将一起见证,当代码与架构思维相结合时,如何引发技术实践的革命性飞跃。
|
2月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
|
1月前
ARM64架构提供的Cache操作
ARM64架构提供的Cache操作
|
2月前
|
存储 前端开发 数据库
神秘编程世界惊现强大架构!Web2py 的 MVC 究竟隐藏着怎样的神奇魔力?带你探索实际应用之谜!
【8月更文挑战第31天】在现代 Web 开发中,MVC(Model-View-Controller)架构被广泛应用,将应用程序分为模型、视图和控制器三个部分,有助于提高代码的可维护性、可扩展性和可测试性。Web2py 是一个采用 MVC 架构的 Python Web 框架,其中模型处理数据和业务逻辑,视图负责呈现数据给用户,控制器则协调模型和视图之间的交互。
29 0
|
3月前
|
Kubernetes Cloud Native 微服务
探索云原生技术:Kubernetes在微服务架构中的应用Python编程之旅:从基础到进阶
【7月更文挑战第31天】随着云计算技术的迅猛发展,云原生概念应运而生,它代表了一种构建和运行应用程序的全新方式。本文将通过实际代码示例,深入探讨Kubernetes这一云原生关键技术如何在微服务架构中发挥其强大的作用。我们将从容器化开始,逐步过渡到Kubernetes集群的搭建与管理,最后展示如何部署和管理一个微服务应用。
47 2
|
2月前
|
程序员
软件设计与架构复杂度问题之战略编程与战术编程的主要区别如何解决
软件设计与架构复杂度问题之战略编程与战术编程的主要区别如何解决