Las*_*ssi 3 assembly endianness riscv
在汇编语言级别处理 RISC-V 中大端值的最简单方法是什么?也就是说,如何将内存中的 big-endian 值加载到寄存器中,以 native-endian(little-endian)的形式处理寄存器值,然后以 big-endian 的形式将其存储回内存。16、32 和 64 位值用于许多网络协议和文件格式。
我找不到一个字节交换指令(相当于BSWAP对ARM x86或REV)的手册中,也没有任何关于大端加载和存储。
在最新的RISC-V 用户级 ISA 手册(2.1 版)中没有提到字节交换指令。但是,该手册有一个占位符,用于表示位操作的“B”标准扩展。该扩展工作组的一些草稿材料收集在 GitHub 上。特别是,草案规范谈到了grev可以进行 16、32 和 64 位字节交换的指令(广义反向):
该指令提供了一条硬件指令,可以实现字节中的所有字节顺序交换、按位反转、短顺序交换、字序交换(RV64)、半字节顺序交换、按位反转等,全部来自单个硬件指令。通过控制递归树中发生反转的级别,它接受单个寄存器值和一个立即数来控制哪个函数发生。
扩展 B 工作组在最终确定规范之前“因官僚主义原因于 2017 年 11 月解散”。
2020 年,工作组再次活跃,在链接的 GitHub 存储库中发布他们的工作。
因此,目前似乎没有什么比做通常的换挡面具或跳舞更简单的了。我在 GCC 或 clang riscv 端口中找不到任何内在的汇编语言 bswap。例如,bswapsi2以下是riscv64-linux-gnu-gcc编译器版本 8.1.0-12发出的函数(字节交换 32 位值)的反汇编:
000000000000068a <__bswapsi2>:
68a: 0185169b slliw a3,a0,0x18
68e: 0185579b srliw a5,a0,0x18
692: 8fd5 or a5,a5,a3
694: 66c1 lui a3,0x10
696: 4085571b sraiw a4,a0,0x8
69a: f0068693 addi a3,a3,-256 # ff00 <__global_pointer$+0xd6a8>
69e: 8f75 and a4,a4,a3
6a0: 8fd9 or a5,a5,a4
6a2: 0085151b slliw a0,a0,0x8
6a6: 00ff0737 lui a4,0xff0
6aa: 8d79 and a0,a0,a4
6ac: 8d5d or a0,a0,a5
6ae: 2501 sext.w a0,a0
6b0: 8082 ret
Run Code Online (Sandbox Code Playgroud)
小智 5
RISC-V ISA 没有明确的字节交换指令。最好的办法是使用 C 内置函数来执行此计算,在 GCC 中,它类似于__builtin_bswap32(). 这为编译器提供了尽可能多的信息,因此它可以做出正确的决定。使用当前定义的 ISA 集,您几乎肯定最终会调用例程,但如果定义了 B 扩展,您将透明地获得更好的生成代码。完整的已定义内置函数集可在线获取:https : //gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html。
如果您在汇编中坚持这样做,那么最好的办法是调用现有的字节交换例程。32 位交换的规范是__bswapsi2,它是 libgcc 的一部分——无论如何你可能正在使用它,所以它会存在。这就是编译器当前所做的,因此您失去的只是在有更好的实现可用时省略函数调用。
作为一个具体的例子,这是我的示例 C 函数
unsigned swapb(unsigned in) { return __builtin_bswap32(in); }
Run Code Online (Sandbox Code Playgroud)
和生成的程序集
swapb:
addi sp,sp,-16
sd ra,8(sp)
call __bswapsi2
ld ra,8(sp)
sext.w a0,a0
addi sp,sp,16
jr ra
Run Code Online (Sandbox Code Playgroud)
与 x86 不同,RISC-V 没有类似的东西movbe(可以在一条指令中加载和字节交换)。
因此,在 RISC-V 上,您可以照常加载/存储,并且在加载/存储之后/之前,您必须使用额外的指令交换字节。
\nRISC -V“B”(Bitmanip)扩展(版本 0.92)包含通用位反转指令(grev、grevi)和几个可用于字节交换的伪指令:
\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\nRISC-V ARM X86 Comment\n\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\xe2\x80\x95\nrev RBIT \xe2\x98\x90 bit reverse\nrev8.h REV16 \xe2\x98\x90 byte-reverse half-word (lower 16 bit)\nrev8.w REV32 \xe2\x98\x90 byte-reverse word (lower 32 bit)\nrev8 REV BSWAP byte-reverse whole register\n\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\nRun Code Online (Sandbox Code Playgroud)\n(表基于表 2.5,RISC-V Bitmanip Extension V0.92,第 18 页)
\n截至 2020 年 3 月,“B”扩展处于草案状态,因此硬件和模拟器的支持有限。
\n如果没有“B”扩展,您必须使用多个基本指令来实现字节交换。例如,请参阅“B”规范中的第 16 页,或者查看,和gcc /clang 内在函数的反汇编代码。__builtin_bswap16__builtin_bswap32__builtin_bswap64