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)
在这里插入图片描述

指令格式功能描述操作(伪代码)指令集
LBlb rd, offset(rs1)加载字节(符号扩展)rd = SignExt(Mem[rs1 + offset][7:0])RV32I / RV64I
LBUlbu rd, offset(rs1)加载字节(无符号扩展)rd = ZeroExt(Mem[rs1 + offset][7:0])RV32I / RV64I
LHlh rd, offset(rs1)加载半字(符号扩展)rd = SignExt(Mem[rs1 + offset][15:0])RV32I / RV64I
LHUlhu rd, offset(rs1)加载半字(无符号扩展)rd = ZeroExt(Mem[rs1 + offset][15:0])RV32I / RV64I
LWlw rd, offset(rs1)加载字(RV32I:32位;RV64I:符号扩展至64位)RV32I: rd = Mem[rs1 + offset][31:0]
RV64I: rd = SignExt(Mem[rs1 + offset][31:0])
RV32I / RV64I
LWUlwu rd, offset(rs1)加载字(无符号扩展至64位)rd = ZeroExt(Mem[rs1 + offset][31:0])RV64I
LDld rd, offset(rs1)加载双字(64位)rd = Mem[rs1 + offset][63:0]RV64I
SBsb rs2, offset(rs1)存储字节Mem[rs1 + offset] = rs2[7:0]RV32I / RV64I
SHsh rs2, offset(rs1)存储半字Mem[rs1 + offset] = rs2[15:0]RV32I / RV64I
SWsw rs2, offset(rs1)存储字Mem[rs1 + offset] = rs2[31:0]RV32I / RV64I
SDsd rs2, offset(rs1)存储双字Mem[rs1 + offset] = rs2[63:0]RV64I

3.2 算术指令

算术指令狭义定义:仅包含加法、减法及其直接相关的操作,用于寄存器或寄存器与立即数之间的数值运算。
在这里插入图片描述

指令格式功能描述操作(伪代码)指令集
基础加减指令
ADDadd rd, rs1, rs2加法(忽略溢出)rd = rs1 + rs2RV32I / RV64I
SUBsub rd, rs1, rs2减法(忽略溢出)rd = rs1 - rs2RV32I / RV64I
ADDIaddi rd, rs1, imm立即数加法(符号扩展立即数)rd = rs1 + SignExt(imm)RV32I / RV64I
RV64I 扩展加减指令
ADDIWaddiw rd, rs1, imm立即数加法(32位,符号扩展至64位)rd = SignExt((rs1 + SignExt(imm))[31:0])RV64I
ADDWaddw rd, rs1, rs2加法(32位,符号扩展至64位)rd = SignExt((rs1 + rs2)[31:0])RV64I
SUBWsubw rd, rs1, rs2减法(32位,符号扩展至64位)rd = SignExt((rs1 - rs2)[31:0])RV64I
高位立即数构建指令
LUIlui rd, imm加载高位立即数(imm[31:12])rd = imm << 12RV32I / RV64I
AUIPCauipc rd, imm将高位立即数与 PC 相加rd = PC + (imm << 12)RV32I / RV64I

伪指令表格

伪指令格式功能描述实际转换(基础指令)适用指令集
寄存器操作
MVmv rd, rs寄存器间移动值addi rd, rs, 0RV32I / RV64I
NEGneg rd, rs取负值(rd = -rs)sub rd, x0, rsRV32I / RV64I
NEGWnegw rd, rs取负值(32位操作,符号扩展)subw rd, x0, rsRV64I
立即数操作
LIli rd, imm加载任意立即数到寄存器若 imm 在 12 位有符号范围内:addi rd, x0, imm
否则:lui rd, imm[31:12] + addi rd, rd, imm[11:0]
RV32I / RV64I
地址加载
LAla rd, symbol加载绝对地址(链接时解析)auipc rd, offset_hi + addi rd, rd, offset_lo
lui rd, offset_hi + addi rd, rd, offset_lo
RV32I / RV64I
LLAlla rd, symbol加载本地地址(PC相对,位置无关)auipc rd, offset_hi + addi rd, rd, offset_loRV32I / RV64I
符号扩展
SEXT.Wsext.w rd, rs将低32位符号扩展至64位(RV64I)addiw rd, rs, 0RV64I
空操作
NOPnop空操作(无实际效果)addi x0, x0, 0RV32I / RV64I

3.3 移位指令

移位指令用于对寄存器中的数据进行位级左移或右移,分为以下两类:

    1. 寄存器移位:移位位数由另一个寄存器的低 5 位(RV32I)或低 6 位(RV64I)指定。
    1. 立即数移位:移位位数由指令中的立即数字段直接指定。
      在这里插入图片描述
