【ARM 裸机】汇编 led 驱动之基本语法

我们要编写的是 ARM 汇编,编译使用的是 gcc 交叉编译器,所以要符合 GNU 语法。

1、汇编指令

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

常用的存储器访问指令有两种:LDR 和 STR

LDR 指令

c 复制代码
LDR Rd, [Rn , #offset]  从存储器 Rn+offset 的位置读取数据存放到 Rd 中

LDR 主要用于从存储加载数据到寄存器 Rx 中,LDR 也可以将一个立即数加载到寄存器 Rx 中,LDR 加载立即数的时候要使用"=",而不是"#"。在嵌入式开发中,LDR 最常用的就是读取 CPU 的寄存器值,比如 I.MX6UL 有个寄存器 GPIO1_GDIR,其地址为 0X0209C004,我们现在要读取这个寄存器中的数据,示例代码如下;

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

上述代码就是读取寄存器 GPIO1_GDIR 中的值,读取到的寄存器值保存在 R1 寄存器中,上面代码中 offset 是 0,也就是没有用到 offset 。

STR 指令

c 复制代码
STR Rd, [Rn, #offset]   将 Rd 中的数据写入到存储器中的 Rn+offset 位置

LDR 是从存储器读取数据,STR 就是将数据写入到存储器中,以 I.MX6UL 寄存器GPIO1_GDIR 为例,现在我们要配置寄存器 GPIO1_GDIR 的值为 0X20000002,示例代码如下;

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

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

其他指令比如处理器内部数据传输指令(MOV、MRS、MSR等)、压栈和出栈指令(PUSH、POP)、跳转指令(B、BL等)、算数运算指令(ADD、ADC、SUB、SBC、MUL、UDIV、SDIV等)、逻辑运算指令(AND、ORR等)等不一一列举了。

2、LDR、STR 为什么用的是 R0、R1

这就涉及到 Cortex-A 寄存器组了,首先 Cortex-A7 处理器有 9 种处理模式如下图;

ARM 架构提供了 16 个 32 位的通用寄存器(R0 ~ R15)供软件使用,前 15 个(R0~R14)可以用作通用的数据存储,R15 是程序计数器 PC,用来保存将要执行的指令。ARM 还提供了一个当前程序状态寄存器 CPSR 和一个备份程序状态寄存器 SPSR,SPSR 寄存器就是 CPSR 寄存器的备份。

每一种模式可见的寄存器包括 15 个通用寄存器(R0~R14)、一两个程序状态寄存器和一个程序计数器 PC。在这些寄存器中,有些是所有模式所共用的同一个物理寄存器,有一些是各模式自己所独立拥有的。

因为 ARM 指令不能直接读取 RAM 中的数据,必须借助内部的寄存器来完成数据的读取,所以使用 R0、R1、R2等通用寄存器都是可以的。

相关推荐
大飞记Python2 小时前
Linux命令速查手册(测试开发4年实战总结,附PDF)
linux·网络·pdf
顾喵3 小时前
PetaLinux 2017.4 实操指南:PREEMPT_RT实时补丁移植+Zynq PL中断UIO用户态配置(超完整避坑版)
linux
小樱花的樱花4 小时前
Linux 线程的创建
linux·c语言·开发语言
mounter6254 小时前
BPF 的进化史:从网络过滤器到 AI 时代的 Linux 核心引擎
linux·网络·人工智能·ebpf·linux kernel·kernel
YMWM_4 小时前
video.preset的值为null和ultrafast的区别
linux·video
学逆向的5 小时前
汇编——数据存储模式
开发语言·汇编·网络安全
代码AC不AC6 小时前
【Linux】线程池
linux·线程池
网络小白不怕黑7 小时前
12.DHCP服务搭建
linux·运维·服务器·网络
FREEDOM_X8 小时前
Linux 多线程编程——总结
java·linux·运维·ubuntu
振南的单片机世界10 小时前
单片机:一颗芯片包办CPU、内存、外设的“单芯片计算机”
arm开发·stm32·单片机·嵌入式硬件