当今,强大的编译器将C或者更高级的语言编译成机器码后,其效能损失已经很小了,再加上芯片的性能越来越强,让汇编语言显得可有可无。但对于嵌入式来说至少在下面两种情况还需要汇编:1是启动代码,2是OS的上下文切换。另外在极端情况下使用汇编提高效率也是有必要的,例如芯片内核非常新编译器优化不够好可以在非常清楚CPU的微结构下进行指令集编码提高性能。因此学习一种新的体系结构,了解其汇编语言是非常有必要的。
实例
在将Zephyr开发环境做为RISC-V的实验环境一文中,贴出了一段非常简单的RISC-V汇编,这里进行分析
1 | # __start被放入到.txt.entry段,位于.text的最开始 |
上面这段代码中:
.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下的安装方法:1
2
3
4
5cd ~
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