指令格式功能描述操作(伪代码)指令集
逻辑左移
SLLsll rd, rs1, rs2逻辑左移(低位补零)rd = rs1 << (rs2[4:0])(RV32I,取低5位)
rd = rs1 << (rs2[5:0])(RV64I,取低6位)
RV32I / RV64I
SLLIslli rd, rs1, shamt立即数逻辑左移rd = rs1 << shamt(shamt范围:RV32I为 0–31,RV64I为 0–63)RV32I / RV64I
SLLWsllw rd, rs1, rs232位逻辑左移(RV64I,低32位操作)rd = SignExt((rs1[31:0] << rs2[4:0]))RV64I
SLLIWslliw rd, rs1, shamt32位立即数逻辑左移(RV64I)rd = SignExt((rs1[31:0] << shamt)[31:0])(shamt范围:0–31)RV64I
逻辑右移
SRLsrl rd, rs1, rs2逻辑右移(高位补零)rd = rs1 >> (rs2[4:0])(RV32I)
rd = rs1 >> (rs2[5:0])(RV64I)
RV32I / RV64I
SRLIsrli rd, rs1, shamt立即数逻辑右移rd = rs1 >> shamtRV32I / RV64I
SRLWsrlw rd, rs1, rs232位逻辑右移(RV64I,低32位操作)rd = SignExt((rs1[31:0] >> rs2[4:0]))RV64I
SRLIWsrliw rd, rs1, shamt32位立即数逻辑右移(RV64I)rd = SignExt((rs1[31:0] >> shamt)[31:0])(shamt范围:0–31)RV64I
算术右移
SRAsra rd, rs1, rs2算术右移(高位补符号位)rd = rs1 >>> (rs2[4:0])(RV32I)
rd = rs1 >>> (rs2[5:0])(RV64I)
RV32I / RV64I
SRAIsrai rd, rs1, shamt立即数算术右移rd = rs1 >>> shamtRV32I / RV64I
SRAWsraw rd, rs1, rs232位算术右移(RV64I,低32位操作)rd = SignExt((rs1[31:0] >>> rs2[4:0]))RV64I
SRAIWsraiw rd, rs1, shamt32位立即数算术右移(RV64I)rd = SignExt((rs1[31:0] >>> shamt)[31:0])(shamt范围:0–31)RV64I

3.4 逻辑指令

逻辑指令用于对寄存器中的数据进行按位操作,分为以下两类:

  • 1.寄存器-寄存器操作:两个寄存器之间的按位运算。
  • 2.寄存器-立即数操作:寄存器与符号扩展后的立即数进行按位运算。
    在这里插入图片描述
指令格式功能描述操作(伪代码)指令集
按位与操作
ANDand rd, rs1, rs2按位与rd = rs1 & rs2RV32I / RV64Ity-reference
ANDIandi rd, rs1, imm立即数按位与(符号扩展立即数)rd = rs1 & SignExt(imm)RV32I / RV64Ity-reference
按位或操作
ORor rd, rs1, rs2按位或`rd = rs1rs2`
ORIori rd, rs1, imm立即数按位或(符号扩展立即数)`rd = rs1SignExt(imm)`
按位异或操作
XORxor rd, rs1, rs2按位异或rd = rs1 ^ rs2RV32I / RV64Ity-reference
XORIxori rd, rs1, imm立即数按位异或(符号扩展立即数)rd = rs1 ^ SignExt(imm)RV32I / RV64Ity-reference

伪指令

伪指令格式功能描述实际转换(基础指令)适用指令集
NOTnot rd, rs按位取反(rd = ~rs)xori rd, rs, -1RV32I / RV64I

3.5 比较-置位指令

指令根据两个操作数的比较结果设置目标寄存器的值为 1 或 0,用于条件判断和逻辑控制,支持有符号和无符号比较。

在这里插入图片描述

指令格式功能描述操作(伪代码)指令集
有符号比较
SLTslt rd, rs1, rs2有符号比较:若 rs1 < rs2,则 rd = 1,否则 rd = 0rd = (rs1 < rs2) ? 1 : 0 (有符号比较)RV32I / RV64Ity-reference
SLTIslti rd, rs1, imm有符号立即数比较:若 rs1 < SignExt(imm),则 rd = 1rd = (rs1 < SignExt(imm)) ? 1 : 0RV32I / RV64Ity-reference
无符号比较
SLTUsltu rd, rs1, rs2无符号比较:若 rs1 < rs2,则 rd = 1rd = (rs1 < rs2) ? 1 : 0 (无符号比较)RV32I / RV64Ity-reference
SLTIUsltiu rd, rs1, imm无符号立即数比较(立即数符号扩展后按无符号比较):若 rs1 < SignExt(imm),则 rd = 1rd = (rs1 < SignExt(imm)) ? 1 : 0 (无符号比较)RV32I / RV64Ity-reference

伪指令

伪指令格式功能描述实际转换(基础指令)适用指令集
零值判断
SEQZseqz rd, rs若 rs == 0,则 rd = 1,否则 0sltiu rd, rs, 1RV32I / RV64I
SNEZsnez rd, rs若 rs ≠ 0,则 rd = 1,否则 0sltu rd, x0, rsRV32I / RV64I
符号判断
SLTZsltz rd, rs若 rs < 0(有符号),则 rd = 1slt rd, rs, x0RV32I / RV64I
SGTZsgtz rd, rs若 rs > 0(有符号),则 rd = 1slt rd, x0, rsRV32I / RV64I
非零符号判断
SLEZslez rd, rs若 rs ≤ 0(有符号),则 rd = 1slt rd, x0, rs → xori rd, rd, 1RV32I / RV64I
SGEZsgez rd, rs若 rs ≥ 0(有符号),则 rd = 1slt rd, rs, x0 → xori rd, rd, 1RV32I / RV64I

3.6 分支指令

分支指令用于控制程序流程,根据条件或地址跳转执行目标代码,均为 B-Type 或 J-Type 格式。
在这里插入图片描述

条件分支指令

指令格式功能描述操作(伪代码)指令集
BEQbeq rs1, rs2, offset若 rs1 == rs2,跳转到 PC + offsetif (rs1 == rs2) PC += SignExt(offset << 1)RV32I / RV64I
BNEbne rs1, rs2, offset若 rs1 ≠ rs2,跳转到 PC + offsetif (rs1 != rs2) PC += SignExt(offset << 1)RV32I / RV64I
BLTblt rs1, rs2, offset若 rs1 < rs2(有符号),跳转if (rs1 < rs2) PC += SignExt(offset << 1)RV32I / RV64I
BGEbge rs1, rs2, offset若 rs1 ≥ rs2(有符号),跳转if (rs1 >= rs2) PC += SignExt(offset << 1)RV32I / RV64I
BLTUbltu rs1, rs2, offset若 rs1 < rs2(无符号),跳转if (rs1 < rs2) PC += SignExt(offset << 1)RV32I / RV64I
BGEUbgeu rs1, rs2, offset若 rs1 ≥ rs2(无符号),跳转if (rs1 >= rs2) PC += SignExt(offset << 1)RV32I / RV64I

