RISC-V汇编快速入门
本文简单介绍RISC-V的汇编。
当今,强大的编译器将C或者更高级的语言编译成机器码后,其效能损失已经很小了,再加上芯片的性能越来越强,让汇编语言显得可有可无。但对于嵌入式来说至少在下面两种情况还需要汇编:1是启动代码,2是OS的上下文切换。另外在极端情况下使用汇编提高效率也是有必要的,例如芯片内核非常新编译器优化不够好可以在非常清楚CPU的微结构下进行指令集编码提高性能。因此学习一种新的体系结构,了解其汇编语言是非常有必要的。
实例 链接到标题
在将Zephyr开发环境做为RISC-V的实验环境一文中,贴出了一段非常简单的RISC-V汇编,这里进行分析
# __start被放入到.txt.entry段,位于.text的最开始
.section .text.entry
.globl __start
# 上电后ROM从__start开始运行:初始化$sp,栈是负增长,所以sp指向boot_stack_top,然后跳回到__start
__start:
la sp, boot_stack_top
j __start
# 要将stack放到bss后面,这里声明字段 .bss.stack 作为启动时的栈
.section .bss.stack
.global boot_stack
boot_stack:
# 4K 启动栈大小
.space 4096 * 4
.global boot_stack_top
boot_stack_top:
# 栈结尾
上面这段代码中: .section .globl .space叫汇编指示符,是汇编器的命令,用于告诉汇编器代码和数据的位置,指定程序中特定的数据常量。 la, j 叫做汇编指令,用于告诉CPU要执行什么样的动作 __start, boot_stack, boot_statck_top,叫做lable,用于代码或者数据的位置表示
汇编指示符 链接到标题
RISC-V的汇编指示符和作用如下
| 指示符 | 作用 |
|---|---|
| .text | 代码段,之后跟的符号都在.text内 |
| .data | 数据段,之后跟的符号都在.data内 |
| .bss | 未初始化数据段,之后跟的符号都在.bss中 |
| .section .foo | 自定义段,之后跟的符号都在.foo段中,.foo段名可以做修改 |
| .align n | 按2的n次幂字节对齐 |
| .balign n | 按n字节对齐 |
| .globl sym | 声明sym未全局符号,其它文件可以访问 |
| .string “str” | 将字符串str放入内存 |
| .byte b1,…,bn | 在内存中连续存储n个单字节 |
| .half w1,…,wn | 在内存中连续存储n个半字(2字节) |
| .word w1,…,wn | 在内存中连续存储n个字(4字节) |
| .dword w1,…,wn | 在内存中连续存储n个双字(8字节) |
| .float f1,…,fn | 在内存中连续存储n个单精度浮点数 |
| .double d1,…,dn | 在内存中连续存储n个双精度浮点数 |
| .option rvc | 使用压缩指令(risc-v c) |
| .option norvc | 不压缩指令 |
| .option relax | 允许链接器松弛(linker relaxation,链接时多次扫描代码,尽可能将跳转两条指令替换为一条) |
| .option norelax | 不允许链接松弛 |
| .option pic | 与位置无关代码段 |
| .option nopic | 与位置有关代码段 |
| .option push | 将所有.option设置存入栈 |
| .option pop | 从栈中弹出上次存入的.option设置 |
汇编指令 链接到标题
RISC-V指令 链接到标题
RISC-V的汇编器可以直接识别RISC-V指令集中所有的指令,例如在RISC-V指令集体系结构-RV32I指令集概览里面列出来的RV32I。实际读写汇编的时候可以参考riscv-card,https://github.com/jameslzhu/riscv-card 下面摘要了rv32i的card:

RISC-V伪WEI指令 链接到标题
RISC-V的汇编器也可以直接识别RISC-V伪指令。在之前的文章我们曾经提到过RISC-V的指令非常精简,一些功能指令(例如取反)可由其它指令组成,在实际写汇编的RISC-V的汇编器也可以直接识别RISC-V过程中我们要是靠人脑去组合,写代码的WEI效率会很低,因此汇编器提供一组伪指令,在汇编的时候汇编器会将伪指令翻RISC-V的汇编器也可以直接识别RISC-V译为RISC-V的指令组合,RISC-V spec Chatper 25规定的伪指令如下:
第一栏为伪指令,第二栏为基础指令,第三栏说明伪指令的作用。基础指令是RISC-V处理器支持的指令,伪指令由基础指令组成,在汇编的时候由汇编器将伪指令转换为基础指令。
指令速查 链接到标题
虽然RISC-V的汇编指令不多,但能用的场合也不多,少用则易忘。因此我们可以将risc-card和RISC-V spec Chapter 25的伪指令列表打印出来,写汇编或者读汇编代码的时候参考。另外我有将RV32I和伪指令做成tldr文件,大家可以下载安装后直接进行查询, Linux下的安装方法:
cd ~
git clone https://github.com/lgl88911/riscv_tldr.git
sudo apt-get install tldr
cp riscv_tldr/rv32i/* ~/.tldr/tldr/pages/common/
cp riscv_tldr/pseudo/* ~/.tldr/tldr/pages/common/
使用和tldr一样
tldr met
如果没有查找到指令,请尝试缩短查找词,只找有意义的关键词例如
tldr addi 找不到就用 tldr add
参考 链接到标题
http://crva.io/documents/RISC-V-Reader-Chinese-v2p1.pdf https://github.com/riscv/riscv-isa-manual/releases

