• RISCV汇编指令


    CPU寄存器

    RegisterABIDiscriptionAttribution
    x0zero硬件常数0N/A
    x1ra返回地址Caller
    x2sp栈指针Callee
    x3gp全局指针-
    x4tp线程指针-
    x5-x7t0-t2临时变量Caller
    x8s0/fp保存寄存器/帧指针Callee
    x9s1保存寄存器Callee
    x10-x11a0-a1函数参数/返回值Caller
    x12-x17a2-a7函数参数Caller
    x18-x27s2-s11保存寄存器Callee
    x28-x31t3-t6临时变量Caller
    f0-f7ft0-ft7浮点临时变量Caller
    f8-f9fs0-fs1浮点保存寄存器Callee
    f10-f11fa0-fa1浮点函数参数/返回值Caller
    f12-f17fa2-fa7浮点函数参数Caller
    f18-f27fs2-fs11浮点保存寄存器Callee
    f28-f31ft8-ft11浮点临时变量Caller

    32位RISC-V(RV32)指令集概述

    典型汇编语句

    label:opcodeoperandscomment
    标签操作码操作数注释
    • 标签:表示当前指令的位置标记
    • 操作码:操作码主要有以下几种形式
      • RISC-V标准指令
      • 伪指令
      • 用户自定义宏
    • 操作数:
      • 操作码所需的操作,与操作码之间以空格分开
      • 符号、常量、或是符号与常量组成的表达式

    指令机器码格式

    • I型指令

      imm[11:0]rs1funct3rdopcode
      [31:20][19:15][14:12][11:7][6:0]
    • U型指令

      imm[31:12]rdopcode
      [31:12][11:7][6:0]
    • S型指令

      imm[11:5]rs2rs1imm[4:0]rdopcode
      [31:25][24:20][19:15][14:12][11:7][6:0]
    • R型指令

      funct7rs2rs1funct3rdopcode
      [31:25][24:20][19:15][14:12][11:7][6:0]
    • B型指令

    • J型指令

    RV32I基本指令集

    说明:为了展示指令之间的层次结构,在这里使用了多级无序列表,每个指令后的括号即该指令的英文全称,方便理解相似指令在不同环境下的运用,而大写部分则是指令缩写所提取的字母,另外划有删除线代表本身不存在但具有分支应用的指令;后续也可能会画一个树表作为补充。

    算术指令

    • add

       
        
      ADD:
      add rd,rs

      等效于rd = rd + rs

      • addi(add immediate)
         
            
        ADDI:
        addi rd,rs1,imm
    • or

      • ori(OR Immediate)
    • xor(eXclusive OR)

      • xori(eXclusive OR Immediate)
    • shift

      • sll(Shift Left Logical)
        • slli(Shift Left Logical Immediate)
      • sra(Shift Right Arithmetic)
        • srai(Shift Right Arithmetic Immediate)
      • srl(Shift Right Logical)
        • srli(Shift Right Logical Immediate)
    • sub(SUBtract)

    • lui(Load Upper Immediate)
      将一个16位的立即数填入寄存器的高16位中,低16位则补零

    • auipc(Add Upper Immediate to PC)

    • slt(Set Less Than)

      • slti(Set Less Than Immediate)
        • sltiu(Set Less Than Immediate Unsigned)

    加载指令

    • load

      • lb(Load Byte)
        • lbu(Load Byte Unsigned)
      • lh(Load Halfword)
        读16位,符号位拓展后写入寄存器rd中
        • lhu(Load Halfword Unsigned)
          读16位,高位补0,写入寄存器rd中
      • lw(Load Word)
        从存储器中读回一个32位的数据,写入寄存器rd中
    • store

      • sb(store Byte)
      • sh(store Halfword)
      • sw(store Word)

    条件分支指令

    • branch
      • beq(branch equal)
        比较两个寄存器内部的值,若相等便跳转至指定标签位置,否则继续顺序执行。
      • bne(branch not equal)
        比较两个寄存器内部的值,如果结果不相等,则跳转至指定标签位置,反之继续顺序执行。
      • bge(Branch Greater than or Equal)
        当前操作数大于等于后者时,跳转到分支标签内容,否则继续执行顺序内容。
        • bgeu(Branch Greater than or Equal Unsigned)
          对参数以无符号格式进行比较,其他部分逻辑与bge指令相同
      • blt(Branch Less Than)
        当前操作数小于(但不等于)后者时,跳转到分支标签内容,不然继续执行顺序内容。
        • bltu(Branch Less Than Unsigned)

    小于等于、大于判断可以通过颠倒操作数位置来实现,注意逻辑和边际问题即可。
    站在芯片运行优化的角度,设计的比较条件应该尽可能倾向于程序顺序执行,以减少在判断跳转之间的时间消耗。

     
    
    BRANCH:
    opcode rs1,rs2,LABEL;

    跳转控制指令

    • jal(Jump And Link)
      • jalr(Jump And Link Register)

    寄存器屏障指令

    • fence

    • break

      • ebreak
    • call

      • ecall
    • csr

      • csrrc(Control Status Register Read & Clear bit)
        • csrrci(Control Status Register Read & Clear bit Immediate)
      • csrrs(Control Status Register Read & Set bit)
        • csrrsi(Control Status Register Read & Set bit Immediate)
      • csrrw(Control Status Register Read & Write bit)
        • csrrwi(Control Status Register Read & Write bit Immediate)

    RV32标准拓展指令

    RV32M标准拓展指令

    • mul
      • mulh
        • mulhsu
        • mulhu
    • div
      • divu
    • rem
      • remu

    RV32A标准拓展指令

    • lr.w
    • sc.w
    • amo
      • amoswap.w
      • amoadd.w
      • amoxor.w
      • amoand.w
      • amoor.w
      • amomin.w
      • amomax.w
      • amominu.w
      • amomaxu.w

    RV32F标准拓展指令

    • flw
    • fsw
    • fmadd.s
    • fmsub.s
    • fnmsub.s
    • snmadd.s
    • fadd.s
    • fsub.s
    • fmul.s
    • fdiv.s
    • fsqrt.s
    • fsgnj.s
      • fsgnjn.s
      • fsgnjx.s
    • fmin.s
    • fmax.s
    • fcvt.w.s
      • fcvt.wu.s
    • fmv.x.s
    • feq.s
    • flt.s
    • fclass.s
    • fcvt.s.w
    • fcvt.s.wu
    • fmv.s.x

    伪指令

    实际上是由基本指令组合而成

    加载伪指令

    • la(Load Address)
      加载地址
    • ld(LoaD)
      加载全局参数

    算术伪指令

    • nop
       
        
      NOP:
      nop
      执行一个空操作
    • li(Load Immediate)
       
        
      LI:
      li rd,imm;
      将imm代表的立即数直接赋值rd寄存器
    • mv(MOV)
    • not
    • neg
    • negw
    • sext
    • seqz
    • snez
    • sltz
    • sgtz

    浮点算术伪指令

    • fmv.s
    • fabs.s
    • fneg.s
    • fmv.d
    • fabs.d
    • feng.d

    条件分支伪指令

    • beqz
    • bnez
    • blez
    • bgez
    • bltz
    • bgtz

    跳转控制伪指令

    • j
    • jal
    • jr
    • jalr
    • ret
    • tail

    启动

    • .global(.globl)
      伪操作,用于定义全局符号,使链接过程中能被其他程序文件可见,类似于extern

    • .local
      伪操作,用于定义局部符号,仅当前程序文件可见

    • .file
      伪操作,用于指示汇编器该汇编程序的逻辑文件名

      opcodeoprands
      .file"filename"
    • .section

      • .text
      • .data
      • .rodata
      • .bss
    • .type

    • .align

      • .balign
    • .zero

    • .byte

      • 2byte
      • 4byte
      • 8byte
    • .float

      • .double
    • .word

      • .half
      • .dword
    • .string

    • .equ

    • .weak
      伪操作,同时创建符号并定义为弱属性。如果该符号已定义,则设置此符号为弱属性

      • 在汇编程序中,符号的默认属性为强(strong)

      如果符号的属性为弱,则可无需定义具体内容,常用于预留空符号并通过汇编语法检查。当另外存在一个属性为强的同名符号实体时会自动覆盖并链接

    • .pushsection - .popsection

    • .marco - .endm

    • .comm(.common)

    • .option

    注释

    以符号 # 或 ; 作为分隔号,当行分隔号以后的部分会被视作注释

    代指

    • rd(Register Destination)

    指目标寄存器,实际代码中可以是t0、t1等

    代码格式(C语言嵌套汇编)

    在C语言文件中嵌入汇编代码,除对固定地址寄存器并直接进行操作外,需要将变量等参数传入汇编程序中,才能保证操作有效,想要传入参数,需要通过操作符列表来完成

    关键字

    • asm
      为GCC的关键字,表示进行内联汇编操作,也可以使用前后各带两个下划线的__asm___asm_是GCC关键字asm的宏定义。

    • volatile
      或者_volatile__volatile_volatile,均为宏定义。如果添加了该关键字,则通知编译器避免对后续括号内添加汇编程序进行任何优化,以保持其原状

    • 汇编指令列表
      即需要嵌入的汇编指令,每条指令必须被双引号括起来(作为字符串),两条指令之前必须以“\n”或者“;”作为分隔符。如果没有添加分隔符,相连的字符串将会被合并成为一个字符串。内部语法与汇编程序一样

    标记符号

    • %
      后面跟标签则为指定,若为数字则是从操作符列表顺序选择

    • [ ]
      方括号中的符号名,用于将内联汇编程序中使用的操作数和此操作符通过名称绑定起来。标签名称随意,但不能重复

    • “ ”
      引号中的限制字符串,用于约束此操作数变量的属性,常用的约束如:

      • r
        代表使用编译器自动分配的寄存器来存储该操作数变量

      • m
        字母“m”代表使用内存地址来存储该操作数变量,如果同时指明“rm”则编译器自动选择最优方案

      • =
        对于输出操作数而言,等号代表输出变量用作输出,原来的值会被新值替换,此约束不适用于输入操作数

      • +
        代表输出变量不仅作为输出,还作为输入,此约束不适用于输入操作数

    • ( )
      圆括号中填入C/C++变量或者表达式

    输出操作符之间需使用逗号分割

    操作符列表

    • 输出资源表
      : [ ]"=r"( ), [ ]"=r"( ), ···

    • 输入资源表
      : [ ]"r"( ), [ ]"r"( ), ···

    • 影响资源表
      : " ", "", ···

    用于告知编译器当前内联汇编语句可能会对某些寄存器或内存进行修改,使得编译器在优化时将其因素考虑进去

    • 隐式表
      除了使用%[字符]中明确的符号命名指定之外,还可以使用%数字的方式进行隐含指定。从0开始,依次表示操作符列表中所有的输出操作数与输入操作数。

    范例

     
    
    int abc = 10,cba = 20;
    printf("%d & %d\n",abc,cba);
    asm volatile(
    "mv %[da],%3\n"
    "add %2,%1,%0\n"
    "li %3,12\n"
    : [da]"=r"(abc), "=r"(cba) // Working
    : "r"(abc), [db]"r"(cba) // Working
    : "t1", "t2"//, "x7"
    );
    printf("%d & %d\n",abc,cba);

    输出结果为:

     
    
    10 20 (修改前)
    40 12 (修改后)
  • 相关阅读:
    一招解决IDEA使用Junit4自动创建的测试类无内容问题
    UE5.3实现1秒12帧风格的动画抽帧效果
    港联证券:a股b股区别?
    【安装windows10 RTX3060 tensorflow的开发环境】
    点云 3D 数据 读取、保存 - pypcd 包
    网络技术缩写术语大全,还有中英文对比哦。
    go 开源中后台管理系统
    Elasticsearch - Elasticsearch集群Cluster(三)
    深入理解 Happens-Before 原则
    雪莱的式子武汉2023(分析+快速幂)
  • 原文地址:https://blog.csdn.net/I_O_fly/article/details/127089091