条件分支伪指令

伪指令格式功能描述实际转换(基础指令)适用指令集
BEQZbeqz rs, offset若 rs == 0,跳转到 offsetbeq rs, x0, offsetRV32I / RV64I
BNEZbnez rs, offset若 rs ≠ 0,跳转到 offsetbne rs, x0, offsetRV32I / RV64I
BGTbgt rs1, rs2, offset若 rs1 > rs2(有符号),跳转blt rs2, rs1, offsetRV32I / RV64I
BGTUbgtu rs1, rs2, offset若 rs1 > rs2(无符号),跳转bltu rs2, rs1, offsetRV32I / RV64I
BLEble rs1, rs2, offset若 rs1 ≤ rs2(有符号),跳转bge rs2, rs1, offsetRV32I / RV64I
BLEUbleu rs1, rs2, offset若 rs1 ≤ rs2(无符号),跳转bgeu rs2, rs1, offsetRV32I / RV64I

3.7 跳转指令

跳转指令用于改变程序的执行流程,使程序能够跳转到代码中的其他位置执行
在这里插入图片描述

无条件跳转指令

指令格式功能描述操作(伪代码)指令集
JALjal rd, offset跳转到 PC + offset,并将返回地址存入 rdrd = PC + 4; PC += SignExt(offset << 1)RV32I / RV64I
JALRjalr rd, offset(rs1)跳转到 rs1 + offset,存入返回地址rd = PC + 4; PC = (rs1 + SignExt(offset)) & ~1RV32I / RV64I

无条件跳转伪指令

伪指令格式功能描述实际转换(基础指令)适用指令集
Jj offset无条件跳转到 offsetjal x0, offsetRV32I / RV64I
JRjr rs跳转到 rs 指向的地址jalr x0, 0(rs)RV32I / RV64I
RETret从函数返回(跳转到 ra 地址)jalr x0, 0(ra)RV32I / RV64I

3.8 同步指令

同步指令用于处理内存访问顺序控制,确保数据一致性和并发安全。

内存屏障指令

指令格式功能描述操作(伪代码)适用指令集
FENCEfence pred, succ内存屏障(控制访存顺序)确保 pred 操作在 succ 操作前完成 (pred/succ 可以为 r(读)、w(写)、i(指令流))RV32I / RV64I
FENCE.Ifence.i指令流同步屏障确保后续指令看到此前所有指令的修改(用于自修改代码)RV32I / RV64I)

3.9 环境指令

环境指令用于系统调用、调试、中断处理等特权级操作,通常需在特定权限模式下执行。

系统调用与异常处理指令

指令格式功能描述操作(伪代码)适用指令集
ECALLecall触发环境调用(系统调用/异常)根据当前模式跳转到异常处理程序RV32I / RV64I
EBREAKebreak触发断点异常(用于调试)进入调试模式或触发异常处理RV32I / RV64I

中断返回指令

指令格式功能描述操作(伪代码)适用指令集
MRETmret从机器模式异常返回PC = MEPC; Privilege = MPPRV32I / RV64I
SRETsret从监管者模式异常返回PC = SEPC; Privilege = SPPRV32I / RV64I
URETuret从用户模式异常返回PC = UEPCRV32I / RV64I

等待与暂停指令

指令格式功能描述操作(伪代码)适用指令集
WFIwfi等待中断(暂停执行直至中断发生)暂停 CPU 直至中断或事件唤醒RV32I / RV64I )

3.10 控制状态寄存器指令

指令用于读写处理器的控制状态寄存器(如中断配置、计数器、特权模式设置等),支持原子操作和位操作,适用于系统编程和特权级管理。
在这里插入图片描述

CSR 读写指令

指令格式功能描述操作(伪代码)适用指令集
CSRRWcsrrw rd, csr, rs1rs1 写入 CSR,原值存入 rdt = CSR[csr]; CSR[csr] = rs1; rd = tRV32I / RV64I
CSRRScsrrs rd, csr, rs1rs1 对应位设为 1,原值存入 rd`t = CSR[csr]; CSR[csr]= rs1; rd = t`
CSRRCcsrrc rd, csr, rs1rs1 对应位清 0,原值存入 rdt = CSR[csr]; CSR[csr] &= ~rs1; rd = tRV32I / RV64I
CSRRWIcsrrwi rd, csr, imm将 5 位立即数写入 CSRt = CSR[csr]; CSR[csr] = imm; rd = tRV32I / RV64I
CSRRSIcsrrsi rd, csr, imm将立即数对应位置 1`t = CSR[csr]; CSR[csr]= imm; rd = t`
CSRRCIcsrrci rd, csr, imm将立即数对应位清 0t = CSR[csr]; CSR[csr] &= ~imm; rd = tRV32I / RV64I

CSR 伪指令

伪指令格式功能描述实际转换(基础指令)适用指令集
CSRRcsrr rd, csr读取 CSR 的值到寄存器csrrs rd, csr, x0(读 CSR,不修改)RV32I / RV64I
CSRWcsrw csr, rs将寄存器的值写入 CSRcsrrw x0, csr, rs(丢弃原值,仅写入)RV32I / RV64I
CSRScsrs csr, rs设置 CSR 中由 rs 指定的位csrrs x0, csr, rs(按位或,不保存结果)RV32I / RV64I
CSRCcsrc csr, rs清除 CSR 中由 rs 指定的位csrrc x0, csr, rs(按位与取反,不保存结果)RV32I / RV64I
CSRWIcsrwi csr, imm将 5 位立即数写入 CSRcsrrwi x0, csr, immRV32I / RV64I
CSRSIcsrsi csr, imm设置 CSR 中由立即数指定的位csrrsi x0, csr, immRV32I / RV64I
CSRCIcsrci csr, imm清除 CSR 中由立即数指定的位csrrci x0, csr, immRV32I / RV64I

