原文: https://blog.csdn.net/zoomdy/article/details/79343785
RISC-V有32个通用寄存器,其中第1个寄存器x0硬编码为0,即读出来总是0,写进去总是被丢弃。x0为RISC-V指令集的简化可贡献不少啊。
搞过Linux的都知道Linux有两个特殊的设备:/dev/zero和/dev/null。从/dev/zero可以源源不断地读到0,往/dev/null写的任何内容都被丢弃。如果要创建一个需要填0的文件,就从/dev/zero拷贝,如果要丢弃一些输出,就把输出重定向到/dev/null。
RISC-V的x0寄存器就相当于是硬件版的/dev/zero和/dev/null的组合体。从x0读出来的总是0,往x0写进去的总是被丢弃。所以这x0提供了两种功能,一是提供常量0,在软件编程中0可以说是最常用的常量了;二是提供一个可以丢弃结果的场所。有了这个x0,很多本来需要单独指令的操作只要更普通的指令加上x0就可以实现了。
比如nop空指令,RISC-V没有提供nop指令噢,RISC-V用addi x0, x0, 0来实现空指令的,这条addi使用x0作为目标寄存器,x0是会丢弃结果的,所以这条指令不会对程序状态产生任何影响,和空指令是完全等价的。这就不需要单独的空指令了。
比如neg取负数指令,RISC-V用sub rd, x0, rs来实现,x0 - rs 等价于 0 - rs 等价于 -rs,有了x0,就可以用更普通的减法指令来实现取负数指令。
比如j跳转指令,RISC-V没有单独的j跳转指令,只有jal跳转链接指令,跳转之前总是要把下一条指令的地址拷贝到寄存器,但是如果用x0作为jal的操作寄存器,即把下一条指令的地址拷贝到x0,那么效果就等价于j跳转指令了,因为写入x0的任何值都是会被丢弃的呀。
比如beqz等于零跳转指令等等一系列和0比较的跳转指令,程序中和0比较是相当常见的操作了,RISC-V中和0比较的指令就是普通的比较跳转指令,无非是用了x0寄存器做指令的操作数罢了。
其它还有很多这样的指令,用普通的指令加上x0做操作数,就实现了那些没有x0寄存器的处理器需要单独指令或者需要组合两条指令才能实现的操作。更多这样的指令可以参考《The RISC-V Instruction Set Manual Volume I: User-Level ISA》Chapter 20 RISC-V Assembly Programmer’s Handbook ,这个Handbook中定义了大量的伪指令,大部分伪指令都使用了x0作为操作数。
离线
使用 Linux 朋友经常会用到 dd 命令, 同时带上这两个设备 /dev/null /dev/zero, 用于测试flash, u盘读写速度速度
比如测试 U盘写速度(文件大小/时间):
dd if=/dev/zero of=/mnt/flash/zero.bin
测试 U盘读速度(文件大小/时间):
dd if=/mnt/flash/zero.bin of=/dev/null
RISC-V架构中的X0寄存器与 Unix 哲学中的 /dev/null, /dev/zero 有异曲同工之妙!
离线