ARM汇编基础

对于ARM Cortex芯片,大部分芯片上电以后,SP指针未初始化,C语言无法运行。有些芯片还需要用汇编来初始化DDR。在进入C语言之前的阶段需要汇编做一些事情。

ARM汇编,编译使用的 GCC 交叉编译器,所以我们的汇编代码要符合 GNU 语法。

GNU 语法

基本格式

label:instruction @ comment

label 即标号,表示地址位置
instruction 即指令,也就是汇编指令或伪指令
comment 就是注释内容。

add:
    MOVS R0, #0X12 @设置 R0=0X12

定义段

可以通过用.section 伪操作来定义一个段

.section .testsection @定义一个 testsetcion 段

常见的段有
.text 表示代码段。
.data 初始化的数据段。
.bss 未初始化的数据段。
.rodata 只读数据段。

常见的伪操作有
.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。

汇编函数

函数名:
	函数体
	返回语句
/* 未定义中断 */
Undefined_Handler:
	 ldr r0, =Undefined_Handler
	 bx r0
/* SVC 中断 */
SVC_Handler:
	 ldr r0, =SVC_Handler
	 bx r0
/* 预取终止中断 */
PrefAbort_Handler:
	 ldr r0, =PrefAbort_Handler 
	 bx r0

Cortex-A7常用的汇编指令

内部数据传输指令MOV,MRS,MSR

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

MRS R0, CPSR @将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR
MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0

存储器访问指令

ARM 不能直接访问存储器,一般先将要配置的值写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器。读取 I.MX6UL 寄存器的值也是类似的逻辑。常用的存储器访问指令有两种:LDR 和STR。

LDR
LDR 最常用的就是读取 CPU 的寄存器值,比如 I.MX6UL 有个寄存器 GPIO1_GDIR,其地址为 0X0209C004,我们现在要读取这个寄存器中的数据。采用下面的汇编指令:

 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
 LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中

STR
LDR是读取,STR就是将数据写入到寄存器

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

压栈和出栈指令

堆栈(Stack)是一种常见的数据结构,具有“先进后出”(Last In First Out,LIFO)的特性,即最后入栈的元素最先被弹出。堆栈通常用于实现函数调用、表达式求值、递归算法等场景。

堆栈有两个基本操作:
入栈(Push):向堆栈顶部添加元素。
出栈(Pop):从堆栈顶部移除元素。

在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。压栈的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令,即可以一次操作多个寄存器数据。

堆区在低地址段,向上增长,可以由程序员自己开辟,栈区在高地址段主要存放函数参数值和局部变量等,由系统自动的分配。

STMFD SP!,{R0~R3, R12} @R0~R3,R12 入栈
STMFD SP!,{LR} @LR 入栈

LDMFD SP!, {LR} @先恢复 LR
LDMFD SP!, {R0~R3, R12} @再恢复 R0~R3, R12

在这里插入图片描述

跳转指令

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

算术运算指令

在这里插入图片描述

逻辑运算指令

在这里插入图片描述
参考:【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6
声明:本博客部分内容来自网络,旨在分享,若侵犯您的合法权益请及时联系删除。

  • 31
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

稚肩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值