为什么要有汇编
因为Cortex-A芯片一上电SP指针还没初始化,C环境还没准备 好,所以肯定不能运行C代码,必须先用汇编语言设置好C环境,比如初始化DDR、设置SP 指针等等,当汇编把C环境设置好了以后才可以运行C代码
GNU语法
如果大家使用过STM32的话就会知道MDK和IAR下的启动文件startup_stm32f10x_hd.s 其中的汇编语法是有所不同的,将MDK下的汇编文件直接复制到IAR下去编译就会出错,因 为MDK和IAR的编译器不同,因此对于汇编的语法就有一些小区别。编写IMX6UL汇编语法,编译使用的GCC交叉编译器,所以我们的汇编代码要符合GNU语法。
GNU汇编语法适用于所有的架构,并不是ARM独享的,GNU汇编由一系列的语句组成, 每行一条语句,每条语句有三个可选部分,如下:
label:instruction @ comment
label 即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到 指令的地址,标号也可以用来表示数据地址。注意label后面的“:”,任何以“:”结尾的标识 符都会被识别为一个标号。 instruction 即指令,也就是汇编指令或伪指令。 @符号,表示后面的是注释,就跟C语言里面的“/*”和“*/”一样,其实在GNU汇编文 件中我们也可以使用“/*”和“*/”来注释。 comment 就是注释内容。
常见伪指令
.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。
传输指令
LDR指令 LDR主要用于从存储加载数据到寄存器Rx中,LDR也可以将一个立即数加载到寄存器Rx 中,LDR加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中,LDR最常用的就是读 取CPU 的寄存器值,比如I.MX6UL有个寄存器GPIO1_GDIR,其地址为0X0209C004,我们 现在要读取这个寄存器中的数据, LDR指令使用 1 LDR R0, =0X0209C004 @将寄存器地址0X0209C004加载到R0中,即R0=0X0209C004 2 LDR R1, [R0] @读取地址0X0209C004中的数据到R1寄存器中 上述代码就是读取寄存器GPIO1_GDIR中的值,读取到的寄存器值保存在R1寄存器中, 上面代码中offset是0,也就是没有用到offset。STR指令 LDR 是从存储器读取数据,STR 就是将数据写入到存储器中,同样以 I.MX6UL 寄存器 GPIO1_GDIR为例,现在我们要配置寄存器GPIO1_GDIR的值为0X20000002,示例代码如下: 示例代码7.2.2.2 STR指令使用 1 LDR R0, =0X0209C004 @将寄存器地址0X0209C004加载到R0中,即R0=0X0209C004 2 LDR R1, =0X20000002 @R1保存要写入到寄存器的值,即R1=0X20000002 3 STR R1, [R0] @将R1中的值写入到R0中所保存的地址中 LDR 和 STR 都是按照字进行读取和写入的,也就是操作的32位数据,如果要按照字节、 半字进行操作的话可以在指令“LDR”后面加上B或H,比如按字节操作的指令就是LDRB和 STRB,按半字操作的指令就是LDRH和STRH。
资料摘取正点原子阿尔法开发板开发指南