4 RVM指令集

RVM 扩展指令分为 乘法指令 和 除法/取余指令,支持有符号和无符号操作,并区分 RV32 和 RV64 的差异。
在这里插入图片描述

乘法指令

指令格式功能描述操作(伪代码)适用指令集
MULmul rd, rs1, rs2乘法(低32/64位结果)rd = (rs1 * rs2)[31:0](RV32)
rd = rs1 * rs2(RV64)
RV32M / RV64M
MULHmulh rd, rs1, rs2有符号乘法(高32/64位结果)rd = (rs1 * rs2)[63:32](RV32)
rd = (rs1 * rs2)[127:64](RV64)
RV32M / RV64M
MULHUmulhu rd, rs1, rs2无符号乘法(高32/64位结果)同上,操作数为无符号数RV32M / RV64M
MULHSUmulhsu rd, rs1, rs2有符号-无符号乘法(高32/64位结果)rs1 有符号,rs2 无符号RV32M / RV64M
MULWmulw rd, rs1, rs232位乘法(结果符号扩展至64位)rd = SignExt((rs1[31:0] * rs2[31:0]))RV64M

除法/取余指令

指令格式功能描述操作(伪代码)适用指令集
DIVdiv rd, rs1, rs2有符号除法(商)rd = rs1 / rs2(向零舍入)RV32M / RV64M
DIVUdivu rd, rs1, rs2无符号除法(商)rd = rs1 / rs2RV32M / RV64M
REMrem rd, rs1, rs2有符号取余(余数)rd = rs1 % rs2(符号与 rs1 相同)RV32M / RV64M
REMUremu rd, rs1, rs2无符号取余(余数)rd = rs1 % rs2RV32M / RV64M
DIVWdivw rd, rs1, rs232位有符号除法(符号扩展至64位)rd = SignExt((rs1[31:0] / rs2[31:0]))RV64M
DIVUWdivuw rd, rs1, rs232位无符号除法(零扩展至64位)rd = ZeroExt((rs1[31:0] / rs2[31:0]))RV64M
REMWremw rd, rs1, rs232位有符号取余(符号扩展至64位)rd = SignExt((rs1[31:0] % rs2[31:0]))RV64M
REMUWremuw rd, rs1, rs232位无符号取余(零扩展至64位)rd = ZeroExt((rs1[31:0] % rs2[31:0]))RV64M

5 RVFD指令集

5.1 访存指令

指令用于在内存和浮点寄存器(f0-f31)之间传输单精度(F 扩展)或双精度(D 扩展)浮点数据:
在这里插入图片描述

浮点加载和存储指令

指令格式功能描述操作(伪代码)适用指令集
FLWflw fd, offset(rs1)从内存加载单精度浮点数到浮点寄存器fd = F32(Mem[rs1 + offset])RV32F / RV64F
FSWfsw fs, offset(rs1)将单精度浮点数从浮点寄存器存入内存Mem[rs1 + offset] = F32(fs)RV32F / RV64F
FLDfld fd, offset(rs1)从内存加载双精度浮点数到浮点寄存器fd = F64(Mem[rs1 + offset])RV64D
FSDfsd fs, offset(rs1)将双精度浮点数从浮点寄存器存入内存Mem[rs1 + offset] = F64(fs)RV64D

5.2 算术指令

算术指令用于执行各种数学运算,如加法、减法、乘法、除法等。当涉及到浮点数时,这些操作变得更为复杂,因为它们需要处理指数和尾数部分

在这里插入图片描述

基本算术指令

指令类型指令格式功能描述操作(伪代码)适用指令集
加法FADD.Sfadd.s fd, fs1, fs2单精度浮点加法fd = fs1 + fs2RV32F / RV64F
FADD.Dfadd.d fd, fs1, fs2双精度浮点加法fd = fs1 + fs2RV64D
减法FSUB.Sfsub.s fd, fs1, fs2单精度浮点减法fd = fs1 - fs2RV32F / RV64F
FSUB.Dfsub.d fd, fs1, fs2双精度浮点减法fd = fs1 - fs2RV64D
乘法FMUL.Sfmul.s fd, fs1, fs2单精度浮点乘法fd = fs1 * fs2RV32F / RV64F
FMUL.Dfmul.d fd, fs1, fs2双精度浮点乘法fd = fs1 * fs2RV64D
除法FDIV.Sfdiv.s fd, fs1, fs2单精度浮点除法fd = fs1 / fs2RV32F / RV64F
FDIV.Dfdiv.d fd, fs1, fs2双精度浮点除法fd = fs1 / fs2RV64D
平方根FSQRT.Sfsqrt.s fd, fs1单精度浮点平方根fd = sqrt(fs1)RV32F / RV64F
FSQRT.Dfsqrt.d fd, fs1双精度浮点平方根fd = sqrt(fs1)RV64D
最小值FMIN.Sfmin.s fd, fs1, fs2单精度浮点最小值fd = min(fs1, fs2)RV32F / RV64F
FMIN.Dfmin.d fd, fs1, fs2双精度浮点最小值fd = min(fs1, fs2)RV64D
最大值FMAX.Sfmax.s fd, fs1, fs2单精度浮点最大值fd = max(fs1, fs2)RV32F / RV64F
FMAX.Dfmax.d fd, fs1, fs2双精度浮点最大值fd = max(fs1, fs2)RV64D

