准备写几篇学习笔记来讲述RISC-V汇编。
1 指令集架构
指令集架构(Instruction Set Architecture,简称ISA)是一种定义处理器体系结构的规范。定义了处理器能够执行的指令集、寄存器、编码格式、内存访问方式、中断、异常处理等细节。
- 指令集:包含数条指令,每条指令都代表一个特定的操作,如加法、乘法、内存读写等;
- 寄存器:寄存器用于暂存指令或数据;
- 编码格式:表示如何将指令操作、寄存器、立即数等信息组织成具体的二进制指令;
- 内存访问方式:指令集架构规定了处理器如何与内存进行交互,包括地址寻址方式、读写操作等;
- 特权级别:指令集架构可能定义了多个特权级别,用于区分不同的操作权限,例如用户态和内核态;
- 扩展指令集:一些指令集架构支持扩展指令集,可以根据特定需求添加新的指令,以提高特定应用程序性能。
常见的指令集架构包括x86、ARM、RISC-V、LoongArch等。不同的处理器可能采用不同的指令集架构,因此编写的软件必须符合指令集规范才能在对应的处理器上运行。指令集架构的选择对于处理器性能、功耗、兼容性等方面都有影响,因此在设计处理器系统时需要考虑各种因素来选择适合的指令集架构。
2 复杂指令集与精简指令集
指令集架构可以简单的分为:
- 复杂指令集(Complex Instruction Set Computer,CISC)
- 精简指令集(Reduced Instruction Set Computer,RISC)。
最早出现的是CISC,既有简单指令也有复杂指令,人们发现常用的指令只占20%(正如常用的汉字只有2,3千个一样,符合二八法则),这20%的指令都是简单指令,并且通过简单指令组合可以实现复杂指令相同的功能,所以没必要花太多时间去实现复杂指令,这样就诞生了RISC指令。
RISC指令设计理念是:常用的指令做得快,少用的指令只要功能正确就行,即RISC只包含常用的简单指令,对于不常用复杂的操作,则通过执行几条简单指令组合来达到相同效果。
CISC 与 RISC的区别如下:
VS | 复杂指令集(CISC) | 精简指令集(RISC) |
---|---|---|
指令数量 | 多 | 少 |
指令系统复杂度 | 复杂 | 简单 |
指令长度 | 变长,不固定 | 等长,固定 |
寻址方式 | 多 | 少 |
指令格式 | 多 | 少且规整 |
各指令使用频率 | 相差很大 | 相差不大 |
指令执行时间 | 相差很大 | 相差不大 |
指令周期 | 多周期为主 | 单周期为主(流水线技术,大部分指令在一个机器周期完成) |
cpu寄存器数量 | 少 | 多(增加寄存器,以减少访存) |
指令并行性 | 低 | 高 |
可访存指令 | 不加限制 | 只有load/store等访存指令才能访问内存(减少了访存周期) |
优化编译实现 | 很难 | 较容易(依靠编译程序的优化来更有效的支持高级语言) |
代表架构 | x86 | ARM,MIPS,PowerPC,LoongArch,RISC-V等 |
RISC精简指令不仅有利于硬件的高效实现,还有利于通过流水线、多发射、乱序执行等技术来提高效率,所以,像x86这种CISC架构,也在不断趋于RISC风格,即x86会把一些比较复杂的指令预译码成多笔简单指令操作
简单理解:CISC = 预译码 + RISC,以便更有效的使用流水线等技术,不由的感叹一下,CISC负重前行,需要考虑向前兼容,不然直接投奔RISC更简单一些。
RISC-V是第5代精简指令集,属于RISC的一种实现。
3 什么场合需要使用RISC-V汇编指令?
汇编指令难写难读,但在一些场合我们很难完全避免不使用汇编指令,如下是使用汇编指令的一些场合:
使用场合 | 具体示例 |
---|---|
完成高级语言(C/C++等)无法实现的功能 | 在进入C/C++语言main函数之前需要准备函数栈、初始化变量等,这些只能使用汇编; OS的进程切换,需要直接操作寄存器,只能使用汇编语言; 获取当前PC值等需要直接操作寄存器的操作,只能用汇编语言 |
需要严格限制二进制文件的大小 | 嵌入式设备(如电话、打印机、门禁设备等)内存要求较严格,如果使用高级语言编写,经过编译后,可能存在大量的函数调用开销,动态库加载等,如果直接使用汇编语言,可以编写脱离库(libc库)的嵌入式程序,这种内存占用肯定是最小的。 |
性能分析与优化 | 比如优化库函数:memset、memcpy等; 使用SIMD指令(risc-v中的pv扩展等)对算法进行优化 |
定位分析问题 | 有些问题可能与编译器优化有关,需要对照反汇编来分析 |
参考:
- 指令集架构知识汇总 - 知乎 (zhihu.com)
- 计组 | RISC与CISC
- 《汇编语言编程基础 基于LoongArch》