文章目录
- 一、基础概念
- 指令集---指示计算机执行某种操作的命令,是计算机运行的最小功能单位。
- 复杂指令集CISC(如x86)和精简指令集RISC(如arm、riscV)---两种指令集的优化设计方向
- RiscV---一个基于精简指令集RISC原则的开源指令集架构ISA
- 二、RiscV汇编指令集介绍
- RiscV的基础指令与扩展指令分类
- RiscV指令根据格式特点六种类型---R/I/S/B/U/J
- RiscV的寄存器描述---32个通用寄存器和一个PC寄存器
- 指令介绍1:算数运算---add/sub/addi/mul/div/rem
- 指令介绍2:逻辑运算---and/andi/or/ori/xor/xori
- 指令介绍3:位移运算---sll/slli/srl/srli/sra/srai
- 指令介绍4:数据传输---lb/lh/lw/lbu/lhu/lwu/sb/sh/sw
- 指令介绍5:比较指令---slt/slti/sltu/sltiu
- 指令介绍6:条件分支指令---beq/bne/blt/bge
- 指令介绍7:无条件跳转指令---j/jal/jalr
- 参考
一、基础概念
指令集—指示计算机执行某种操作的命令,是计算机运行的最小功能单位。
指令集:CPU中用来计算和控制计算机系统的一套指令的集合,而每一种新型的CPU在设计时就规定了一系列与其他硬件电路相配合的指令系统。而指令集的先进与否,也关系到CPU的性能发挥,它也是CPU性能体现的一个重要标志。
常见指令集,Intel有x86,x86-64,MMX,SSE等 和针对64位桌面处理器的EM-64T。AMD主要是3D-Now!指令集。
复杂指令集CISC(如x86)和精简指令集RISC(如arm、riscV)—两种指令集的优化设计方向
指令集一般分为两大体系结构,即复杂指令集CISC(Complex lnstruction Set Computer)和精简指令集RISC(Reduced Instruction Set Computer)。最初人们采用的优化方法是通过设置一些功能复杂的指令,把一些原来由软件实现的、常用的功能改用硬件的指令系统实现,以此来提高计算机的执行速度,这就是CISC,倾向于用一条复杂指令执行更多特定任务。另一种优化方法是在20世纪80年代才发展起来的,其基本思想是尽量简化计算机指令功能,只保留那些功能简单、能在一个节拍内执行完成的指令,而把较复杂的功能用一段子程序来实现,即RISC。
RiscV—一个基于精简指令集RISC原则的开源指令集架构ISA
RISC-V(读作“RISC-FIVE”)是基于精简指令集计算(RISC)原理建立的开放指令集架构(ISA),V表示为第五代RISC(精简指令集计算机),表示此前已经有四代RISC处理器原型芯片。每一代RISC处理器都是在同一人带领下完成,那就是加州大学伯克利分校的David A. Patterson教授。与大多数ISA相反,RISC-V ISA可以免费地用于所有希望的设备中,允许任何人设计、制造和销售RISC-V芯片和软件。
开源采用宽松的BSD协议,企业完全自由免费使用,同时也容许企业添加自有指令集拓展而不必开放共享以实现差异化发展。
二、RiscV汇编指令集介绍
RiscV的基础指令与扩展指令分类
RiscV的基础指令:根据寄存器位宽和地址空间不同,分为32、64、128位三种不同整数指令集(用I表示)。整数指令集包括算术、逻辑、分支、访存(访问内存)指令等,已经可以实现一个完整的软件栈。
RiscV的扩展指令:一些CPU有更多的功能要求,如 M:乘除法、取模求余指令;F:单精度浮点指令;D:双精度浮点指令Q:四倍浮点指令;A:原子操作指令,例如常见的cas(compare and swap)指令;C:压缩指令,主要用于改善程序大小;
RiscV指令根据格式特点六种类型—R/I/S/B/U/J
RISC-V指令根据格式特点可以分为六种类型(Type):
R Type:用于寄存器——寄存器之间的操作 (Register)
I Type:短立即数及内存访问操作(Immediate)
S Type:用于内存store操作 (Store)
B Type:用于条件跳转操作 (Branch)
U Type:用于长立即数操作
J Type:用于无条件跳转操作 (Jump)
上图opcode表示指令操作码,通过这7位就知道这是一个什么指令;rs1、rs2、rd分别表示源寄存器1、2以及目的寄存器;imm代表立即数;funct3、funct7代表指令对应的功能,这在之后会讲。
RiscV的寄存器描述—32个通用寄存器和一个PC寄存器
RISC-V定义了32个通用寄存器和一个PC寄存器,32个通用寄存器如下:
指令介绍1:算数运算—add/sub/addi/mul/div/rem
add rd,rs1,rs2:将寄存器rs1与rs2的值相加并写入寄存器rd。
sub rd,rs1,rs2:将寄存器rs1与rs2的值相减并写入寄存器rd。
addi rd,rs1,imm:将寄存器rs1的值与立即数imm相加并存入寄存器rd。
mul rd,rs1,rs2:将寄存器rs1与rs2的值相乘并写入寄存器rd。
div rd,rs1,rs2:将寄存器rs1除以寄存器rs2的值,向零舍入并写入寄存器rd。
rem rd,rs1,rs2:将寄存器rs1模寄存器rs2的值并写入寄存器rd。
指令介绍2:逻辑运算—and/andi/or/ori/xor/xori
and rd,rs1,rs2:将寄存器rs1与rs2的值按位与并写入寄存器rd。
andi rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位与并写入寄存器rd。
or rd,rs1,rs2:将寄存器rs1与rs2的值按位或并写入寄存器rd。
ori rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位或并写入寄存器rd。
xor rd,rs1,rs2:将寄存器rs1与rs2的值按位异或并写入寄存器rd。
xori rd,rs1,imm:将寄存器rs1的值与立即数imm的值按位异或并写入寄存器rd。
指令介绍3:位移运算—sll/slli/srl/srli/sra/srai
sll rd,rs1,rs2:将寄存器rs1的值左移寄存器rs2的值这么多位,并写入寄存器rd。
slli rd,rs1,imm:将寄存器rs1的值左移立即数imm的值这么多位,并写入寄存器rd。
srl rd,rs1,rs2:将寄存器rs1的值逻辑右移寄存器rs2的值这么多位,并写入寄存器rd。
srli rd,rs1,imm:将寄存器rs1的值逻辑右移立即数imm的值这么多位,并写入寄存器rd。
sra rd,rs1,rs2:将寄存器rs1的值算数右移寄存器rs2的值这么多位,并写入寄存器rd。
srai rd,rs1,imm:将寄存器rs1的值算数右移立即数imm的值这么多位,并写入寄存器rd。
左移会在右边补0,逻辑右移会在最高位添0,算数右移在最高位添加符号位。
指令介绍4:数据传输—lb/lh/lw/lbu/lhu/lwu/sb/sh/sw
在RISC-V中1word=4Bytes=32bits。l是load的首字母,即加载数据;s是store的缩写,即存储数据。b,h,w分别是byte,half word,word的首字母,除此之外还有存取双字的d,即double word。
lb rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个字节,符号扩展后存入rd
lh rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读半个字,符号扩展后存入rd
lw rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个字,符号扩展后存入rd
lbu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个无符号的字节,零扩展后存入rd
lhu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读半个无符号的字,零扩展后存入rd
lwu rd,offset(rs1):从地址为寄存器rs1的值加offset的主存中读一个无符号的字,零扩展后存入rd
sb rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的8位
sh rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的16位
sw rs1,offset(rs2):把寄存器rs1的值存入地址为寄存器rs2的值加offset的主存中,保留最右端的32位
指令介绍5:比较指令—slt/slti/sltu/sltiu
有符号数:
slt rd,rs1,rs2:若rs1的值小于rs1的值,rd置为1,否则置为0
slti rd,rs1,imm:若rs1的值小于立即数imm,rd置为1,否则置为0
无符号数:
sltu rd,rs1,rs2:若rs1的值小于rs1的值,rd置为1,否则置为0
sltiu rd,rs1,imm:若rs1的值小于立即数imm,rd置为1,否则置为0
指令介绍6:条件分支指令—beq/bne/blt/bge
beq rs1,rs2,lable:若rs1的值等于rs2的值,程序跳转到lable处继续执行
bne rs1,rs2,lable:若rs1的值不等于rs2的值,程序跳转到lable处继续执行
blt rs1,rs2,lable:若rs1的值小于rs2的值,程序跳转到lable处继续执行
bge rs1,rs2,lable:若rs1的值大于等于rs2的值,程序跳转到lable处继续执行
指令介绍7:无条件跳转指令—j/jal/jalr
j label:程序直接跳转到lable处继续执行
jal rd,label:用于调用函数,把下一条指令的地址保存在rd中(通常用x1),然后跳转到label处继续执行
jalr rd,offset(rs):可用于函数返回,把下一条指令的地址存到rd中,然后跳转到rs+offset地址处的指令继续执行。若rd=x0就是单纯的跳转(x0不能被修改)
参考
risc-v 指令集手册:https://max.book118.com/html/2022/0614/5200103013004242.shtm
循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰:https://www.bilibili.com/video/BV1Q5411w7z5/?spm_id_from=333.788.recommend_more_video.0&vd_source=e5379ad2570e86814925715ab989c6fb
riscv相关github:https://github.com/riscv/riscv-isa-manual
计基2—RISCV指令集介绍与汇编:https://blog.csdn.net/ll15982534415/article/details/126574495