5.3 RVFD 乘加指令

指令用于执行 乘加融合运算(Fused Multiply-Add, FMA),即在一个操作中完成乘法和加法,通常具有更高的精度和性能
在这里插入图片描述

指令类型指令格式功能描述操作(伪代码)适用指令集
单精度乘加FMADD.Sfmadd.s fd, fs1, fs2, fs3单精度浮点乘加fd = (fs1 * fs2) + fs3RV32F / RV64F
单精度乘减FMSUB.Sfmsub.s fd, fs1, fs2, fs3单精度浮点乘减fd = (fs1 * fs2) - fs3RV32F / RV64F
单精度负乘加FNMADD.Sfnmadd.s fd, fs1, fs2, fs3单精度浮点负乘加fd = -((fs1 * fs2) + fs3)RV32F / RV64F
单精度负乘减FNMSUB.Sfnmsub.s fd, fs1, fs2, fs3单精度浮点负乘减fd = -((fs1 * fs2) - fs3)RV32F / RV64F
双精度乘加FMADD.Dfmadd.d fd, fs1, fs2, fs3双精度浮点乘加fd = (fs1 * fs2) + fs3RV64D
双精度乘减FMSUB.Dfmsub.d fd, fs1, fs2, fs3双精度浮点乘减fd = (fs1 * fs2) - fs3RV64D
双精度负乘加FNMADD.Dfnmadd.d fd, fs1, fs2, fs3双精度浮点负乘加fd = -((fs1 * fs2) + fs3)RV64D
双精度负乘减FNMSUB.Dfnmsub.d fd, fs1, fs2, fs3双精度浮点负乘减fd = -((fs1 * fs2) - fs3)RV64D

5.4 RVFD传送指令

指令用于在 浮点寄存器 和 整数寄存器 之间传输数据,或在不同浮点寄存器之间复制数据
在这里插入图片描述

指令类型指令格式功能描述操作(伪代码)适用指令集
浮点到整数FMV.X.Sfmv.x.s rd, fs1将单精度浮点数转为整数表示rd = fs1(按位复制)RV32F / RV64F
浮点到整数FMV.X.Dfmv.x.d rd, fs1将双精度浮点数转为整数表示rd = fs1(按位复制)RV64D
整数到浮点FMV.S.Xfmv.s.x fd, rs1将整数表示转为单精度浮点数fd = rs1(按位复制)RV32F / RV64F
整数到浮点FMV.D.Xfmv.d.x fd, rs1将整数表示转为双精度浮点数fd = rs1(按位复制)RV64D

5.5 RVFD 转换指令

分两类归纳:浮点寄存器间传送 和 浮点与整数寄存器间传送,涵盖符号操作、位模式复制及特殊值处理
在这里插入图片描述

浮点与整数之间的转换

指令类型指令格式功能描述操作(伪代码)适用指令集
浮点 → 整数FCVT.W.Sfcvt.w.s rd, fs1单精度浮点转为 32 位有符号整数rd = (int32_t)fs1RV32F / RV64F
FCVT.WU.Sfcvt.wu.s rd, fs1单精度浮点转为 32 位无符号整数rd = (uint32_t)fs1RV32F / RV64F
FCVT.L.Sfcvt.l.s rd, fs1单精度浮点转为 64 位有符号整数rd = (int64_t)fs1RV64F
FCVT.LU.Sfcvt.lu.s rd, fs1单精度浮点转为 64 位无符号整数rd = (uint64_t)fs1RV64F
FCVT.W.Dfcvt.w.d rd, fs1双精度浮点转为 32 位有符号整数rd = (int32_t)fs1RV64D
FCVT.WU.Dfcvt.wu.d rd, fs1双精度浮点转为 32 位无符号整数rd = (uint32_t)fs1RV64D
FCVT.L.Dfcvt.l.d rd, fs1双精度浮点转为 64 位有符号整数rd = (int64_t)fs1RV64D
FCVT.LU.Dfcvt.lu.d rd, fs1双精度浮点转为 64 位无符号整数rd = (uint64_t)fs1RV64D
整数 → 浮点FCVT.S.Wfcvt.s.w fd, rs132 位有符号整数转为单精度浮点fd = (float)rs1RV32F / RV64F
FCVT.S.WUfcvt.s.wu fd, rs132 位无符号整数转为单精度浮点fd = (float)rs1RV32F / RV64F
FCVT.S.Lfcvt.s.l fd, rs164 位有符号整数转为单精度浮点fd = (float)rs1RV64F
FCVT.S.LUfcvt.s.lu fd, rs164 位无符号整数转为单精度浮点fd = (float)rs1RV64F
FCVT.D.Wfcvt.d.w fd, rs132 位有符号整数转为双精度浮点fd = (double)rs1RV64D
FCVT.D.WUfcvt.d.wu fd, rs132 位无符号整数转为双精度浮点fd = (double)rs1RV64D
FCVT.D.Lfcvt.d.l fd, rs164 位有符号整数转为双精度浮点fd = (double)rs1RV64D
FCVT.D.LUfcvt.d.lu fd, rs164 位无符号整数转为双精度浮点fd = (double)rs1RV64D

浮点精度之间的转换

指令类型指令格式功能描述操作(伪代码)适用指令集
单精度 ↔ 双精度FCVT.S.Dfcvt.s.d fd, fs1双精度浮点转为单精度浮点fd = (float)fs1RV64D
单精度 ↔ 双精度FCVT.D.Sfcvt.d.s fd, fs1单精度浮点转为双精度浮点fd = (double)fs1RV64D

5.6 RVFD 符号注入指令

