ARM汇编基础知识

1、前言

汇编语言是一种低级编程语言,通常是一对一的汇编语言指令(助记符)与由核心执行的实际二进制操作码之间的关系,在高度优化的情况下,汇编代码可能会很有用,在编写编译器或者无法直接使用底层功能的情况下,在C中添加汇编代码是必需的,部分SoC的启动代码、设备驱动程序或者操作系统开发也可能需要汇编代码,在进行嵌入式Linux开发的时候需要掌握一定的ARM汇编知识,对于ARM Cortex-A架构的芯片,系统上电后,C语言运行环境还没有设置好,因此肯定是不能直接运行C代码的,所以必须先用汇编语言设置好C运行环境,初始化好SP指针等,使用汇编语言设置好C运行环境后,才能开始运行C语言代码。

2、GNU汇编语法

对于ARM架构下的汇编语言,编译使用的是gcc交叉编译工具链,汇编代码要符合GNU汇编语法,GNU汇编语法适用于所有的架构,并不是ARM独享的,GNU汇编由一系列的语句组成,每行一条语句,每条语句有3个可选部分,如下所示:

label:    instruction    @comment

label:label就是标号,表示地址的位置,有一些指令的前面可能会存在标号,然后通过这个标号就可以得到指令的地址,标号也可以用来表示数据的地址,任何以冒号":"结尾的标识符都会被认为是一个标号label;

instruction:汇编指令或者伪指令;

@:表示后面的是注释,和C语言的注释一样,同样也可以使用"/**/"进行注释;

comment:要注释的内容。

例如,下面的ARM汇编代码:

Code:
    MOVS    R0,#0x14    @设置R0=0x14

上面的举例代码中,"Code:"就是标号,"MOVS  R0,#0x14"就是指令,"@"后面就是注释的内容。

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

另外,用户还可以使用".section"伪操作来定义一个段,汇编系统中预定义了一些段名,如下:

.test:表示代码段;

.data:表示初始化的数据段;

.bss:表示未初始化的数据段;

.rodata:表示只读数据段。

用户可以使用".section"来定义一个段,每个段以段名开始,以下一个段名或者文件结束,例如:

.section    .mysection    @定义一个.mysection段

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

.global _start
_start:
    MOVS    R0,#0X14    @R0=0x14

在上面的代码中,".global"就是伪操作,表示"_start"是一个全局标号,类似C语言定义的全局变量一样,ARM汇编中常用的伪操作有如下:

.byte:定义单字节数据,例如:.byte 0x14;

.short:定义双字节数据,例如:.short 0x1000;

.long:定义四字节数据,例如:.long 0x10001000;

.equ:赋值语句,其格式为:.equ 变量名,表达式,例如:.equ cnt,0x14,表示cnt=0x14;

.align:表示数据字节对齐,例如:.align 4,表示4字节对齐;

.end:表示汇编源文件结束;

.global:定义一个全局标号。

GNU汇编同样也支持函数,函数的格式如下所示:

函数名:
    函数体
    返回语句

GNU汇编函数中的返回语句并不是必须的。

3、ARM v7-A常用汇编指令

4、小结

猜你喜欢

转载自www.cnblogs.com/Cqlismy/p/12384882.html