ARM架构

地址空间_RISC与CISC

ARM中怎么访问寄存器?就像访问内存一样,用指针

c 复制代码
unsigned int *p =  0x40010800; // p等于某个寄存器的地址

*p = val;   // 写这个地址,也就是写这个寄存器
val = *p;  // 读寄存器

在ARM CPU看来,内存,I/O的操作是一样的。根据CPU发出的地址选择不同的设备。

在x86架构中内存和IO是分开的,根据CPU发出的指令选择不同的设备

RISC

ARM芯片属于精简指令集计算机(RISC:Reduced Instruction Set Computing),它所使用的指令比较简单,有如下特点:

  1. 对内存只有读、写指令
  2. 对于数据的运算是在CPU内部实现
  3. 使用RISC指令的CPU复杂度小一点易于设计

CISC

X86属于复杂指令集计算机(CISC:Complex Instruction Set Computing),它所用的指令比较复杂,比如某些复杂的指令会通过"微程序"实现。

比如执行乘法指令时,实际上会去执行一个"微程序",

在"微程序"里,

一样是去执行这4不操作:

① 读内存a

② 读内存b

③ 计算a*b

④ 把结果写入内存

但是对于程序员来说,

他看不到"微程序",

他好像用一条指令就搞定了这一切!

RISC与CISC比较

CISC的指令能力强,单多数指令使用率低却增加了CPU的复杂度,指令是可变长格式;

RISC的指令大部分为单周期指令,指令长度固定,操作寄存器,对于内存只有Load/Store操作

CISC支持多种寻址方式;RISC支持的寻址方式

CISC通过微程序控制技术实现;

RISC增加了通用寄存器,硬布线逻辑控制为主,采用流水线

CISC的研制周期长

RISC优化编译,有效支持高级语言

ARM内部寄存器

在CPU内部,用什么来保存a、b、a*b?

无论是Cortex-M3/4或者A7,CPU内部都有R0~R15寄存器,用来暂存数据。

  1. LDR R0,a 把地址a上的值赋值给R0
  2. LDR R1,b 把地址b上的值赋值给R1
  3. ADD R0,R0,R1 将R0上的值与R1相加,结果保存在R0
  4. STR R0,a 把R0的值赋到地址a空间上。

R13:SP,栈指针

R14:LR,用来保存返回地址

R15:PC,程序计数器,预执行指令地址,写入新值即可跳转

对于Cortex-M3/4,汇编指令里使用SP,但是可能对应不同的SP寄存器,一般情况下都是使用SP_main,运行RTOS时,可以让APP使用SP_process。

xPSR保存程序状态,比如上一条指令的执行结果、比较结果,也有一些控制作用,比如屏蔽中断,使能中断。


ARM汇编概述

一开始,ARM公司发布两类指令集:

  1. ARM指令集,32位,高效,但是太占空间。
  2. Thumb指令集,16位,节省空间。

因此,要节省空间时使用Thumb指令,要效率时使用ARM指令。

一个CPU既可以运行Thumb指令,也能运行ARM指令。

怎么区分当前指令是Thumb还是ARM指令呢?
程序状态寄存器中有一位,名为"T",它等于1时表示当前运行的是Thumb指令。

假设函数A是用Thumb指令写的,函数B是用ARM指令写的,怎么调用A/B?

我们可以往PC寄存器里写入函数A或B的地址,就可以调用A或B。

那么如何让CPU在执行A函数时进入Thumb状态,在执行B时进入ARM状态?

调用A时,让PC寄存器的BIT0等于1,即PC=函数A地址+(1<<0)

调用B时,让PC寄存器的BIT0等于0,即PC=函数B地址

很麻烦,因此引入Thumb2指令集,它支持16位指令集、32位指令混合编程。

有ARM、Thumb、Thumb2指令集,但是ARM公司推出了统一汇编语言,不需要去区分这些指令集。