指令用于将 整数立即数 或 整数寄存器值 注入到浮点寄存器中,通常用于快速构造浮点常数或特殊值(如 NaN、无穷大)
在这里插入图片描述

单精度浮点注入指令

指令类型指令格式功能描述操作(伪代码)适用指令集
符号复制FSGNJ.Sfsgnj.s fd, fs1, fs2复制数值,符号位取自 fs2fd = {fs2[31], fs1[30:0]}RV32F / RV64F
符号取反FSGNJN.Sfsgnjn.s fd, fs1, fs2复制数值,符号位取反自 fs2fd = {~fs2[31], fs1[30:0]}RV32F / RV64F
符号取绝对值FSGNJX.Sfsgnjx.s fd, fs1, fs2复制数值,符号位异或(取绝对值)fd = {fs1[31] ^ fs2[31], fs1[30:0]}RV32F / RV64F

双精度浮点注入指令

指令类型指令格式功能描述操作(伪代码)适用指令集
符号复制FSGNJ.Dfsgnj.d fd, fs1, fs2复制数值,符号位取自 fs2fd = {fs2[63], fs1[62:0]}RV64D
符号取反FSGNJN.Dfsgnjn.d fd, fs1, fs2复制数值,符号位取反自 fs2fd = {~fs2[63], fs1[62:0]}RV64D
符号取绝对值FSGNJX.Dfsgnjx.d fd, fs1, fs2复制数值,符号位异或(取绝对值)fd = {fs1[63] ^ fs2[63], fs1[62:0]}RV64D

伪指令

指令类型伪指令格式功能描述实际转换(基础指令)适用指令集
单精度浮点注入FABS.Sfabs.s fd, fs单精度浮点取绝对值fsgnjx.s fd, fs, fsRV32F / RV64F
FMV.Sfmv.s fd, fs单精度浮点复制fsgnj.s fd, fs, fsRV32F / RV64F
FNEG.Sfneg.s fd, fs单精度浮点取反fsgnjn.s fd, fs, fsRV32F / RV64F
指令类型伪指令格式功能描述实际转换(基础指令)适用指令集
双精度浮点注入FABS.Dfabs.d fd, fs双精度浮点取绝对值fsgnjx.d fd, fs, fsRV64D
FMV.Dfmv.d fd, fs双精度浮点复制fsgnj.d fd, fs, fsRV64D
FNEG.Dfneg.d fd, fs双精度浮点取反fsgnjn.d fd, fs, fsRV64D

5.7 RVFD 比较指令

指令用于比较两个浮点数的值,并将比较结果写入整数寄存器,支持 相等、小于 和 小于等于 三种比较操作
在这里插入图片描述

指令类型指令格式功能描述操作(伪代码)适用指令集
相等比较FEQ.Sfeq.s rd, fs1, fs2单精度浮点相等比较rd = (fs1 == fs2) ? 1 : 0RV32F / RV64F
FEQ.Dfeq.d rd, fs1, fs2双精度浮点相等比较rd = (fs1 == fs2) ? 1 : 0RV64D
小于比较FLT.Sflt.s rd, fs1, fs2单精度浮点小于比较rd = (fs1 < fs2) ? 1 : 0RV32F / RV64F
FLT.Dflt.d rd, fs1, fs2双精度浮点小于比较rd = (fs1 < fs2) ? 1 : 0RV64D
小于等于比较FLE.Sfle.s rd, fs1, fs2单精度浮点小于等于比较rd = (fs1 <= fs2) ? 1 : 0RV32F / RV64F
FLE.Dfle.d rd, fs1, fs2双精度浮点小于等于比较rd = (fs1 <= fs2) ? 1 : 0RV64D

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)操作
读取 fcsrFRCSRfrcsr rd读取 fcsr 的值到整数寄存器rd = fcsrRV32F / RV64F
写入 fcsrFSCSRfscsr rd, rs将整数寄存器的值写入 fcsrfcsr = rsRV32F / RV64F
交换 fcsrFSRCSfscsr rd, rs交换 fcsr 和整数寄存器的值t = fcsr; fcsr = rs; rd = tRV32F / RV64F
舍入模式配置
读取舍入模式FRRMfrrm rd读取舍入模式到整数寄存器rd = fcsr[7:5]RV32F / RV64F
写入舍入模式FSRMfsrm rd, rs将整数寄存器的值写入舍入模式fcsr[7:5] = rs[2:0]RV32F / RV64F
交换舍入模式FSRRMfsrrm rd, rs交换舍入模式和整数寄存器的值t = fcsr[7:5]; fcsr[7:5] = rs[2:0]; rd = tRV32F / RV64F
异常标志操作
读取异常标志FFLAGSfflags rd读取异常标志到整数寄存器rd = fcsr[4:0]RV32F / RV64F
写入异常标志FSFLAGSfsflags rd, rs将整数寄存器的值写入异常标志fcsr[4:0] = rs[4:0]RV32F / RV64F
交换异常标志FSRFLAGSfsrflags rd, rs交换异常标志和整数寄存器的值t = fcsr[4:0]; fcsr[4:0] = rs[4:0]; rd = tRV32F / RV64F

6 RVA指令集

RVA(Atomic Operations)扩展为 RISC-V 提供了硬件支持的原子操作指令,用于在多线程或多核环境中实现 原子内存访问 和 同步操作,确保数据一致性和并发安全。
在这里插入图片描述

加载保留与条件存储指令

