ARM汇编指令简介

发布于:2022-12-05 ⋅ 阅读:(911) ⋅ 点赞:(0)

注意!ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用。

目录

伪操作、段

一、处理器常用指令

二、存储器访问指令

三、压栈和出栈指令

四、跳转指令

五、算数运算指令

六、逻辑运算指令


伪操作、段

label:instruction@comment

标号(地址位置):指令@注释

add:

MOVS R0,#0x12 @设置 R0=0x12

.test 表示代码段

.data初始化的数据段

.bss未初始化的数据段

.rodata 只读数据段

用户可以使用 . section 来定义一个段 每个段以段名开始以下一个段段名或文件结尾结束

.section .testsection @定义一个testsection段

汇编程序的默认入口标号是_start,不过我们也可以在链接脚本中使用 ENTRY 来指明其它的入口点,下面的代码就是使用_start 作为入口标号:

.global _start

_start:

ldr r0,=0x12 @r0=0x12

上面代码中.global 是伪操作,表示_start 是一个全局标号,类似 C 语言里面的全局变量一样,常见的伪操作有:

.byte 定义单字节数据,比如.byte 0x12。

.short 定义双字节数据,比如.short 0x1234。

.long 定义一个 4 字节数据,比如.long 0x12345678。

.equ 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。

.align 数据字节对齐,比如:.align 4 表示 4 字节对齐。

.end 表示源文件结束。

.global 定义一个全局符号,格式为:.global symbol,比如:.global _start。

GNU 汇编也支持函数,函数格式如下: GNU 汇编函数返回语句不是必须的

函数名:

函数体

返回语句

一、处理器常用指令

MOV指令 将数据从一个寄存器拷贝到另外一个寄存器

MOV R0,R1 @将R1的数据复制到R0 即 R0=R1

MOV R0,#0x12 @将立即数0x12传递给R0寄存器 即R0=0X12

MRS指令 用于将特殊寄存器 如 CPSR、SPSR 中的数据传递给通用寄存器,要读特殊寄存器的只能用MRS指令

MRS R0 , CPSR

MSR指令 用来将通用寄存器的值传递给特殊寄存器,也就是写特殊寄存器 ,写特殊寄存器只能用MSR

MSR CPSR , R0

二、存储器访问指令

ARM不能直接访问存储器,比如RAM中的数据 I.MX6ul中的寄存器就是RAM类型的 我们用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器 读取也是一样的

LDR指令 LDR用于从存储加载数据到Rx中,LDR最长用的就是读取CPU的寄存器值

LDR R0, =0x0209c004 @将寄存器地址0x0209c004加载到R0中 即R0= 0x0209c004

LDR R1, 【R0】 @读取地址0x0209c004中的地址到R1寄存器中

STR 用于写数据到存储器中

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C0042

LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X200000023

STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和STRB,按半字操作的指令就是 LDRH 和 STRH。

三、压栈和出栈指令

现场保护的时候需要进行压栈 即入栈,恢复现场要进行出栈操作

压栈指令为PUSH 出栈指令为POP 这是一种多存储和多加载指令,即可以一次性操作多个寄存器数据,他们利用SP栈指针来生成地址

PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈

PUSH {LR} @将 LR 进行压栈

POP {LR} @先恢复 LR

POP {R0~R3,R12} @在恢复 R0~R3,R12

出栈要从栈顶也就是当前sp指针的位置开始 PUSH 和 POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”

四、跳转指令

有多种跳转操作,比如:

①、直接使用跳转指令 B、BL、BX 等。

②、直接向 PC 寄存器里面写入数据。

B指令 最简单的跳转指令 B指令会将PC寄存器的值设置会跳转目标地址,一但执行B指令 ARM处理器就会立即跳转到制定的目标地址

start:

ldr sp,=0X80200000 @设置栈指针

b main @跳转到 main 函数

BL指令 BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。

push {r0,r1} @ 保存r0,r1

cps #0x13 @ 进入svc模式,允许其他中断在此进入

bl system_irqhandler @加载c语言中断处理函数到R2寄存器中、

cps #0x12 @进入IRQ模式

pop {R0, R1} @出栈

str r0,{r1,#0x10} @ 中断执行完成,写EOIR

五、算数运算指令

六、逻辑运算指令

在嵌入式中最常用的就是加减法 逻辑运算很好理解 在汇编配置的 I.MX6ULL的外设寄存器的时候可能会用到