一、GNU汇编语法简介

GNU汇编语法目前可以适用于所有架构,并不仅仅局限于ARM。GNU汇编指令由一套制定好规则的语句构成,其中每条语句都可以分解为如下三部分:

Label:Command @Comment
  1. Label:标签,用于表示位置(地址等)。部分汇编指令之前会存在标签,在这种情况下,允许使用标签来代表汇编指令的地址。注意:任何以冒号“:”结尾的字段都会被识别为标签。
  2. Command:指令,可以是汇编指令或伪指令。
  3. @:注释符号,其后内容作为标注,不参与编译,与c语言中的“//”、“/*”、“*/”等注释符作用一致。注意:在GNU汇编文件中,也可以使用“/*”、“*/”作注释符替换“@”使用。
  4. Comment:注释内容。

范例代码如下:

funckey:
    MOV R0,#0x01

注意:在ARM的汇编语言中,任何的汇编指令、伪指令、伪操作、寄存器等描述都可以全部使用大写或者全部使用小写,但不允许大小写混合使用的形式。

1.1伪操作

​伪操作与汇编指令、宏指令共同构成汇编语言程序,伪操作并不由计算机在程序运行期间执行,而是在汇编程序对源程序汇编期间由汇编程序处理的操作。伪操作可以完成多种已经定义好的功能,例如数据定义、分配存储区、指示程序结束等功能。

  1. .section:定义段名
  2. .global:定义全局标签
  3. .byte:定义单字节数据
  4. .short:定义双字节数据
  5. .long:定义四字节数据
  6. .equ:赋值,举例:.equ var,0x01
  7. .align:数据字节对齐
  8. .end:表示源程序文件结束
  9. .type:定义标签的类

1.2定义函数

​使用.type进行定义,结构形式如下:

.type func_name,@func_start
func_name:
    $operation
ret
  1. 行1:
    1. .type:定义一个标签,为函数类
    2. func_name:函数名称
    3. @func_start:表示函数开始
  2. 行2:
    1. func_name:函数标签声明
  3. 行3:
    1. $operation:函数具体操作
  4. 行4:
    1. ret:函数返回,同c语言中函数末尾的“return”

范例函数如下:

.type move_reg,@function
move_reg:
    mov R0,R1 @将寄存器R1存储的数据赋值给R0,同c语言中的"R0=R1;"
ret

二、汇编指令

介绍几种常用的汇编指令。

2.1MOV

用于寄存器数据写入。

范例如下:

MOV R0,R1       @将R1中的数据写入R0
MOV R0,#0x01    @将0x01(立即数)写入R0

2.2MRS

读取特殊寄存器(CPSR,SPSR)中的数据并传递给通用寄存器。

范例如下:

MRS R0,SPSR_xxx    @将SPSR_xxx中的数据写入进R0寄存器,xxx是芯片的工作模式

2.3MSR

将通用寄存器中的数据写入特殊寄存器中。

范例如下:

MSR CPSR,R0    @将R0中的数据写入进特殊寄存器CPSR中

2.4LDR

将一个32位数据写入目标寄存器中,数据一般使用寄存器地址,通过这种方式访问寄存器地址内的数据,因此这条指令的使用十分灵活。

范例如下:

LDR R0,[R1]    @将R1中的32位数据视作寄存器地址,将此地址中的数据写入进R0
LDR R0,[R1,R2]    @将R1与R2中的数据相加,其中的32位数据视作寄存器地址,将此地址中的数据写入进R0
LDR R0,[R1,#0x01]    @将R1中的数据加0x01后,其中的32位数据视作寄存器地址,将此地址中的数据写入进R0
LDR R0,=0x20000c00    @将寄存器地址为0x20000c00中的数据写入进R0

注意:若LDR的最后的地址数据是立即数且不超过8位,那么在进行汇编时会将LDR指令转换为MOV指令,范例如下:

LDR R0,=0xff

汇编后指令如下:

MOV R0,0xFF

此时并不是立即数0xff,而是间接寻址将地址为0xff中的数据写入进R0。

2.5STR

将数据写入寄存器地址中。

范例如下:

STR R0,[R1]    @将R1寄存器内的32位数据视作寄存器地址,将R0中的数据写入到该地址中

2.6B

无条件跳转指令,如其后跟实际值则视为PC指针的相对偏移量,而非绝对指针。一般其后用于跟跳转地址的标签。

范例如下:

B label1:

2.7BL

有数据保护的跳转。在跳转前会先将当前PC指针保存在寄存器R14中,可以通过对PC指针的重加载实现返回原指令,即实现了函数调用与返回的操作。

范例如下:

BL label2:

2.8BLX

在BL的基础上,增加跳转后将处理器工作状态由ARM切换到Thumb。

范例如下:

BLX label3:

2.9BX

跳转到该地址,该地址存放的指令既可以是ARM也可以是Thumb指令。

范例如下:

BX R0    @PC指针跳转到R0寄存器中的数据代表的地址,利用R0寄存器中的数据的最低位来设置处理器工作状态

当R0的最低位数据为0时,处理器使用ARM状态工作。

当R0的最低位数据为1时,处理器使用Thumb状态工作。

三、总结

汇编指令在芯片启动阶段一般用于上电后的引导,将PC地址指向程序main函数入口即可。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