跳到主要内容

risc-v汇编语言

1. 汇编语言概念

汇编语言(Assembly Language)是一种“低级语言”,通常具有难读难写难移植的缺点,

但汇编语言是直接在硬件之上工作的编程语言,具有灵活强大的优点。

汇编语言通常应用在如下场景:

  • 需要直接访问底层硬件的场景,如底层驱动、引导程序
  • 需要对代码执行性能极致优化的场景,如高性能算法库、OS的上下文切换

2. 汇编语言语法介绍

常见的汇编语法版本有GNU和Intel等,因为RISC-V采用GNU Compiler Collection(GCC)编译,本小节将简要介绍GNU版本的汇编语法,感兴趣的读者可以自行查阅GUN汇编语法手册深入了解。

2.1 汇编语句格式

一条典型的RISC-V 汇编语句由3个部分组成:

[label:] [operation] [comment]  # []内的部分可以省略
  • label(标签):GNU汇编中,任何以冒号结尾的标识符都被认为是一个标签,而不一定非要在一行的开始。
  • operation(操作码):操作码部分有以下多种类型
    • instruction(指令):直接对应二进制机器指令的字符串
    • pseudo-instruction(伪指令):一条伪指令在汇编时会生成多条实际的汇编指令,使用伪指令可提高代码的编写效率
    • directive(指示/ 伪操作):通过类似指令的形式(以“.”开头),通知汇编器如何控制代码的产生等,不对应具体的指令
  • comment(注释):代码注释,以"#"或“;”开始到当前行结束

2.2 label标签详解

标签的本质是代表它所在的地址,因此标签可以当作变量函数来使用。常见的标签分为文本标签数字标签

标签只能由a~z,A~Z,0~9,“.”,“_”这些点、字母、数字、下划线等字符组成,除数字标签外,不能以数字开头。

(1)文件标签在程序文件中是全局可见的,所以在定义是不可重复。文本标签通常被作为分支或跳转指令的目标地址,如:

loop:  # 定义一个loop标签
...
j loop # 跳转到loop标签处

(2)数字标签属于一种局部标签,可重复定义,通常用0~9之间的数字定义。在被引用时,数字标签通常需要带上字母“f”或“b”字母后缀,

f:指示编译器向前搜索,即代码行数增加的方向

b:指示编译器向后搜索,即代码行数减少的方向

如:

    j 1f # 向前寻找并跳转至第一个数字为1的标签处
...
1: #数字标签1
...
j 1b # 向后寻找并跳转至第一个数字为1的标签处

2.3 常用伪操作

伪操作通常以“.”开头,在汇编程序中的作用是指导汇编器处理汇编程序的行为,仅在汇编过程中起作用。

(1).file filename

.file 伪操作,指示汇编器该汇编程序的逻辑文件名

(2).global symbol_name或.globl symbol_name

.global和.globl伪操作,用于定义一个全局的符号,使得其他文件也可调用该symbol_name

(3).local symbol_name

.local伪操作,用于定义局部符号,使得该symbol_name对其他文件不可见

(4).weak symbol_name

在汇编程序中,符号的默认属性为强(strong),.weak伪操作用于设置符号的属性为弱(weak)

(5).type name,type description

.type伪操作用于定义符号的类型。如“.type symbol,@function”表示将名为symbol的符号定义为一个函数(function)

(6).align integer

.align伪操作,用于定义接下来的地址按照2的integer次方对齐。如“.align 2”表示按照4字节对齐。

(7).section name [,subsection]

.section伪操作指示将接下来的代码汇编链接到名为name的段中(Section),还可以指定可选的子段(Subsection),常见的段有.text、.data、.bss.

  • “.section .text” 将接下来的代码汇编链接到.text段中
  • “.section .data” 将接下来的代码汇编链接到.data段中
  • “.section .bss” 将接下来的代码汇编链接到.bss段中

(8).macro和.endm宏定义

.macro和.endm用于定义宏,使用方式如下:

.macro mutil_add a,b,c  #定义一个名为mutil_add的宏,参数为a、b、c
add t0,a,b #将a和b相加,值写入t0寄存器
add c,c,t0 #加t0和c相加,值写入c
.endm #宏定义结束

mutil_add x1,x2,x3 #调用mutil_add