ARM 汇编核心知识点总结

ARM汇编知识点总结

学习目标:编写ARM启动代码,CPU复位后搭建C语言运行环境,最终跳转到C语言main函数执行。 启动代码五大任务

  1. 初始化异常向量表
  2. 初始化各个处理器模式的栈指针SP
  3. 配置内核中断
  4. 设置处理器工作模式(User模式)
  5. 跳转进入C语言main函数

一、伪操作(给汇编器看,不是CPU机器指令)

伪操作 功能
AREA reset,CODE,READONLY 定义段;段名reset,代码段,只读;复位代码放在该段
CODE32 后续使用32位ARM指令集;THUMB代表16位Thumb指令集
ENTRY 标记程序入口,复位从此处开始执行
END 汇编源文件结束标记
IMPORT 声明外部符号(外部C函数),相当于C的extern
EXPORT 导出汇编标号,供C语言调用
PRESERVE8 保证栈8字节对齐,解决汇编调用C的编译报错

二、核心汇编指令

1.数据传送指令

  1. MOV :数据拷贝,寄存器‑寄存器、寄存器‑合法立即数;支持移位操作(LSL/LSR/ASR/ROR/RRX);{S}后缀影响CPSR标志位。

    注意:mov sp,#0x40001000报错,地址大多不是合法立即数,改用ldr sp,=0x40001000

  2. MVN:按位取反后传送。

2.算术运算

  • ADD{S} :加法;S后缀会更新NZCV标志。
  • SUB{S} :减法。 格式:ADD Rd,Rn,Rm{,移位},第二操作数支持:立即数、寄存器、寄存器移位。 ⚠错误写法:add r0,#3,#2,汇编指令只能一个立即数。

3.位操作指令

  1. BIC:位清零,掩码中为1的bit清零目标寄存器。
  2. ORR:位置1,掩码中为1的bit置1目标寄存器。

4.比较指令

CMP Rn,操作数 :等价于SUBS Rn,操作数,做减法,只更新CPSR的NZCV标志,不保存运算结果,配合条件码使用(EQ/NE/GT/LT/GE/LE/AL无条件)。

5.跳转指令 B / BL / BX

  1. B label:无条件跳转;修改PC,不保存返回地址LR,不能返回。
  2. BL label:带链接跳转;跳转前把下一条指令地址存入LR(R14),用于函数调用;返回用BX LR
  3. BX Rm:跳转到Rm保存的地址;同时根据Rm最低bit切换ARM/Thumb指令集。 对比:MOV PC,LR仅跳转,不能切换指令集BX LR既返回又切换指令集。

6.加载存储

  • LDR Rt,<label>:伪指令,把地址/常量加载进寄存器;处理无法用mov加载的大数/地址。
  • LDMFD / STMFD:满递减栈批量读写寄存器
    • STMFD SP!,{reglist}保护现场 ,寄存器压栈;!表示自动更新SP。
    • LDMFD SP!,{reglist}恢复现场,寄存器出栈。

7.访问CPSR程序状态寄存器(修改处理器模式)

  • MRS Rd,CPSR:读状态寄存器,CPSR→通用寄存器。
  • MSR CPSR,Rn:写状态寄存器,通用寄存器→CPSR。 修改工作模式套路:MRS读CPSR → BIC清空M位 → ORR设置模式码 → MSR写回CPSR。

8.软中断

SWI #n:触发软中断异常。

三、12位立即数(imm12)

  1. 立即数:编码写在指令内部的常数,不需要访问内存。
  2. 编码组成:8位基础数imm8 +4位循环移位控制;实际是把8位数**循环右移偶数次(0,2...30)**得到32位数值。
  3. 判断:32位数字,是否可以由一个0‑255的8位数循环右移偶数位得到;能=合法立即数;否则非法。 非法立即数不能用mov,要用ldr伪指令加载。

四、CPSR标志位 NZCV

  1. N(负标志):运算结果bit31=1(视为有符号负数),N=1。
  2. Z(零标志):运算结果全0,Z=1。
  3. C(进位/借位,无符号数) -加法:最高位进位C=1; -减法:无借位C=1,发生借位C=0。
  4. V(溢出,有符号数):有符号运算溢出则V=1;两正相加结果负、两负相加结果正就是溢出。

五、栈相关

  1. ARM默认:满递减栈 FD(Full Descending) -满:SP指向最后压入的有效数据; -递减:栈向低地址增长;压栈先SP自减,再写数据;出栈先读数据,SP再加。
  2. 四种栈类型:满递减FD、满递增FA、空递减ED、空递增EA。
  3. 栈初始化:ldr sp,=栈起始地址
  4. 函数嵌套必须保护现场:把用到的通用寄存器+LR压栈;返回前出栈恢复。