指令类型指令格式功能描述操作(伪代码)适用指令集
加载保留LR.Wlr.w rd, (rs1)加载保留(原子加载字,标记内存地址)rd = Mem[rs1]; Reserve rs1RV32A / RV64A
LR.Dlr.d rd, (rs1)加载保留(原子加载双字)rd = Mem[rs1]; Reserve rs1RV64A
条件存储SC.Wsc.w rd, rs2, (rs1)条件存储(若地址未被修改,存储字)if (Reserve rs1 still valid) { Mem[rs1] = rs2; rd = 0 } else { rd = 1 }RV32A / RV64A
SC.Dsc.d rd, rs2, (rs1)条件存储(若地址未被修改,存储双字)if (Reserve rs1 still valid) { Mem[rs1] = rs2; rd = 0 } else { rd = 1 }RV64A

原子内存操作指令

指令类型指令格式功能描述操作(伪代码)适用指令集
原子加AMOADD.Wamoadd.w rd, rs2, (rs1)原子加并返回原值rd = Mem[rs1]; Mem[rs1] += rs2RV32A / RV64A
AMOADD.Damoadd.d rd, rs2, (rs1)原子加并返回原值(双字)rd = Mem[rs1]; Mem[rs1] += rs2RV64A
原子交换AMOSWAP.Wamoswap.w rd, rs2, (rs1)原子交换并返回原值rd = Mem[rs1]; Mem[rs1] = rs2RV32A / RV64A
AMOSWAP.Damoswap.d rd, rs2, (rs1)原子交换并返回原值(双字)rd = Mem[rs1]; Mem[rs1] = rs2RV64A
原子按位与AMOAND.Wamoand.w rd, rs2, (rs1)原子按位与并返回原值rd = Mem[rs1]; Mem[rs1] &= rs2RV32A / RV64A
AMOAND.Damoand.d rd, rs2, (rs1)原子按位与并返回原值(双字)rd = Mem[rs1]; Mem[rs1] &= rs2RV64A
原子按位或AMOOR.Wamoor.w rd, rs2, (rs1)原子按位或并返回原值`rd = Mem[rs1]; Mem[rs1]= rs2`
AMOOR.Damoor.d rd, rs2, (rs1)原子按位或并返回原值(双字)`rd = Mem[rs1]; Mem[rs1]= rs2`
原子按位异或AMOXOR.Wamoxor.w rd, rs2, (rs1)原子按位异或并返回原值rd = Mem[rs1]; Mem[rs1] ^= rs2RV32A / RV64A
AMOXOR.Damoxor.d rd, rs2, (rs1)原子按位异或并返回原值(双字)rd = Mem[rs1]; Mem[rs1] ^= rs2RV64A
原子最大值AMOMAX.Wamomax.w rd, rs2, (rs1)原子有符号最大值并返回原值rd = Mem[rs1]; Mem[rs1] = max(rd, rs2)RV32A / RV64A
AMOMAX.Damomax.d rd, rs2, (rs1)原子有符号最大值并返回原值(双字)rd = Mem[rs1]; Mem[rs1] = max(rd, rs2)RV64A
原子无符号最大值AMOMAXU.Wamomaxu.w rd, rs2, (rs1)原子无符号最大值并返回原值rd = Mem[rs1]; Mem[rs1] = maxu(rd, rs2)RV32A / RV64A
AMOMAXU.Damomaxu.d rd, rs2, (rs1)原子无符号最大值并返回原值(双字)rd = Mem[rs1]; Mem[rs1] = maxu(rd, rs2)RV64A
原子最小值AMOMIN.Wamomin.w rd, rs2, (rs1)原子有符号最小值并返回原值rd = Mem[rs1]; Mem[rs1] = min(rd, rs2)RV32A / RV64A
AMOMIN.Damomin.d rd, rs2, (rs1)原子有符号最小值并返回原值(双字)rd = Mem[rs1]; Mem[rs1] = min(rd, rs2)RV64A
原子无符号最小值AMOMINU.Wamominu.w rd, rs2, (rs1)原子无符号最小值并返回原值rd = Mem[rs1]; Mem[rs1] = minu(rd, rs2)RV32A / RV64A
AMOMINU.Damominu.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 常用汇编指令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/30162.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

双指针8:18. 四数之和

链接&#xff1a;18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; 本题和三数之和基本一样&#xff0c;参见双指针7&#xff1a;LCR 007. 三数之和-CSDN博客 class Solution { public:vector<vector<int>> fourSum(vector<int>&am…

EasyRTC嵌入式音视频通话SDK:基于ICE与STUN/TURN的实时音视频通信解决方案

在当今数字化时代&#xff0c;实时音视频通信技术已成为人们生活和工作中不可或缺的一部分。无论是家庭中的远程看护、办公场景中的远程协作&#xff0c;还是工业领域的远程巡检和智能设备的互联互通&#xff0c;高效、稳定的通信技术都是实现这些功能的核心。 EasyRTC嵌入式音…

腾讯云物联网平台(IoT Explorer)设备端使用

1、直接看图流程 2、跑起来demo,修改产品id,设备名称,设备秘钥。 3、连接部分 4、修改默认地址和端口 sdk里面的地址默认是带着产品ID拼接的,咱们现在中铁没有泛域名解析,要改下这里。把+productID都去掉,然后地址里的.也去掉。

揭开AI-OPS 的神秘面纱 第四讲 AI 模型服务层(自研方向)

AI 模型服务层技术架构与组件选型分析(自研方向) 基于自有开发寻训练方向 AI 模型服务层 是 AI-Ops 架构的 核心智能引擎,负责构建、训练、部署、管理和监控各种 AI 模型,为上层应用服务层提供智能分析和决策能力。 AI 模型服务层需要提供一个灵活、可扩展、高性能的平台…

electron + vue3 + vite 主进程到渲染进程的单向通信

用示例讲解下主进程到渲染进程的单向通信 初始版本项目结构可参考项目&#xff1a;https://github.com/ylpxzx/electron-forge-project/tree/init_project 主进程到渲染进程&#xff08;单向&#xff09; 以Electron官方文档给出的”主进程主动触发动作&#xff0c;发送内容给渲…