在程序前面用CODE32/CODE16/THUMB表示指令集ARM/Thumb/Thumb2

汇编指令格式

  • Operation表示各类汇编指令,比如ADD、MOV
  • cond表示condition,即该指令执行的条件
  • S表示该指令执行后,会去修改程序状态寄存器
  • Rd为目的寄存器,用来存储运算的结果
  • Rn、Operand2表示两个源操作数

Operation表示各类汇编指令,比如ADD、MOV

cond有多种取指,如

读内存指令:LDR/LDM

写内存指令:STR/STM

LDR:Load Register LDM:Load Multiple Register

STR:Store Register STM:Store Multiple Register

立即数

MOV R0,#VAL

意思是把VAL这个值存入R0寄存器。

VAL可以是任意值吗?

  • 不可以,必须是立即数。
  • 假设VAL可以是任意数,MOV R0,#VAL本身是16位或32位,哪来的空间保存任意数值的VAL?所以,VAL必须符合某些规定。

LDR伪指令

去判断一个VAL是否是立即数,很麻烦!

并且就是想把任意数值赋给R0,怎么办?

可以使用伪指令

c 复制代码
LDR R0, =VAL

伪指令,就是假的、不存在的指令。

LDR作为"伪指令"时,指令中有一个=,否则它就是真实的LDR指令了。

编译器会把伪指令替换成真实的指令,比如:

c 复制代码
LDR R0, =0x12

0x12是立即数,那么替换为:MOV R0,#0x12

c 复制代码
LDR R0, =0x12345678

0x12345678不是立即数,那么替换为:

c 复制代码
LDR R0,[PC,#offset]  //2.使用Load Register读内存指令读出值,offset是链接程序时确定的

Label DCD 0x12345678 //1.编译器在程序某个地方保存这个值

ADR伪指令

ADR的意思是:address,用来读取某个标号的地址

c 复制代码
ADR R0,Loop

Loop
	ADD R0,R0,#1

它是伪指令,会被转换成某条真实的指令,比如:

c 复制代码
ADD R0,PC,#val  ;val在链接时确定

Loop
	ADD R0,R0,#1

ARM编译器与GCC编译器语法差异

使用keil这种工具,所用到的编辑器就是armasm

arm-linux-gnueabihf这种就是GNU Assembler

相关推荐
zhou lily3 小时前
高可用(HA)架构:在混合云环境下,如何通过多活容灾保障核心业务流的稳定性
架构
吴佳浩 Alben4 小时前
Agent 安全红线:越狱防御、间接注入与数据防泄漏实战
人工智能·安全·语言模型·架构·ai编程
木木学AI4 小时前
2026主流大模型电话机器人系统解析:技术架构、业务执行与企业落地实践
架构·系统架构·机器人
ChampaignWolf5 小时前
在 SAP S/4HANA 内部基于 ICF Handler 从零实现 ABAP MCP Server:架构、代码与踩坑实录
c++·架构·sap·abap·mcp
国科安芯5 小时前
星链供电架构中的高集成度电源管理方案研究——基于ASP4644四通道降压稳压器在低轨卫星星座中的应用分析
大数据·单片机·嵌入式硬件·架构·低轨卫星·星间链路
诚心呈意共享外卖配送系统5 小时前
中秋礼品配送峰值场景下,自建同城配送平台的技术选型与架构实践
架构·系统架构·创业创新
爱吃火鸡面呀5 小时前
HDFS 架构深度解析:从核心组件到数据读写全流程
hadoop·hdfs·架构
wuyk5555 小时前
从零吃透 MQTT 通信|第 8 章 FreeRTOS 多任务架构下 MQTT 工程架构,任务拆分、队列解耦、临界区保护
c语言·开发语言·stm32·学习·架构
彧azz6 小时前
Redis 全面指南:从核心概念到高可用架构实战
数据库·redis·架构
SLD_Allen6 小时前
MoE架构原理与算力基础设施重估
架构·moe