六、汇编循环(翻译C循环)

  1. do‑while:先执行循环体,再判断条件跳转

  2. while/for:先判断条件,满足才执行循环体

    ;while(i<=100) sum+=i;i++
    mov r0,#0 ;i
    mov r1,#0 ;sum
    loop
    cmp r0,#100
    bgt finish
    add r1,r1,r0
    add r0,r0,#1
    b loop
    finish
    b finish

七、函数调用 & ATPCS规则(C与汇编互相调用)

1.汇编调用C函数

  1. 汇编中IMPORT c_add声明外部C函数。
  2. PRESERVE8保证栈8字节对齐。
  3. 参数传递:前4个参数用 R0,R1,R2,R3第5个及以后参数压栈传递
  4. 返回值存放在 R0(64位返回值R0存低32位,R1存高32位)。
  5. 调用前保护现场stmfd sp!,{r0‑r12,lr}bl c_add调用;调用完恢复现场。

2.C调用汇编函数

  1. 汇编使用EXPORT func_name导出函数标号。
  2. C语言写extern int func(int a,int b);声明。
  3. 汇编函数用BX LR返回;返回值放R0。

寄存器约定:

  • r0‑r3:传前4参数,返回值,调用方保存;
  • r4‑r11:被调用函数必须保存,使用前压栈,返回前恢复;
  • r13=SP栈指针;r14=LR链接寄存器(返回地址);r15=PC程序计数器。

问答题:

  1. 什么是立即数?如何判断某数是不是合法12位立即数? 立即数是直接编码在指令内部的常量,不用访问内存。12位立即数由一个8位无符号数循环右移偶数次得到;把数字写成32位二进制,若能找到0‑255的8位数,循环右移偶数次等于该数,则合法,否则非法。
  2. b,bl,bx指令的区别是什么?
  • B:无条件跳转,修改PC,不保存返回地址LR,无法返回
  • BL:带链接跳转,跳转前将返回地址保存到LR,用于函数调用。
  • BX:跳转到寄存器保存的地址,同时根据寄存器bit0切换ARM/Thumb指令集;常用BX LR做函数返回。
  1. ARM内核采用的栈是哪种栈? ARM默认使用满递减栈FD。SP指向最后入栈有效元素;栈向低地址增长;压栈SP先减小,出栈SP后增大。
  2. CPSR中条件标志位,分别在什么情况下被置位
  • N:运算结果最高位bit31为1,N置1;
  • Z:运算结果等于0,Z置1;
  • C:加法最高位进位 / 减法无借位时C置1;减法借位C清0;用于无符号数;
  • V:有符号数运算溢出时V置1
  1. ARM汇编调用C语言函数以及C语言调用汇编编写的函数,函数参数和返回值如何处理? 遵循ATPCS调用约定: ①参数:前4个参数依次放在R0、R1、R2、R3;超过4个的参数通过栈传递。 ②返回值:32位返回值存放在R0;64位返回值低32位R0,高32位R1。 ③汇编调用C:IMPORT声明C函数,PRESERVE8栈对齐,保护现场,BL调用; ④C调用汇编:汇编EXPORT导出函数,C用extern声明函数原型;汇编函数最后BX LR返回。
相关推荐
Ray Wang3 小时前
Context上下文工程
python·学习·ai编程
百里香酚兰3 小时前
【Unity学习笔记】如何把粉色Prefab还原
笔记·学习·unity
老当益壮梁奶奶3 小时前
ARM 汇编学习笔记(二)启动代码、指令、函数调用与 C 混合编程
c语言·arm开发·单片机·嵌入式硬件·51单片机
索端阳4 小时前
ARM Day02 学习总结:ARM汇编基础核心知识点梳理
汇编·学习·arm
学习FPGA的电气小兴兴4 小时前
基于FPGA的CORDIC向量模式实现arctan运算,Verilog HDL实现
嵌入式硬件·fpga开发·数字信号处理·verilog·fpga·cordic·arctan
国科安芯4 小时前
商业航天星载数据管理单元的存储容错与接口集成方案研究
嵌入式硬件·架构·ecc·商业航天·抗辐射
天空'之城4 小时前
单片机基础核心知识点汇总(三十八)
单片机·嵌入式硬件
小叶肥辉4 小时前
LangChain链和LangGraph图的学习笔记【六】——提示语模板(3)——Few-Shot Prompting(少样本提示) 模板类
笔记·python·学习·langchain·prompt·aigc
for_ever_love__5 小时前
爬虫项目: 获取高分电影的数据总结
开发语言·python·学习