ARM 汇编指令是 ARM 处理器的机器语言直接控制硬件执行操作。理解 ARM 汇编对于底层开发、性能优化和调试非常重要。学习arm汇编的主要目的是为了编写arm启动代码启动代码启动以后引导程序到c语言环境下运行。换句话说启动代码的目的是为了在处理器复位以后搭建c语言最基本的需求。因此启动代码的主要任务有初始化异常向量表初始化各工作模式的栈指针寄存器开启arm内核中断允许将工作模式设置为user模式完成上述工作后引导程序进入c语言主函数执行mov加载12位立即数到寄存器或转移一个寄存器的值到另外一个寄存器mov r0, #2 ;加载立即数2到寄存器r0MOV{S}c Rd, #constmov r1, r0 ;将r0寄存器的值加载到r1MOV{S}c Rd, Rm大多数指令的格式为opcode rd, rn rm,其中rd是目标寄存器rn是第一操作数寄存器; mov r0, #1 ; mov r1, #2 ; mov r2,r1 ; mov r3,r0,lsl #2 ; mov r4,r3,lsl r1addADD{S}c Rd, Rn, #constADDS}c Rd, Rn, Rm{, shift}ADD R0, R1, R2 ; R0 R1 R2 ADD R0, R1, #10 ; R0 R1 10 ADD R0, R1, R2, LSL #2 ; R0 R1 (R2 subSUB{S}c Rd, Rn, #constSUB{S}c Rd, Rn, Rm{, shift}SUB R0, R1, R2 ; R0 R1 - R2 SUB R0, R1, #10 ; R0 R1 - 10立即数立即数Immediate是 ARM 汇编中直接写在指令里的常数不需要从内存或寄存器读取。判断条件立即数是直接写在指令中的常数。ARM 指令只有 12 位给立即数所以不是所有数字都能直接加载。LDR 伪指令可以加载任意 32 位数编译器会自动处理。记住MOV 有立即数限制LDR 没有限制。LDR,SDRldr r0 ,0x40000000 ldr r1 ,[r0] ldr r0, 0x40000004 ldr r2, [r0] add r3,r1,r2 ldr r0,0x40000008 str r3,[r0]STR R0, [R1] ; *R1 R0将 R0 的值存到 R1 指向的地址 STR R0, [R1, #4] ; *(R14) R0 STR R0, [R1, R2] ; *(R1R2) R0cmp比较指令CMP比较指令用于比较两个寄存器的值或者比较一个寄存器和立即数的值其原理是对待比较的两个数求差看结果是否为0这个指令会无条件修改N,V,C,Z位。如mov r0, #100cmp r0, #100会导致Z置位从条件码表可知只要Z置位就是两数相等。espmov r0,#1 mov r1,#3 mov r3,#5 cmp r0,r1 movlt r2,r1 movgt r2,r0 cmp r2,r3 movlt r2,r3用汇编来写dowhile循环mov r0,#1 mov r1,#0 lable add r1,r0,r1 add r0,r0,#1 cmp r0,#100 ble table finished b finishB、BL、BX指令全称核心作用是否保存返回地址是否切换状态BBranch无条件跳转❌ 不保存❌ 不切换BLBranch with Link函数调用✅ 保存到 LR❌ 不切换BXBranch and eXchange跳转并切换状态❌ 不保存✅ 可切换场景用什么指令原因函数调用要回来BL需要保存返回地址到 LR无条件跳转不用回来B不需要返回地址节省代码无限循环B自己b .或b label函数返回BX LR根据 LR 最低位自动切换状态状态切换BX Rm切换 ARM/Thumb 模式调用 Thumb 函数BLX带返回的状态切换调用栈区的保护arm栈的四种类型类型名称增长方向SP指向FA满增栈向高地址最后一个数据EA空增栈向高地址下一个空位FD满减栈向低地址最后一个数据ED空减栈向低地址下一个空位STMFD Store Multiple Full Descending 存储多个寄存器到满递减栈LDMFD Load Multiple Full Descending 从满递减栈加载多个寄存器_asm_max mov r0,#20 mov r1,#10 stmfd sp!,{r0,r1,lr}//入栈 bl _asm_min ldmfd sp!,{r0,r1,lr}//出栈 cmp r0,r1 movgt r2,r0 movlt r2,r1 mov pc,lr bx lr关于c函数的调用首先框架开头加上PRESERVE8PRESERVE8是 ARM 汇编中的一个伪指令用于告诉链接器代码的栈对齐要求确保栈在函数调用边界是8 字节对齐的作用importimport在 C 语言中用#include是调用 C 函数的前提条件它告诉编译器函数的声明函数原型让编译器知道如何正确调用这个函数。ldr sp,0x40001000 import c_add mov r0,#3 mov r1,#4 mov r2,#5 mov r3,#6 stmfd sp!,{r0-r12,lr} stmfd sp!,{r4} bl c_add ldmfd sp!,{r0-r12,lr} ldmfd sp!,{r4} stmfd sp!,{r0-r12,lr} bl _asm_max ldmfd sp!,{r0-r12,lr}其中的参数传递将c语言传递的参数保存到通用寄存器返回值保存到r0exportexport在 ARM 汇编中用于将符号函数名、变量名导出让其他文件C 或汇编可以调用。它是实现模块化编程和跨文件调用的关键。_asm_fn export _asm_fn svc #7 bx lr