在人工智能软件的帮助下学习编程实例

1 引言 本文记录在人工智能软件的帮助下学习一种全新的编程环境的实例&#xff0c;之所以提人工智能软件而不是单指DeepSeek&#xff0c;一方面DeepSeek太火了&#xff0c;经常服务器繁忙&#xff0c;用本机本地部署的最多运行70b模型&#xff0c;又似乎稍差。另一方面也作为一…

记录一下Django的密码重置(忘记密码)

一. Django默认的密码重置 1.路由 # url.pyfrom django.contrib.auth import views as auth_viewsurlpatterns [# 密码重置path(password_reset/, auth_views.PasswordResetView.as_view(), namepassword_reset),# 用户输入邮箱后&#xff0c;跳转到此页面path(password_res…

零售交易流程相关知识(top-down拆解)

引入 关于POS机交易时的后台数据交互 模块之间数据交换&#xff0c;都可以能被窃取或篡改。由此引入加密、解密机制和签名、验签机制 经典的加密、解密机制&#xff1a; 对称加密&#xff1a;DES\ TDES\ AES\ RC4 非对称加密&#xff1a;RSA\ DSA\ ECC 经典的签名、验签…

Web网页开发——水果忍者

1.介绍 复刻经典小游戏——水果忍者 2.预览 3.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

项目实战--网页五子棋(对战功能)(8)

上期我们完成了websocket建立连接后的数据初始化&#xff0c;今天我们完成落子交互的具体代码&#xff1a; 这里我们先复习一下&#xff0c;之前约定好的落子请求与响应包含的字段&#xff1a; 1. 发送落子请求 我们在script.js文件中找到落子的相关方法&#xff0c;增加发送请…

从0开始的操作系统手搓教程24——完成我们的键盘驱动子系统

目录 所以&#xff0c;我们现来说说转义字符 我们需要如何处理扫描码 当键入的是双字符键时 当键入的是字母键时 下一篇 我们下面来看看我们的键盘驱动子系统是一个怎么个事情。 驱动程序&#xff0c;你可以认为是对硬件的一层封装。我们按照手册规格的规定姿势&#xff0…

根据输入汉字生成带拼音的米字格字帖

实现了下面功能&#xff1a; 1、根据输入汉字&#xff0c;自动调整米字格和四线格的行数&#xff1b; 2、给汉字自动加上拼音和声调&#xff08;暂时不考虑多音字&#xff09;&#xff1b; 3、汉字在米字格&#xff0c;拼音在四线格&#xff0c; 4、第一列用黑色&#xff0c;2-…

软件高级架构师 - 软件工程

补充中 测试 测试类型 静态测试 动态测试 测试阶段 单元测试中&#xff0c;包含性能测试&#xff0c;如下&#xff1a; 集成测试中&#xff0c;包含以下&#xff1a; 维护 遗留系统处置 高水平低价值&#xff1a;采取集成 对于这类系统&#xff0c;采取 集成 的方式&…

DeepSeek专题:DeepSeek-V2核心知识点速览

AIGCmagic社区知识星球是国内首个以AIGC全栈技术与商业变现为主线的学习交流平台&#xff0c;涉及AI绘画、AI视频、大模型、AI多模态、数字人以及全行业AIGC赋能等100应用方向。星球内部包含海量学习资源、专业问答、前沿资讯、内推招聘、AI课程、AIGC模型、AIGC数据集和源码等…

电脑如何拦截端口号,实现阻断访问?

如果你弟弟喜欢玩游戏&#xff0c;你可以查询该应用占用的端口&#xff0c;结合以下方法即可阻断端口号&#xff0c;让弟弟好好学习&#xff0c;天天向上&#xff01; 拦截端口可以通过防火墙和路由器进行拦截 &#xff0c;以下是常用方法&#xff1a; 方法 1&#xff1a;使用…

【NLP 32、文本匹配任务 —— 深度学习】

大劫大难以后&#xff0c;人不该失去锐气&#xff0c;不该失去热度&#xff0c;你镇定了却依旧燃烧&#xff0c;你平静了却依旧浩荡&#xff0c;致那个从绝望中走出来的自己&#xff0c;共勉 —— 25.1.31 使用深度学习在文本匹配任务上主要有两种方式&#xff1a;① 表示型 ②…

【AD】5-15 Active Route的自动布线辅助

1.如图所示点击Panels&#xff0c;打开Active Route 2.按如图设置后&#xff0c;点击向导走线确定好走向后&#xff0c;在点击自动辅助布线&#xff0c;布好后可自行微调

使用 Arduino 和 ThingSpeak 通过 Internet 进行心跳监测

使用 Arduino 和 ThingSpeak 通过 Internet 进行心跳监测 在这个项目中,我们将使用 Arduino 制作一个心跳检测和监测系统,该系统将使用脉搏传感器检测心跳,并在与其连接的 LCD 上显示 BPM(每分钟心跳次数)读数。它还将使用 Wi-Fi 模块ESP8266将读数发送到 ThingSpeak 服务…

正则表达式,idea,插件anyrule

​​​​package lx;import java.util.regex.Pattern;public class lxx {public static void main(String[] args) {//正则表达式//写一个电话号码的正则表达式String regex "1[3-9]\\d{9}";//第一个数字是1&#xff0c;第二个数字是3-9&#xff0c;后面跟着9个数字…

分析不同高度障碍物检测情况

import re import matplotlib.pyplot as plt from datetime import datetime import matplotlib.dates as mdates from matplotlib.font_manager import FontProperties# 设置中文字体 font_path /usr/local/sunlogin/res/font/wqy-zenhei.ttc # 替换为你的实际字体路径 my_f…