RISC-V汇编学习(三)—— RV指令集
有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识,本节开始介绍RISC-V指令集和伪指令。
前面说了RISC-V的模块化特点,是以RV32I为作为ISA的核心模块,其他都是要基于此为基础,可以这样认为:RISC-V ISA = 基本整数指令集+多个可选扩展指令集
;另外RISC-V的ISA spec上是从指令类型和指令格式开始介绍指令的;但从一个嵌入式软件开发人员的角度来说,不是特别适合学习和记忆,所以我这里简单罗列下,不多讲解,感兴趣可以参考spec。
1 指令类型
1.1 组成格式
所有RISC-V指令都是固定长度的32位,这有助于简化指令解码过程。每个指令都由以下几个关键部分组成:
- opcode:这是7位的操作码,用来标识指令的基本类型。
- funct3:这是一个3位的功能码,与opcode一起使用以进一步细化指令的类别。
- funct7:某些指令使用额外的7位功能码来更精确地定义指令的行为。
- rs1/rs2/rd:这些是5位的寄存器地址,分别代表源寄存器1、源寄存器2和目的寄存器。
- imm:立即数字段,其大小和位置根据指令类型的不同而变化。
1.2 类型
RISC-V定义了几种基本的指令格式,每一种都针对特定类型的运算或操作。这些格式包括:R型、I型、S型、B型、U型、J型。
-
R型(Register)
用于寄存器间的算术/逻辑运算(如ADD x1, x2, x3)
字段:opcode确定操作类型,funct3和funct7进一步指定具体操作(如区分ADD与SUB) -
I型(Immediate)
用于立即数操作(如ADDI x1, x2, 42)或加载指令(如LW x1, 100(x2))
立即数:12位符号扩展,直接嵌入指令中 -
S型(Store)
存储数据到内存(如SW x3, 200(x4))
立即数:12位拆分为imm[11:5]和imm[4:0],组合后作为偏移地址。 -
B型(Branch)
条件分支(如BEQ x1, x2, label)
立即数:13位(符号扩展后左移1位),拆分为imm[12|10:5|4:1|11],支持更大跳转范围 -
U型(Upper Immediate)
加载高20位立即数(如LUI x1, 0x12345)或构造地址(如AUIPC)
立即数:20位直接嵌入高位,低12位由后续指令补充 -
J型(Jump)
长距离无条件跳转(如JAL x1, label)
立即数:20位符号扩展后左移1位,支持±1MB跳转范围
但在实际应用中,我们也很难记住这么汇编指令机器码,一般情况下也不会有错,具体可以参考spec。
2 指令命名
下图是RV32I基础指令集的⼀⻚图形表示,将有下划线的字⺟从左到右连接起来,即可组成完整的RV32I指令集。集合标志{}内列举了指令的所有变体,变体⽤加下划线的字⺟或下划线字符_表示,特别的,下划线字符_表示对于此指令变体不需⽤字符表示
以slt指令为例,如下示意图:大括号{ }内列举了每组指令的所有变体,这些变体通过带下滑线的字母(单独的下划线_表示空字段),从左到右连接带下滑线的字母即可组成完整的指令集,比如slt意思是set less than,相当于是一种缩写,完整语句方便我们快速清晰的理解指令的作用。
上图可以表示:slt、slti、sltu、sltiu 这4条RVI指令。
下面将列举以下RISC-V指令集:
- RVI(包括RV32I与RV64I)
- RVM(包括RV32M与RV64M)
- RVFD(包括RV32FD与RV64FD)
- RVA(包括RV32A与RV64A)
3 RVI指令集
RVI是 RISC-V 指令集架构的基础部分,它定义了32位整数运算的核心指令集。RVI 包括 RV32I(32位整数指令集)和 RV64I(64位整数指令集),它们为处理器提供了执行基本计算任务的能力;包括:内存操作指令、逻辑指令、分支和跳转指令、算术指令等等,下面就一一列举。
3.1 内存操作指令
在RISC-V中,内存操作主要通过加载(Load)和存储(Store)两类指令来实现。这些指令允许程序从内存读取数据到寄存器(Load),或将寄存器中的数据写入内存(Store)
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
LB | lb rd, offset(rs1) | 加载字节(符号扩展) | rd = SignExt(Mem[rs1 + offset][7:0]) | RV32I / RV64I |
LBU | lbu rd, offset(rs1) | 加载字节(无符号扩展) | rd = ZeroExt(Mem[rs1 + offset][7:0]) | RV32I / RV64I |
LH | lh rd, offset(rs1) | 加载半字(符号扩展) | rd = SignExt(Mem[rs1 + offset][15:0]) | RV32I / RV64I |
LHU | lhu rd, offset(rs1) | 加载半字(无符号扩展) | rd = ZeroExt(Mem[rs1 + offset][15:0]) | RV32I / RV64I |
LW | lw rd, offset(rs1) | 加载字(RV32I:32位;RV64I:符号扩展至64位) | RV32I: rd = Mem[rs1 + offset][31:0] RV64I: rd = SignExt(Mem[rs1 + offset][31:0]) | RV32I / RV64I |
LWU | lwu rd, offset(rs1) | 加载字(无符号扩展至64位) | rd = ZeroExt(Mem[rs1 + offset][31:0]) | RV64I |
LD | ld rd, offset(rs1) | 加载双字(64位) | rd = Mem[rs1 + offset][63:0] | RV64I |
SB | sb rs2, offset(rs1) | 存储字节 | Mem[rs1 + offset] = rs2[7:0] | RV32I / RV64I |
SH | sh rs2, offset(rs1) | 存储半字 | Mem[rs1 + offset] = rs2[15:0] | RV32I / RV64I |
SW | sw rs2, offset(rs1) | 存储字 | Mem[rs1 + offset] = rs2[31:0] | RV32I / RV64I |
SD | sd rs2, offset(rs1) | 存储双字 | Mem[rs1 + offset] = rs2[63:0] | RV64I |
3.2 算术指令
算术指令狭义定义:仅包含加法、减法及其直接相关的操作,用于寄存器或寄存器与立即数之间的数值运算。
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
基础加减指令 | ||||
ADD | add rd, rs1, rs2 | 加法(忽略溢出) | rd = rs1 + rs2 | RV32I / RV64I |
SUB | sub rd, rs1, rs2 | 减法(忽略溢出) | rd = rs1 - rs2 | RV32I / RV64I |
ADDI | addi rd, rs1, imm | 立即数加法(符号扩展立即数) | rd = rs1 + SignExt(imm) | RV32I / RV64I |
RV64I 扩展加减指令 | ||||
ADDIW | addiw rd, rs1, imm | 立即数加法(32位,符号扩展至64位) | rd = SignExt((rs1 + SignExt(imm))[31:0]) | RV64I |
ADDW | addw rd, rs1, rs2 | 加法(32位,符号扩展至64位) | rd = SignExt((rs1 + rs2)[31:0]) | RV64I |
SUBW | subw rd, rs1, rs2 | 减法(32位,符号扩展至64位) | rd = SignExt((rs1 - rs2)[31:0]) | RV64I |
高位立即数构建指令 | ||||
LUI | lui rd, imm | 加载高位立即数(imm[31:12]) | rd = imm << 12 | RV32I / RV64I |
AUIPC | auipc rd, imm | 将高位立即数与 PC 相加 | rd = PC + (imm << 12) | RV32I / RV64I |
伪指令表格:
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
寄存器操作 | ||||
MV | mv rd, rs | 寄存器间移动值 | addi rd, rs, 0 | RV32I / RV64I |
NEG | neg rd, rs | 取负值(rd = -rs) | sub rd, x0, rs | RV32I / RV64I |
NEGW | negw rd, rs | 取负值(32位操作,符号扩展) | subw rd, x0, rs | RV64I |
立即数操作 | ||||
LI | li rd, imm | 加载任意立即数到寄存器 | 若 imm 在 12 位有符号范围内:addi rd, x0, imm 否则: lui rd, imm[31:12] + addi rd, rd, imm[11:0] | RV32I / RV64I |
地址加载 | ||||
LA | la rd, symbol | 加载绝对地址(链接时解析) | auipc rd, offset_hi + addi rd, rd, offset_lo 或 lui rd, offset_hi + addi rd, rd, offset_lo | RV32I / RV64I |
LLA | lla rd, symbol | 加载本地地址(PC相对,位置无关) | auipc rd, offset_hi + addi rd, rd, offset_lo | RV32I / RV64I |
符号扩展 | ||||
SEXT.W | sext.w rd, rs | 将低32位符号扩展至64位(RV64I) | addiw rd, rs, 0 | RV64I |
空操作 | ||||
NOP | nop | 空操作(无实际效果) | addi x0, x0, 0 | RV32I / RV64I |
3.3 移位指令
移位指令用于对寄存器中的数据进行位级左移或右移,分为以下两类:
-
- 寄存器移位:移位位数由另一个寄存器的低 5 位(RV32I)或低 6 位(RV64I)指定。
-
- 立即数移位:移位位数由指令中的立即数字段直接指定。
- 立即数移位:移位位数由指令中的立即数字段直接指定。
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
逻辑左移 | ||||
SLL | sll rd, rs1, rs2 | 逻辑左移(低位补零) | rd = rs1 << (rs2[4:0]) (RV32I,取低5位)rd = rs1 << (rs2[5:0]) (RV64I,取低6位) | RV32I / RV64I |
SLLI | slli rd, rs1, shamt | 立即数逻辑左移 | rd = rs1 << shamt (shamt范围:RV32I为 0–31,RV64I为 0–63) | RV32I / RV64I |
SLLW | sllw rd, rs1, rs2 | 32位逻辑左移(RV64I,低32位操作) | rd = SignExt((rs1[31:0] << rs2[4:0])) | RV64I |
SLLIW | slliw rd, rs1, shamt | 32位立即数逻辑左移(RV64I) | rd = SignExt((rs1[31:0] << shamt)[31:0]) (shamt范围:0–31) | RV64I |
逻辑右移 | ||||
SRL | srl rd, rs1, rs2 | 逻辑右移(高位补零) | rd = rs1 >> (rs2[4:0]) (RV32I)rd = rs1 >> (rs2[5:0]) (RV64I) | RV32I / RV64I |
SRLI | srli rd, rs1, shamt | 立即数逻辑右移 | rd = rs1 >> shamt | RV32I / RV64I |
SRLW | srlw rd, rs1, rs2 | 32位逻辑右移(RV64I,低32位操作) | rd = SignExt((rs1[31:0] >> rs2[4:0])) | RV64I |
SRLIW | srliw rd, rs1, shamt | 32位立即数逻辑右移(RV64I) | rd = SignExt((rs1[31:0] >> shamt)[31:0]) (shamt范围:0–31) | RV64I |
算术右移 | ||||
SRA | sra rd, rs1, rs2 | 算术右移(高位补符号位) | rd = rs1 >>> (rs2[4:0]) (RV32I)rd = rs1 >>> (rs2[5:0]) (RV64I) | RV32I / RV64I |
SRAI | srai rd, rs1, shamt | 立即数算术右移 | rd = rs1 >>> shamt | RV32I / RV64I |
SRAW | sraw rd, rs1, rs2 | 32位算术右移(RV64I,低32位操作) | rd = SignExt((rs1[31:0] >>> rs2[4:0])) | RV64I |
SRAIW | sraiw rd, rs1, shamt | 32位立即数算术右移(RV64I) | rd = SignExt((rs1[31:0] >>> shamt)[31:0]) (shamt范围:0–31) | RV64I |
3.4 逻辑指令
逻辑指令用于对寄存器中的数据进行按位操作,分为以下两类:
- 1.寄存器-寄存器操作:两个寄存器之间的按位运算。
- 2.寄存器-立即数操作:寄存器与符号扩展后的立即数进行按位运算。
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
按位与操作 | ||||
AND | and rd, rs1, rs2 | 按位与 | rd = rs1 & rs2 | RV32I / RV64Ity-reference |
ANDI | andi rd, rs1, imm | 立即数按位与(符号扩展立即数) | rd = rs1 & SignExt(imm) | RV32I / RV64Ity-reference |
按位或操作 | ||||
OR | or rd, rs1, rs2 | 按位或 | `rd = rs1 | rs2` |
ORI | ori rd, rs1, imm | 立即数按位或(符号扩展立即数) | `rd = rs1 | SignExt(imm)` |
按位异或操作 | ||||
XOR | xor rd, rs1, rs2 | 按位异或 | rd = rs1 ^ rs2 | RV32I / RV64Ity-reference |
XORI | xori rd, rs1, imm | 立即数按位异或(符号扩展立即数) | rd = rs1 ^ SignExt(imm) | RV32I / RV64Ity-reference |
伪指令:
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
NOT | not rd, rs | 按位取反(rd = ~rs) | xori rd, rs, -1 | RV32I / RV64I |
3.5 比较-置位指令
指令根据两个操作数的比较结果设置目标寄存器的值为 1 或 0,用于条件判断和逻辑控制,支持有符号和无符号比较。
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
有符号比较 | ||||
SLT | slt rd, rs1, rs2 | 有符号比较:若 rs1 < rs2,则 rd = 1,否则 rd = 0 | rd = (rs1 < rs2) ? 1 : 0 (有符号比较) | RV32I / RV64Ity-reference |
SLTI | slti rd, rs1, imm | 有符号立即数比较:若 rs1 < SignExt(imm),则 rd = 1 | rd = (rs1 < SignExt(imm)) ? 1 : 0 | RV32I / RV64Ity-reference |
无符号比较 | ||||
SLTU | sltu rd, rs1, rs2 | 无符号比较:若 rs1 < rs2,则 rd = 1 | rd = (rs1 < rs2) ? 1 : 0 (无符号比较) | RV32I / RV64Ity-reference |
SLTIU | sltiu rd, rs1, imm | 无符号立即数比较(立即数符号扩展后按无符号比较):若 rs1 < SignExt(imm),则 rd = 1 | rd = (rs1 < SignExt(imm)) ? 1 : 0 (无符号比较) | RV32I / RV64Ity-reference |
伪指令:
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
零值判断 | ||||
SEQZ | seqz rd, rs | 若 rs == 0,则 rd = 1,否则 0 | sltiu rd, rs, 1 | RV32I / RV64I |
SNEZ | snez rd, rs | 若 rs ≠ 0,则 rd = 1,否则 0 | sltu rd, x0, rs | RV32I / RV64I |
符号判断 | ||||
SLTZ | sltz rd, rs | 若 rs < 0(有符号),则 rd = 1 | slt rd, rs, x0 | RV32I / RV64I |
SGTZ | sgtz rd, rs | 若 rs > 0(有符号),则 rd = 1 | slt rd, x0, rs | RV32I / RV64I |
非零符号判断 | ||||
SLEZ | slez rd, rs | 若 rs ≤ 0(有符号),则 rd = 1 | slt rd, x0, rs → xori rd, rd, 1 | RV32I / RV64I |
SGEZ | sgez rd, rs | 若 rs ≥ 0(有符号),则 rd = 1 | slt rd, rs, x0 → xori rd, rd, 1 | RV32I / RV64I |
3.6 分支指令
分支指令用于控制程序流程,根据条件或地址跳转执行目标代码,均为 B-Type 或 J-Type 格式。
条件分支指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
BEQ | beq rs1, rs2, offset | 若 rs1 == rs2,跳转到 PC + offset | if (rs1 == rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
BNE | bne rs1, rs2, offset | 若 rs1 ≠ rs2,跳转到 PC + offset | if (rs1 != rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
BLT | blt rs1, rs2, offset | 若 rs1 < rs2(有符号),跳转 | if (rs1 < rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
BGE | bge rs1, rs2, offset | 若 rs1 ≥ rs2(有符号),跳转 | if (rs1 >= rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
BLTU | bltu rs1, rs2, offset | 若 rs1 < rs2(无符号),跳转 | if (rs1 < rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
BGEU | bgeu rs1, rs2, offset | 若 rs1 ≥ rs2(无符号),跳转 | if (rs1 >= rs2) PC += SignExt(offset << 1) | RV32I / RV64I |
条件分支伪指令
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
BEQZ | beqz rs, offset | 若 rs == 0,跳转到 offset | beq rs, x0, offset | RV32I / RV64I |
BNEZ | bnez rs, offset | 若 rs ≠ 0,跳转到 offset | bne rs, x0, offset | RV32I / RV64I |
BGT | bgt rs1, rs2, offset | 若 rs1 > rs2(有符号),跳转 | blt rs2, rs1, offset | RV32I / RV64I |
BGTU | bgtu rs1, rs2, offset | 若 rs1 > rs2(无符号),跳转 | bltu rs2, rs1, offset | RV32I / RV64I |
BLE | ble rs1, rs2, offset | 若 rs1 ≤ rs2(有符号),跳转 | bge rs2, rs1, offset | RV32I / RV64I |
BLEU | bleu rs1, rs2, offset | 若 rs1 ≤ rs2(无符号),跳转 | bgeu rs2, rs1, offset | RV32I / RV64I |
3.7 跳转指令
跳转指令用于改变程序的执行流程,使程序能够跳转到代码中的其他位置执行
无条件跳转指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 指令集 |
---|---|---|---|---|
JAL | jal rd, offset | 跳转到 PC + offset,并将返回地址存入 rd | rd = PC + 4; PC += SignExt(offset << 1) | RV32I / RV64I |
JALR | jalr rd, offset(rs1) | 跳转到 rs1 + offset,存入返回地址 | rd = PC + 4; PC = (rs1 + SignExt(offset)) & ~1 | RV32I / RV64I |
无条件跳转伪指令
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
J | j offset | 无条件跳转到 offset | jal x0, offset | RV32I / RV64I |
JR | jr rs | 跳转到 rs 指向的地址 | jalr x0, 0(rs) | RV32I / RV64I |
RET | ret | 从函数返回(跳转到 ra 地址) | jalr x0, 0(ra) | RV32I / RV64I |
3.8 同步指令
同步指令用于处理内存访问顺序控制,确保数据一致性和并发安全。
内存屏障指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
FENCE | fence pred, succ | 内存屏障(控制访存顺序) | 确保 pred 操作在 succ 操作前完成 (pred/succ 可以为 r(读)、w(写)、i(指令流)) | RV32I / RV64I |
FENCE.I | fence.i | 指令流同步屏障 | 确保后续指令看到此前所有指令的修改(用于自修改代码) | RV32I / RV64I) |
3.9 环境指令
环境指令用于系统调用、调试、中断处理等特权级操作,通常需在特定权限模式下执行。
系统调用与异常处理指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
ECALL | ecall | 触发环境调用(系统调用/异常) | 根据当前模式跳转到异常处理程序 | RV32I / RV64I |
EBREAK | ebreak | 触发断点异常(用于调试) | 进入调试模式或触发异常处理 | RV32I / RV64I |
中断返回指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
MRET | mret | 从机器模式异常返回 | PC = MEPC; Privilege = MPP | RV32I / RV64I |
SRET | sret | 从监管者模式异常返回 | PC = SEPC; Privilege = SPP | RV32I / RV64I |
URET | uret | 从用户模式异常返回 | PC = UEPC | RV32I / RV64I |
等待与暂停指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
WFI | wfi | 等待中断(暂停执行直至中断发生) | 暂停 CPU 直至中断或事件唤醒 | RV32I / RV64I ) |
3.10 控制状态寄存器指令
指令用于读写处理器的控制状态寄存器(如中断配置、计数器、特权模式设置等),支持原子操作和位操作,适用于系统编程和特权级管理。
CSR 读写指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
CSRRW | csrrw rd, csr, rs1 | 将 rs1 写入 CSR,原值存入 rd | t = CSR[csr]; CSR[csr] = rs1; rd = t | RV32I / RV64I |
CSRRS | csrrs rd, csr, rs1 | 将 rs1 对应位设为 1,原值存入 rd | `t = CSR[csr]; CSR[csr] | = rs1; rd = t` |
CSRRC | csrrc rd, csr, rs1 | 将 rs1 对应位清 0,原值存入 rd | t = CSR[csr]; CSR[csr] &= ~rs1; rd = t | RV32I / RV64I |
CSRRWI | csrrwi rd, csr, imm | 将 5 位立即数写入 CSR | t = CSR[csr]; CSR[csr] = imm; rd = t | RV32I / RV64I |
CSRRSI | csrrsi rd, csr, imm | 将立即数对应位置 1 | `t = CSR[csr]; CSR[csr] | = imm; rd = t` |
CSRRCI | csrrci rd, csr, imm | 将立即数对应位清 0 | t = CSR[csr]; CSR[csr] &= ~imm; rd = t | RV32I / RV64I |
CSR 伪指令
伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|
CSRR | csrr rd, csr | 读取 CSR 的值到寄存器 | csrrs rd, csr, x0 (读 CSR,不修改) | RV32I / RV64I |
CSRW | csrw csr, rs | 将寄存器的值写入 CSR | csrrw x0, csr, rs (丢弃原值,仅写入) | RV32I / RV64I |
CSRS | csrs csr, rs | 设置 CSR 中由 rs 指定的位 | csrrs x0, csr, rs (按位或,不保存结果) | RV32I / RV64I |
CSRC | csrc csr, rs | 清除 CSR 中由 rs 指定的位 | csrrc x0, csr, rs (按位与取反,不保存结果) | RV32I / RV64I |
CSRWI | csrwi csr, imm | 将 5 位立即数写入 CSR | csrrwi x0, csr, imm | RV32I / RV64I |
CSRSI | csrsi csr, imm | 设置 CSR 中由立即数指定的位 | csrrsi x0, csr, imm | RV32I / RV64I |
CSRCI | csrci csr, imm | 清除 CSR 中由立即数指定的位 | csrrci x0, csr, imm | RV32I / RV64I |
4 RVM指令集
RVM 扩展指令分为 乘法指令 和 除法/取余指令,支持有符号和无符号操作,并区分 RV32 和 RV64 的差异。
乘法指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
MUL | mul rd, rs1, rs2 | 乘法(低32/64位结果) | rd = (rs1 * rs2)[31:0] (RV32)rd = rs1 * rs2 (RV64) | RV32M / RV64M |
MULH | mulh rd, rs1, rs2 | 有符号乘法(高32/64位结果) | rd = (rs1 * rs2)[63:32] (RV32)rd = (rs1 * rs2)[127:64] (RV64) | RV32M / RV64M |
MULHU | mulhu rd, rs1, rs2 | 无符号乘法(高32/64位结果) | 同上,操作数为无符号数 | RV32M / RV64M |
MULHSU | mulhsu rd, rs1, rs2 | 有符号-无符号乘法(高32/64位结果) | rs1 有符号,rs2 无符号 | RV32M / RV64M |
MULW | mulw rd, rs1, rs2 | 32位乘法(结果符号扩展至64位) | rd = SignExt((rs1[31:0] * rs2[31:0])) | RV64M |
除法/取余指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
DIV | div rd, rs1, rs2 | 有符号除法(商) | rd = rs1 / rs2 (向零舍入) | RV32M / RV64M |
DIVU | divu rd, rs1, rs2 | 无符号除法(商) | rd = rs1 / rs2 | RV32M / RV64M |
REM | rem rd, rs1, rs2 | 有符号取余(余数) | rd = rs1 % rs2 (符号与 rs1 相同) | RV32M / RV64M |
REMU | remu rd, rs1, rs2 | 无符号取余(余数) | rd = rs1 % rs2 | RV32M / RV64M |
DIVW | divw rd, rs1, rs2 | 32位有符号除法(符号扩展至64位) | rd = SignExt((rs1[31:0] / rs2[31:0])) | RV64M |
DIVUW | divuw rd, rs1, rs2 | 32位无符号除法(零扩展至64位) | rd = ZeroExt((rs1[31:0] / rs2[31:0])) | RV64M |
REMW | remw rd, rs1, rs2 | 32位有符号取余(符号扩展至64位) | rd = SignExt((rs1[31:0] % rs2[31:0])) | RV64M |
REMUW | remuw rd, rs1, rs2 | 32位无符号取余(零扩展至64位) | rd = ZeroExt((rs1[31:0] % rs2[31:0])) | RV64M |
5 RVFD指令集
5.1 访存指令
指令用于在内存和浮点寄存器(f0-f31)之间传输单精度(F 扩展)或双精度(D 扩展)浮点数据:
浮点加载和存储指令
指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|
FLW | flw fd, offset(rs1) | 从内存加载单精度浮点数到浮点寄存器 | fd = F32(Mem[rs1 + offset]) | RV32F / RV64F |
FSW | fsw fs, offset(rs1) | 将单精度浮点数从浮点寄存器存入内存 | Mem[rs1 + offset] = F32(fs) | RV32F / RV64F |
FLD | fld fd, offset(rs1) | 从内存加载双精度浮点数到浮点寄存器 | fd = F64(Mem[rs1 + offset]) | RV64D |
FSD | fsd fs, offset(rs1) | 将双精度浮点数从浮点寄存器存入内存 | Mem[rs1 + offset] = F64(fs) | RV64D |
5.2 算术指令
算术指令用于执行各种数学运算,如加法、减法、乘法、除法等。当涉及到浮点数时,这些操作变得更为复杂,因为它们需要处理指数和尾数部分
基本算术指令
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
加法 | FADD.S | fadd.s fd, fs1, fs2 | 单精度浮点加法 | fd = fs1 + fs2 | RV32F / RV64F |
FADD.D | fadd.d fd, fs1, fs2 | 双精度浮点加法 | fd = fs1 + fs2 | RV64D | |
减法 | FSUB.S | fsub.s fd, fs1, fs2 | 单精度浮点减法 | fd = fs1 - fs2 | RV32F / RV64F |
FSUB.D | fsub.d fd, fs1, fs2 | 双精度浮点减法 | fd = fs1 - fs2 | RV64D | |
乘法 | FMUL.S | fmul.s fd, fs1, fs2 | 单精度浮点乘法 | fd = fs1 * fs2 | RV32F / RV64F |
FMUL.D | fmul.d fd, fs1, fs2 | 双精度浮点乘法 | fd = fs1 * fs2 | RV64D | |
除法 | FDIV.S | fdiv.s fd, fs1, fs2 | 单精度浮点除法 | fd = fs1 / fs2 | RV32F / RV64F |
FDIV.D | fdiv.d fd, fs1, fs2 | 双精度浮点除法 | fd = fs1 / fs2 | RV64D | |
平方根 | FSQRT.S | fsqrt.s fd, fs1 | 单精度浮点平方根 | fd = sqrt(fs1) | RV32F / RV64F |
FSQRT.D | fsqrt.d fd, fs1 | 双精度浮点平方根 | fd = sqrt(fs1) | RV64D | |
最小值 | FMIN.S | fmin.s fd, fs1, fs2 | 单精度浮点最小值 | fd = min(fs1, fs2) | RV32F / RV64F |
FMIN.D | fmin.d fd, fs1, fs2 | 双精度浮点最小值 | fd = min(fs1, fs2) | RV64D | |
最大值 | FMAX.S | fmax.s fd, fs1, fs2 | 单精度浮点最大值 | fd = max(fs1, fs2) | RV32F / RV64F |
FMAX.D | fmax.d fd, fs1, fs2 | 双精度浮点最大值 | fd = max(fs1, fs2) | RV64D |
5.3 RVFD 乘加指令
指令用于执行 乘加融合运算(Fused Multiply-Add, FMA),即在一个操作中完成乘法和加法,通常具有更高的精度和性能
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
单精度乘加 | FMADD.S | fmadd.s fd, fs1, fs2, fs3 | 单精度浮点乘加 | fd = (fs1 * fs2) + fs3 | RV32F / RV64F |
单精度乘减 | FMSUB.S | fmsub.s fd, fs1, fs2, fs3 | 单精度浮点乘减 | fd = (fs1 * fs2) - fs3 | RV32F / RV64F |
单精度负乘加 | FNMADD.S | fnmadd.s fd, fs1, fs2, fs3 | 单精度浮点负乘加 | fd = -((fs1 * fs2) + fs3) | RV32F / RV64F |
单精度负乘减 | FNMSUB.S | fnmsub.s fd, fs1, fs2, fs3 | 单精度浮点负乘减 | fd = -((fs1 * fs2) - fs3) | RV32F / RV64F |
双精度乘加 | FMADD.D | fmadd.d fd, fs1, fs2, fs3 | 双精度浮点乘加 | fd = (fs1 * fs2) + fs3 | RV64D |
双精度乘减 | FMSUB.D | fmsub.d fd, fs1, fs2, fs3 | 双精度浮点乘减 | fd = (fs1 * fs2) - fs3 | RV64D |
双精度负乘加 | FNMADD.D | fnmadd.d fd, fs1, fs2, fs3 | 双精度浮点负乘加 | fd = -((fs1 * fs2) + fs3) | RV64D |
双精度负乘减 | FNMSUB.D | fnmsub.d fd, fs1, fs2, fs3 | 双精度浮点负乘减 | fd = -((fs1 * fs2) - fs3) | RV64D |
5.4 RVFD传送指令
指令用于在 浮点寄存器 和 整数寄存器 之间传输数据,或在不同浮点寄存器之间复制数据
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
浮点到整数 | FMV.X.S | fmv.x.s rd, fs1 | 将单精度浮点数转为整数表示 | rd = fs1 (按位复制) | RV32F / RV64F |
浮点到整数 | FMV.X.D | fmv.x.d rd, fs1 | 将双精度浮点数转为整数表示 | rd = fs1 (按位复制) | RV64D |
整数到浮点 | FMV.S.X | fmv.s.x fd, rs1 | 将整数表示转为单精度浮点数 | fd = rs1 (按位复制) | RV32F / RV64F |
整数到浮点 | FMV.D.X | fmv.d.x fd, rs1 | 将整数表示转为双精度浮点数 | fd = rs1 (按位复制) | RV64D |
5.5 RVFD 转换指令
分两类归纳:浮点寄存器间传送 和 浮点与整数寄存器间传送,涵盖符号操作、位模式复制及特殊值处理
浮点与整数之间的转换
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
浮点 → 整数 | FCVT.W.S | fcvt.w.s rd, fs1 | 单精度浮点转为 32 位有符号整数 | rd = (int32_t)fs1 | RV32F / RV64F |
FCVT.WU.S | fcvt.wu.s rd, fs1 | 单精度浮点转为 32 位无符号整数 | rd = (uint32_t)fs1 | RV32F / RV64F | |
FCVT.L.S | fcvt.l.s rd, fs1 | 单精度浮点转为 64 位有符号整数 | rd = (int64_t)fs1 | RV64F | |
FCVT.LU.S | fcvt.lu.s rd, fs1 | 单精度浮点转为 64 位无符号整数 | rd = (uint64_t)fs1 | RV64F | |
FCVT.W.D | fcvt.w.d rd, fs1 | 双精度浮点转为 32 位有符号整数 | rd = (int32_t)fs1 | RV64D | |
FCVT.WU.D | fcvt.wu.d rd, fs1 | 双精度浮点转为 32 位无符号整数 | rd = (uint32_t)fs1 | RV64D | |
FCVT.L.D | fcvt.l.d rd, fs1 | 双精度浮点转为 64 位有符号整数 | rd = (int64_t)fs1 | RV64D | |
FCVT.LU.D | fcvt.lu.d rd, fs1 | 双精度浮点转为 64 位无符号整数 | rd = (uint64_t)fs1 | RV64D | |
整数 → 浮点 | FCVT.S.W | fcvt.s.w fd, rs1 | 32 位有符号整数转为单精度浮点 | fd = (float)rs1 | RV32F / RV64F |
FCVT.S.WU | fcvt.s.wu fd, rs1 | 32 位无符号整数转为单精度浮点 | fd = (float)rs1 | RV32F / RV64F | |
FCVT.S.L | fcvt.s.l fd, rs1 | 64 位有符号整数转为单精度浮点 | fd = (float)rs1 | RV64F | |
FCVT.S.LU | fcvt.s.lu fd, rs1 | 64 位无符号整数转为单精度浮点 | fd = (float)rs1 | RV64F | |
FCVT.D.W | fcvt.d.w fd, rs1 | 32 位有符号整数转为双精度浮点 | fd = (double)rs1 | RV64D | |
FCVT.D.WU | fcvt.d.wu fd, rs1 | 32 位无符号整数转为双精度浮点 | fd = (double)rs1 | RV64D | |
FCVT.D.L | fcvt.d.l fd, rs1 | 64 位有符号整数转为双精度浮点 | fd = (double)rs1 | RV64D | |
FCVT.D.LU | fcvt.d.lu fd, rs1 | 64 位无符号整数转为双精度浮点 | fd = (double)rs1 | RV64D |
浮点精度之间的转换
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
单精度 ↔ 双精度 | FCVT.S.D | fcvt.s.d fd, fs1 | 双精度浮点转为单精度浮点 | fd = (float)fs1 | RV64D |
单精度 ↔ 双精度 | FCVT.D.S | fcvt.d.s fd, fs1 | 单精度浮点转为双精度浮点 | fd = (double)fs1 | RV64D |
5.6 RVFD 符号注入指令
指令用于将 整数立即数 或 整数寄存器值 注入到浮点寄存器中,通常用于快速构造浮点常数或特殊值(如 NaN、无穷大)
单精度浮点注入指令
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
符号复制 | FSGNJ.S | fsgnj.s fd, fs1, fs2 | 复制数值,符号位取自 fs2 | fd = {fs2[31], fs1[30:0]} | RV32F / RV64F |
符号取反 | FSGNJN.S | fsgnjn.s fd, fs1, fs2 | 复制数值,符号位取反自 fs2 | fd = {~fs2[31], fs1[30:0]} | RV32F / RV64F |
符号取绝对值 | FSGNJX.S | fsgnjx.s fd, fs1, fs2 | 复制数值,符号位异或(取绝对值) | fd = {fs1[31] ^ fs2[31], fs1[30:0]} | RV32F / RV64F |
双精度浮点注入指令
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
符号复制 | FSGNJ.D | fsgnj.d fd, fs1, fs2 | 复制数值,符号位取自 fs2 | fd = {fs2[63], fs1[62:0]} | RV64D |
符号取反 | FSGNJN.D | fsgnjn.d fd, fs1, fs2 | 复制数值,符号位取反自 fs2 | fd = {~fs2[63], fs1[62:0]} | RV64D |
符号取绝对值 | FSGNJX.D | fsgnjx.d fd, fs1, fs2 | 复制数值,符号位异或(取绝对值) | fd = {fs1[63] ^ fs2[63], fs1[62:0]} | RV64D |
伪指令
指令类型 | 伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|---|
单精度浮点注入 | FABS.S | fabs.s fd, fs | 单精度浮点取绝对值 | fsgnjx.s fd, fs, fs | RV32F / RV64F |
FMV.S | fmv.s fd, fs | 单精度浮点复制 | fsgnj.s fd, fs, fs | RV32F / RV64F | |
FNEG.S | fneg.s fd, fs | 单精度浮点取反 | fsgnjn.s fd, fs, fs | RV32F / RV64F |
指令类型 | 伪指令 | 格式 | 功能描述 | 实际转换(基础指令) | 适用指令集 |
---|---|---|---|---|---|
双精度浮点注入 | FABS.D | fabs.d fd, fs | 双精度浮点取绝对值 | fsgnjx.d fd, fs, fs | RV64D |
FMV.D | fmv.d fd, fs | 双精度浮点复制 | fsgnj.d fd, fs, fs | RV64D | |
FNEG.D | fneg.d fd, fs | 双精度浮点取反 | fsgnjn.d fd, fs, fs | RV64D |
5.7 RVFD 比较指令
指令用于比较两个浮点数的值,并将比较结果写入整数寄存器,支持 相等、小于 和 小于等于 三种比较操作
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
相等比较 | FEQ.S | feq.s rd, fs1, fs2 | 单精度浮点相等比较 | rd = (fs1 == fs2) ? 1 : 0 | RV32F / RV64F |
FEQ.D | feq.d rd, fs1, fs2 | 双精度浮点相等比较 | rd = (fs1 == fs2) ? 1 : 0 | RV64D | |
小于比较 | FLT.S | flt.s rd, fs1, fs2 | 单精度浮点小于比较 | rd = (fs1 < fs2) ? 1 : 0 | RV32F / RV64F |
FLT.D | flt.d rd, fs1, fs2 | 双精度浮点小于比较 | rd = (fs1 < fs2) ? 1 : 0 | RV64D | |
小于等于比较 | FLE.S | fle.s rd, fs1, fs2 | 单精度浮点小于等于比较 | rd = (fs1 <= fs2) ? 1 : 0 | RV32F / RV64F |
FLE.D | fle.d rd, fs1, fs2 | 双精度浮点小于等于比较 | rd = (fs1 <= fs2) ? 1 : 0 | RV64D |
5.8 RVFD 分类指令
指令用于检查浮点数的类别(如正无穷、负零、NaN 等),并将结果写入整数寄存器,适用于浮点数的异常处理和特殊值检测
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
浮点分类 | 单精度分类 | fclass.s rd, fs1 | 单精度浮点分类 | rd = classify(fs1) | RV32F / RV64F |
浮点分类 | 双精度分类 | fclass.d rd, fs1 | 双精度浮点分类 | rd = classify(fs1) | RV64D |
5.9 RVFD 配置指令
指令用于配置和管理浮点单元的状态,包括 舍入模式、异常标志 和 浮点控制状态寄存器(fcsr) 的操作
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
浮点控制状态寄存器(fcsr)操作 | |||||
读取 fcsr | FRCSR | frcsr rd | 读取 fcsr 的值到整数寄存器 | rd = fcsr | RV32F / RV64F |
写入 fcsr | FSCSR | fscsr rd, rs | 将整数寄存器的值写入 fcsr | fcsr = rs | RV32F / RV64F |
交换 fcsr | FSRCS | fscsr rd, rs | 交换 fcsr 和整数寄存器的值 | t = fcsr; fcsr = rs; rd = t | RV32F / RV64F |
舍入模式配置 | |||||
读取舍入模式 | FRRM | frrm rd | 读取舍入模式到整数寄存器 | rd = fcsr[7:5] | RV32F / RV64F |
写入舍入模式 | FSRM | fsrm rd, rs | 将整数寄存器的值写入舍入模式 | fcsr[7:5] = rs[2:0] | RV32F / RV64F |
交换舍入模式 | FSRRM | fsrrm rd, rs | 交换舍入模式和整数寄存器的值 | t = fcsr[7:5]; fcsr[7:5] = rs[2:0]; rd = t | RV32F / RV64F |
异常标志操作 | |||||
读取异常标志 | FFLAGS | fflags rd | 读取异常标志到整数寄存器 | rd = fcsr[4:0] | RV32F / RV64F |
写入异常标志 | FSFLAGS | fsflags rd, rs | 将整数寄存器的值写入异常标志 | fcsr[4:0] = rs[4:0] | RV32F / RV64F |
交换异常标志 | FSRFLAGS | fsrflags rd, rs | 交换异常标志和整数寄存器的值 | t = fcsr[4:0]; fcsr[4:0] = rs[4:0]; rd = t | RV32F / RV64F |
6 RVA指令集
RVA(Atomic Operations)扩展为 RISC-V 提供了硬件支持的原子操作指令,用于在多线程或多核环境中实现 原子内存访问 和 同步操作,确保数据一致性和并发安全。
加载保留与条件存储指令
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
加载保留 | LR.W | lr.w rd, (rs1) | 加载保留(原子加载字,标记内存地址) | rd = Mem[rs1]; Reserve rs1 | RV32A / RV64A |
LR.D | lr.d rd, (rs1) | 加载保留(原子加载双字) | rd = Mem[rs1]; Reserve rs1 | RV64A | |
条件存储 | SC.W | sc.w rd, rs2, (rs1) | 条件存储(若地址未被修改,存储字) | if (Reserve rs1 still valid) { Mem[rs1] = rs2; rd = 0 } else { rd = 1 } | RV32A / RV64A |
SC.D | sc.d rd, rs2, (rs1) | 条件存储(若地址未被修改,存储双字) | if (Reserve rs1 still valid) { Mem[rs1] = rs2; rd = 0 } else { rd = 1 } | RV64A |
原子内存操作指令
指令类型 | 指令 | 格式 | 功能描述 | 操作(伪代码) | 适用指令集 |
---|---|---|---|---|---|
原子加 | AMOADD.W | amoadd.w rd, rs2, (rs1) | 原子加并返回原值 | rd = Mem[rs1]; Mem[rs1] += rs2 | RV32A / RV64A |
AMOADD.D | amoadd.d rd, rs2, (rs1) | 原子加并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] += rs2 | RV64A | |
原子交换 | AMOSWAP.W | amoswap.w rd, rs2, (rs1) | 原子交换并返回原值 | rd = Mem[rs1]; Mem[rs1] = rs2 | RV32A / RV64A |
AMOSWAP.D | amoswap.d rd, rs2, (rs1) | 原子交换并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] = rs2 | RV64A | |
原子按位与 | AMOAND.W | amoand.w rd, rs2, (rs1) | 原子按位与并返回原值 | rd = Mem[rs1]; Mem[rs1] &= rs2 | RV32A / RV64A |
AMOAND.D | amoand.d rd, rs2, (rs1) | 原子按位与并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] &= rs2 | RV64A | |
原子按位或 | AMOOR.W | amoor.w rd, rs2, (rs1) | 原子按位或并返回原值 | `rd = Mem[rs1]; Mem[rs1] | = rs2` |
AMOOR.D | amoor.d rd, rs2, (rs1) | 原子按位或并返回原值(双字) | `rd = Mem[rs1]; Mem[rs1] | = rs2` | |
原子按位异或 | AMOXOR.W | amoxor.w rd, rs2, (rs1) | 原子按位异或并返回原值 | rd = Mem[rs1]; Mem[rs1] ^= rs2 | RV32A / RV64A |
AMOXOR.D | amoxor.d rd, rs2, (rs1) | 原子按位异或并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] ^= rs2 | RV64A | |
原子最大值 | AMOMAX.W | amomax.w rd, rs2, (rs1) | 原子有符号最大值并返回原值 | rd = Mem[rs1]; Mem[rs1] = max(rd, rs2) | RV32A / RV64A |
AMOMAX.D | amomax.d rd, rs2, (rs1) | 原子有符号最大值并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] = max(rd, rs2) | RV64A | |
原子无符号最大值 | AMOMAXU.W | amomaxu.w rd, rs2, (rs1) | 原子无符号最大值并返回原值 | rd = Mem[rs1]; Mem[rs1] = maxu(rd, rs2) | RV32A / RV64A |
AMOMAXU.D | amomaxu.d rd, rs2, (rs1) | 原子无符号最大值并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] = maxu(rd, rs2) | RV64A | |
原子最小值 | AMOMIN.W | amomin.w rd, rs2, (rs1) | 原子有符号最小值并返回原值 | rd = Mem[rs1]; Mem[rs1] = min(rd, rs2) | RV32A / RV64A |
AMOMIN.D | amomin.d rd, rs2, (rs1) | 原子有符号最小值并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] = min(rd, rs2) | RV64A | |
原子无符号最小值 | AMOMINU.W | amominu.w rd, rs2, (rs1) | 原子无符号最小值并返回原值 | rd = Mem[rs1]; Mem[rs1] = minu(rd, rs2) | RV32A / RV64A |
AMOMINU.D | amominu.d rd, rs2, (rs1) | 原子无符号最小值并返回原值(双字) | rd = Mem[rs1]; Mem[rs1] = minu(rd, rs2) | RV64A |
上面列举了RISC-V指令集,但实际上上面列举的指令集我很多也没用过,是按照spec总结了下,如有错误或者遗漏,还请各位大佬评论区指出。
参考
riscv-spec-20240411.pdf
一起学RISC-V汇编第5讲之常用指令及伪指令列表
RISC-V 常用汇编指令
相关文章:
RISC-V汇编学习(三)—— RV指令集
有了前两节对于RISC-V汇编、寄存器、汇编语法等的认识,本节开始介绍RISC-V指令集和伪指令。 前面说了RISC-V的模块化特点,是以RV32I为作为ISA的核心模块,其他都是要基于此为基础,可以这样认为:RISC-V ISA 基本整数指…...
【Linux】冯诺依曼体系与操作系统理解
🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充:理解系统调用…...
Android15使用FFmpeg解码并播放MP4视频完整示例
效果: 1.编译FFmpeg库: 下载FFmpeg-kit的源码并编译生成安装平台库 2.复制生成的FFmpeg库so文件与包含目录到自己的Android下 如果没有prebuiltLibs目录,创建一个,然后复制 包含目录只复制arm64-v8a下...
音视频入门基础:RTP专题(16)——RTP封装音频时,音频的有效载荷结构
一、引言 《RFC 3640》和《RFC 6416》分别定义了两种对MPEG-4流的RTP封包方式,这两个文档都可以从RFC官网下载: RFC Editor 本文主要对《RFC 3640》中的音频打包方式进行简介。《RFC 3640》总共有43页,本文下面所说的“页数”是指在pdf阅读…...
3.3.2 Proteus第一个仿真图
文章目录 文章介绍0 效果图1 新建“点灯”项目2 添加元器件3 元器件布局接线4 补充 文章介绍 本文介绍:使用Proteus仿真软件画第一个仿真图 0 效果图 1 新建“点灯”项目 修改项目名称和路径,之后一直点“下一步”直到完成 2 添加元器件 点击元…...
MySQL创建数据库和表,插入四大名著中的人物
一、登录数据库并创建数据库db_ck 二、创建表t_hero 表属性包括(id,name,nickname,age,gender,address,weapon,types) mysql> create table t_hero(-> id int,-…...
matlab和FPGA联合仿真时读写.txt文件数据的方法
在FPGA开发过程中,往往需要将MATLAB生成的数据作为原始激励灌入FPGA进行仿真。为了验证FPGA计算是否正确,又需要将FPGA计算结果导入MATLAB绘图与MATLAB计算结果对比。 下面是MATLAB“写.txt”、“读.txt”,Verilog“读.txt”、“写.txt”的代…...
C++修炼之路:初识C++
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》 欢迎点赞,关注! 引言 …...
ACE协议学习1
在多核系统或复杂SoC(System on Chip)中,不同处理器核心或IP(Intellectual Property)模块之间需要保持数据的一致性。常用的是ACE协议or CHI。 先对ACE协议进行学习 ACE协议(Advanced Microcontroller Bu…...
通俗易懂的介绍LLM大模型技术常用专业名词(通用版)
1. 神经网络 (Neural Network) 解释: 一种模拟人脑神经元结构的计算模型,用于处理复杂的数据模式。 示例: 图像识别中的卷积神经网络(CNN)。 2. 深度学习 (Deep Learning) 解释: 基于多层神经网络的机器学习方法,能够自动提取数…...
深度学习环境安装
Anaconda 3.0 下载地址 Download Success | Anaconda CUDA 下载地址 cuda_12.4.0 https://developer.nvidia.com/cuda-12-4-0-download-archive?target_osWindows&target_archx86_64&target_version11&target_typeexe_local pytorch 下载地址 (2…...
【哇! C++】类和对象(五) - 赋值运算符重载
目录 编辑 一、运算符重载 1.1 运算符重载概念 1.2 全局运算符重载 1.3 运算符重载为成员函数 二、赋值运算符重载的特性 2.1 赋值运算符重载需要注意的点 2.2 赋值运算符重载格式 2.2.1 传值返回 2.2.2 传引用返回 2.2.3 检查自己给自己赋值 三、赋值运算符重载的…...
【时序图】1.StarUML绿化
1)下载地址 官网: StarUML 如下: 2)绿化 step1:用管理员打开cmd,执行如下 npm install -g asar cd C:\Program Files\StarUML\resources //进入到StarUML的默认安装目录下面 asar extract app.asar app //反编译软件step2:把resources下的app文件夹拷贝出来到…...
mysql练习
创建数据库db_ck,再创建表t_hero,将四大名著中的主要人物都插入这个表中,将实现过程中sql提交上上来 1、创建数据库db_ck mysql> create database db_ck; 2、创建表t_hero mysql> use db_ck Database changed mysql> create table …...
数据结构(队列)
数据结构(队列) 什么是队列? 队列和栈类似,也是一类特殊的线性表。特殊之处也是在于操作上。队列:只允许在一端进行插入数据操作(入队),在另一端进行删除数据操作(出队&…...
fps项目二次总结
文章目录 角色角色蓝图动画蓝图角色蓝图与动画蓝图间的通信动画蓝图绑定在网格体上 其他蓝图角色蓝图与其他蓝图的通信通信详解单向通信:A向B与B向A互不相通A向B发送消息A:发起方:即调用方B:接收方:即提供方࿱…...
VTK笔记- 3D Widget类 vtkSplineWidget 样条部件
vtk3DWidget vtk3DWidget是用于3D交互观察器的基类,也就是各种3D小部件类的基类,主要是在三维渲染场景中生成一个可以用于控制数据的可视化实体,比如点,线段(曲线)、平面、球体、包围盒(线框&am…...
文心一言:中国大模型时代的破局者与探路者
2023年,生成式人工智能(AIGC)的浪潮席卷全球,而百度推出的“文心一言”(ERNIE Bot)作为中国AI领域的代表性产品,迅速成为行业焦点。这款基于百度自主研发的“文心大模型”打造的对话式AI工具&am…...
【芯片验证】verificationguide上的36道UVM面试题
跟上一篇一样,verificationguide上的36到UVM面试题,通义回答ds判卷。 1. What is uvm_transaction, uvm_seq_item, uvm_object, uvm_component? uvm_transaction、uvm_seq_item、uvm_object、uvm_component是什么? uvm_transaction是UVM中所有事务的基础类,用于表示仿真…...
操作系统控制台-健康守护我们的系统
引言基本准备体验功能健康守护系统诊断 收获提升结语 引言 阿里云操作系统控制平台作为新一代云端服务器中枢平台,通过创新交互模式重构主机管理体验。操作系统控制台提供了一系列管理功能,包括运维监控、智能助手、扩展插件管理以及订阅服务等。用户可以…...
基于策略模式的智能提示语生成器设计与实现——以Tkinter GUI开发为例
基于策略模式的智能提示语生成器设计与实现——以Tkinter GUI开发为例 一、引言:智能化时代的提示工程工具 在人工智能技术广泛应用的时代背景下,如何与AI模型进行有效交互已成为关键技能。本文介绍的"AI任务需求与提示语策略生成器"正是基于…...
【打卡d1】算法模拟类
题目1 题目描述: 某百货公司为了促销,采用购物打折的优惠方法,每位顾客一次购物:在1000元以上者,按 9.5 折优惠;在2000以上者,按9折优惠;在3000以上者,按8.5 折优惠;在5000 以上者,按8折优惠;编写程序&…...
7.2 奇异值分解的基与矩阵
一、奇异值分解 奇异值分解(SVD)是线性代数的高光时刻。 A A A 是一个 m n m\times n mn 的矩阵,可以是方阵或者长方形矩阵,秩为 r r r。我们要对角化 A A A,但并不是把它化成 X − 1 A X X^{-1}A X X−1AX 的形…...
3.3.2 用仿真图实现点灯效果
文章目录 文章介绍Keil生成.hex代码Proteus仿真图中导入.hex代码文件开始仿真 文章介绍 点灯之前需要准备好仿真图keil代码 仿真图参考前文:3.3.2 Proteus第一个仿真图 keil安装参考前文:3.1.2 Keil4安装教程 keil新建第一个项目参考前文:3.1…...
Docker 学习笔记:从入门到部署,实战演练全流程!
📌 开篇:为什么要学 Docker? 还在为环境不一致、部署麻烦、依赖冲突头疼吗?Docker 让一切变得简单!作为现代开发和运维的神器,Docker 让我们可以用 一句命令 解决 “在我电脑上能跑” 的问题。今天&#x…...
本地搭建DeepSeek R1模型 + 前端
本地搭建DeepSeek R1模型 前端 配置: 操作系统:windows11 CPU:i5 13600KF GPU:英伟达4070 12GB 内存:16G DDR5 硬盘:1TB 模型安装 本文采用Ollama进行安装。Ollama安装比较简单。 官网࿱…...
MyBatis增删改查:静态与动态SQL语句拼接及SQL注入问题解析
MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。本文将深入探讨 MyBatis 中的增删改查操作,重点讲解静态与动态 SQL 语句的拼接,并分析 S…...
Unity入门学习笔记(Day01)
一.认识unity工作面板 1.1.project window(项目面板) 显示当前项目中的所有文件和目录,包含了项目里面所有的资源文件 1.2.console window(输出面板) 显示当前游戏开发中生成的警告错误 1.3.hierarchy window&…...
教务考试管理系统-Sprintboot vue
一、前言 1.1 实践目的和要求 本次实践的目的是为了帮助学生强化对实践涉及专业技术知识的理解,掌握专业领域中软件知识的应用方法,并了解软件工程在具体行业领域的发展趋势。通过培养学生利用软件工程方法分析、设计并完成具体行业软件开发的能力&…...
GHCTF2025--Web
upload?SSTI! import os import refrom flask import Flask, request, jsonify,render_template_string,send_from_directory, abort,redirect from werkzeug.utils import secure_filename import os from werkzeug.utils import secure_filenameapp Flask(__name__)# 配置…...
文件上传漏洞(upload-labs)
目录 Pass-01(前端绕过) (1)JavaScript (2)Burpsuite(改后缀) Pass-02(IMME类型 ) burpsuite(改文件类型) Pass-03(黑名单绕过) …...
图片的拖拽+缩放
效果图: <script setup lang"ts"> import { onMounted, ref } from vue; import ImgBg from /assets/img/bg.jpg import Img1 from /assets/img/1.jpgconst innerStyle ref({left: 0,top: 0,width: 100,height: 0 }) const wrapStyle ref({width:…...
Windows软件插件-音视频文件读取器
下载本插件 本插件读取音频和视频文件,输出音频样本和视频样本,音频样本为16位PCM,采样率48000;视频样本为RGB32。大部分音频和视频文件格式都可以读取。本插件类型为DLL。 本插件是通过创建媒体基础“源读取器”对象实现读取音视…...
考研数一复习之拉格朗日中值定理求解函数极限
最近在复习考研数学,只是简单做题过于乏味,因此便总结了一些笔记,后续若有空,也会将自己的复习笔记分享出来。本篇,我们将重点讲解拉格朗日中值定理在求解函数极限中的应用。同时,作者本人作为python领域创作者,还将在本文分享使用sympy求解高数中函数极…...
聊天服务器分布式改造
目前的聊天室是单节点的,无论是http接口还是socket接口都在同一个进程,无法承受太多人同时在线,容灾性也非常差。因此,一个成熟的IM产品一定是做成分布式的,根据功能分模块,每个模块也使用多个节点并行部署…...
C++11的一些特性
目录 一、C11简介 二、统一的列表初始化 2.1 {}初始化 2.2 std::initializer_list 三、声明 3.1 auto 3.2 decltype 3.3 nullptr 四、范围for循环 五、智能指针 5.1 RAII 5.2 智能指针的原理 5.3 std::auto_ptr…...
【打卡day3】字符串类
例如统计字符个数,字符大小写转换 题目描述:输入一行字符串,计算A-Z大写字母出现的次数 思路: 1 定义一个整型数组,初始化为0,存储每个字母出现的次数,下标0对应字母A, 2,定义字…...
图像滑块对比功能的开发记录
背景介绍 最近,公司需要开发一款在线图像压缩工具,其中的一个关键功能是让用户直观地比较压缩前后的图像效果。因此,我们设计了一个对比组件,它允许用户通过拖动滑块,动态调整两张图像的显示区域,从而清晰…...
【音视频】ffplay常用命令
一、 ffplay常用命令 -x width:强制显示宽度-y height:强制显示高度 强制以 640*360的宽高显示 ffplay 2.mp4 -x 640 -y 360 效果如下 -fs 全屏显示 ffplay -fs 2.mp4效果如下: -an 禁用音频(不播放声音)-vn 禁…...
初识Linux
文章目录 初识Linux:从开源哲学到技术生态的全面解析一、Linux的背景与发展简史:从代码实验到数字基础设施1.1 起源与开源基因1.2 技术哲学之争1.3 GNU/Linux的融合 二、开源:Linux的核心竞争力与生态力量2.1 法律保障与四大自由2.2 社区协作…...
基于遗传算法的IEEE33节点配电网重构程序
一、配电网重构原理 配电网重构(Distribution Network Reconfiguration, DNR)是一项优化操作,旨在通过改变配电网中的开关状态,优化电力系统的运行状态,以达到降低网损、均衡负载、改善电压质量等目标。配电网重构的核…...
manus对比ChatGPT-Deep reaserch进行研究类学术相关数据分析!谁更胜一筹?
没有账号,只能挑选一个案例 一夜之间被这个用全英文介绍全华班出品的新爆款国产AI产品的小胖刷频。白天还没有切换语言的选项,晚上就加上了。简单看了看团队够成,使用很长实践的Monica创始人也在其中。逐渐可以理解,重心放在海外产…...
线程通信---java
线程 我们知道,线程是进程的最小执行单位,一个进程可以拥有多个线程,那么就会引入两个问题: 多个线程之间如何进行通信多个线程对同一个数据进行操作,如何保证程序正确执行,也就是线程安全问题 线程的常…...
python面试常见题目
1、python 有几种数据类型 数字:整形 (int),浮点型 (float)布尔 ( bool):false true字符串 (string)列表 (list)元组 (tuple)字典 &…...
Python中与字符串操作相关的30个常用函数及其示例
以下是Python中与字符串操作相关的30个常用函数及其示例: 1. str.capitalize() 将字符串的第一个字符大写,其余字符小写。 s "hello world" print(s.capitalize()) # 输出: Hello world2. str.lower() 将字符串中的所有字符转换为小写。…...
2025年渗透测试面试题总结-小某鹏汽车-安全工程师(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 小鹏汽车-安全工程师 一、XXE漏洞与SSRF漏洞 1. XXE(XML External Entity)漏洞…...
kafka + flink +mysql 案例
假设你有两个Kafka主题:user_activities_topic 和 product_views_topic,并且你希望将user_activities_topic中的数据写入到user_activities表,而将product_views_topic中的数据写入到product_views表。 maven <dependencies><!-- …...
Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置
截止 2025/3/9 ,版本更新到了 3.29.1 ,但是为了防止出现一些奇怪的bug,我安装的还是老一点的,3.19,其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量(Windows) PUB_H…...
【工具类】Springboot 项目日志打印项目版本和构建时间
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
p5.js:模拟 n个彩色小球在一个3D大球体内部弹跳
向 豆包 提问:编写一个 p5.js 脚本,模拟 42 个彩色小球在一个3D大球体内部弹跳。每个小球都应留下一条逐渐消失的轨迹。大球体应缓慢旋转,并显示透明的轮廓线。请确保实现适当的碰撞检测,使小球保持在球体内部。 cd p5-demo copy…...