RISCV asm内嵌汇编

RISCV asm内嵌汇编

引用自 使用asm函数嵌套汇编 - 知乎 (zhihu.com)

在ysyx和处理器学习中,经常遇到类似这样的语句asm volatile("li a5, -1; ecall");或蜂鸟中

    asm volatile (
       ".insn r 0x7b, 2, 1, x0, %1, x0"
           :"=r"(zero)
           :"r"(addr)
     );

这些都是通过asm嵌套汇编实现的,这篇文章就来梳理一下。

asm格式

asm ("汇编指令":"输出部分":"输入部分":"破坏描述部分")

​ 主要有四部分组成,每个部分用双引号包起来,用冒号做间隔,除了汇编指令部分是必须的,其他可以不用。但是如果中间部分缺省,则也用冒号区分并填充空格,如用到第一部分和第四部分:

asm volatile ("sleep" : : : "memory")

​ 一般还有volatile,以避免被优化。

汇编指令

​ 汇编指令部分有汇编指令语句组成。如果使用多条,用 ; 隔开。操作数可以用占位符引用C语言中的变量,最多10个,比如 %0 ,%1 , %2 …%9.

​ 命令中使用占位符表示的操作数,总被视为long型,但对其施加的操作根据指令可以是字或者字节,当把操作数当作字或者字节使用时,默认为低字或者低字节。对字节操作可以显式的指明是低字节还是高字节。方法是在%和序号之间插入一个字母,"b"代表低字节,"h"代表高字节,例如:%h1。

输出部分

​ 格式为**“输出修饰符、限定符”(变量)**。

  • 输出修饰符有三种:
输出修饰符名称意义
=只写
+可读可写
&指定寄存器
  • 限定符
限定符名称意义
r将变量放到通用寄存器
m直接操作内存
n立即数
g使用任意一个寄存器,由gcc在所有的可以使用的寄存器中选取一个gcc认为合适的。
f浮点寄存器
  • 变量

    变量一般就是寄存器名或立即数值或内存。

输入部分

输入部分与输出部分类似,但没有输出修饰符,格式为 "限定符"(变量)

破坏描述部分(暂时没用到)

​ 破坏描述符用于通知编译器我们使用了哪些寄存器或内存,由逗号格开的字符串组成,每个字符串描述一种情况,一般是寄存器名以及"memory"。例如:“%R0”,“%R1”,"memory"等。

例子解析

解释三个例子,前两个是开头提到的。

  • asm volatile("li a5, -1; ecall");

      这个只有汇编指令部分。
    
      1. 先执行`li a5,-1`,即令a5寄存器为-1;
    
      2. 然后执行`ecall`,结束。
    
  • 蜂鸟例子

    这个例子包括汇编指令、输出部分和输入部分。

    .insn r 0x7b是自定义指令,表示为R型指令,0x7b是RISCV为自定义指令留的操作码(custom_3,inst[6:0])。其余部分按.insn r opcode, func3, func7, rd, rs1, rs2。由于这里不是asm重点,不详细解析。

    输出部分为"=r"(zero) ,其中 = 是输出修饰符,表示只写,r表示放入通用寄存器,zero表示变量名。

    输入部分,把addr变量值赋给rs1寄存器。

asm volatile (
   ".insn r 0x7b, 2, 1, x0, %1, x0"
       :"=r"(zero)
       :"r"(addr)
 );
  • asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));

    这个包括汇编指令和输入部分。

    csrw格式如下图,%0是输入变量__am_asm_trap的占位符。

    image-20231226210416089

  • 29
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值