ARM 中常用的汇编指令解释汇总

前言

嵌入式项目中经常涉及到需要通过分析编译后的汇编文件,来确定异常代码,对一些常用的指令进行了汇总。

一、处理器内部数据传输指令

在ARM架构中,包括Cortex-A7处理器内部,有一些专门用于数据传输的指令,这些指令用于在寄存器之间移动数据或在寄存器和内存之间进行数据传输。

MOV: 将数据从一个寄存器复制到另一个寄存器。

MOV R0, R1 @将寄存器R1中的数据传给寄存器R0 即R0=R1
MOV R0, #0X01 @将立即数0x01传给寄存器R0 即R0=0X01

MRS: 将特殊寄存器(CPSR,SPSR)中的数据传给通用寄存器。

MRS R0, CPSR

MSR: 将通用寄存器中的数据传给特殊寄存器(CPSR,SPSR)。

MRS CPSR, R0

二、存储器访问指令

在很多计算机体系结构中,包括ARM架构,不能直接访问存储器,而是需要借助存储器访问指令去配置寄存器,原因是为了实现灵活性、可编程性以及动态配置的需要。

LDR:用于从内存中加载数据到寄存器。LDR Rd, [Rn, #offset]

LDR Rd, [Rn, #offset]

LDR R0, [R1] ; 将R1寄存器指向的内存地址处的数据加载到R0中
LDR R2, [R3, #8] ; 将R3寄存器指向的内存地址 + 8 处的数据加载到R2中
LDR R4, [R5, R6] ; 将R5寄存器指向的内存地址 + R6 寄存器的值处的数据加载到R4中

STR:用于从内存中加载数据到寄存器。这个指令非常常见,用于访问内存中的变量、数组元素或其他数据。STR Rd, [Rn, #offset]

三、压栈和出栈指令

现场保护(Save Context)

在函数调用、中断或异常处理开始时,程序通常会保存当前执行环境的状态,主要包括一些关键的寄存器的值、堆栈指针等信息。这个过程被称为现场保护。目的是为了在执行完特定任务后,能够正确返回到之前的状态。
恢复现场(Restore Context)

在函数调用、中断或异常处理结束时,程序需要将之前保存的执行环境状态恢复,确保返回到调用前的状态。这个过程被称为恢复现场。

在汇编语言中,压栈(Push)和出栈(Pop)指令通常用于实现现场保护和恢复现场的操作。这些指令可以用来将寄存器的值保存到栈中(现场保护),以及从栈中弹出值并存储回寄存器中(恢复现场)。

压栈指令(Push):

PUSH 指令用于将寄存器或数据压入栈中。这会将数据推入栈顶,并将栈指针递减以指向新的栈顶位置。

PUSH {R0, R1, R2} @将寄存器R0、R1、R2中的数据依次压入栈中。

出栈指令(Pop):

POP 指令用于从栈中弹出数据,同时将栈指针递增以指向新的栈顶位置。出栈的顺序与入栈的顺序相反。

POP {R0, R1, R2} @将从栈顶弹出数据,并分别存储到寄存器R2、R1、R0中。

四.跳转指令

在汇编语言中,跳转指令用于改变程序的执行流程,即从一个地址转移到另一个地址。跳转指令是实现条件分支、循环、函数调用等控制流操作的基本工具。

无条件跳转B:

B(Branch)指令是无条件跳转指令,它会将程序控制转移到指定地址。

B target_address @将程序无条件地跳转到 target_address 处。

子程序调用和返回BL:

BL(Branch with Link)指令用于调用子程序,并将返回地址保存在链接寄存器中。返回时使用 BX 或 POP 指令。BL相比于B,在跳转之前会在寄存器LR中保存当前PC寄存器值,所以可以通过将LR寄存器中的值重新加载到PC中来继续从跳转之前的代码处运行,这是子程序调用的一个基本但常用的手段。

BL subroutine_address @调用子程序
BX LR @从链接寄存器中加载返回地址,实现返回

条件跳转:

条件跳转指令根据某个条件是否满足来决定是否执行跳转。常见的条件跳转指令有:

  • BEQ(Branch if Equal):等于零时跳转
  • BNE(Branch if Not Equal):不等于零时跳转
  • BLT(Branch if Less Than):小于时跳转
  • BGT(Branch if Greater Than):大于时跳转

五.算术运算指令

算术运算指令用于执行各种数学运算,如加法、减法、乘法、除法等。这些指令允许程序对数据进行处理并得出结果。在嵌入式开发中,咱们一般只会用到加减命令,乘除命令基本用不到。

加法指令:

ADD(Addition)指令用于将两个操作数相加,并将结果存储在目标寄存器中。

ADD Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

减法指令:

SUB(Subtraction)指令用于将一个操作数减去另一个操作数,并将结果存储在目标寄存器中。

SUB Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

乘法指令:

MUL(Multiply)指令用于将两个操作数相乘,并将结果存储在目标寄存器中。

MUL Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

除法指令:

DIV(Divide)指令用于将一个操作数除以另一个操作数,并将结果存储在目标寄存器中。

SDIV Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

六.逻辑运算指令

逻辑运算指令用于执行各种逻辑运算,例如按位与、按位或、按位异或等。这些指令允许程序员对二进制数据进行逻辑操作。
按位与指令:

AND(Bitwise AND)指令用于对两个操作数执行按位与操作,并将结果存储在目标寄存器中。

AND Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

按位或指令:

ORR(Bitwise OR)指令用于对两个操作数执行按位或操作,并将结果存储在目标寄存器中。

ORR Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

按位异或指令:

EOR(Bitwise Exclusive OR,异或)指令用于对两个操作数执行按位异或操作,并将结果存储在目标寄存器中。

EOR Rd, Rn, Operand2
@Rd 是目标寄存器,Rn 是源寄存器,Operand2 是另一个操作数。

按位取反指令:

MVN(Bitwise NOT)指令用于对一个操作数执行按位取反操作,并将结果存储在目标寄存器中。

MVN Rd, Rn
@Rd 是目标寄存器,Rn 是源寄存器。