Golang为何在RISC-V架构中使用JMP而非J指令

Golang为何在RISC-V架构中使用JMP而非J指令 我注意到Go在RISC-V架构中使用了JMP指令进行无条件跳转,但实际上应该使用J指令。

JMP指令在该架构中并不存在,所以我想知道是否存在一个按架构设置指令别名的文件,或者这是一个错误。

示例文件:https://github.com/golang/go/blob/release-branch.go1.16/src/math/big/arith_riscv64.s

谢谢。

3 回复

非常感谢!

更多关于Golang为何在RISC-V架构中使用JMP而非J指令的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


请参阅:https://golang.org/doc/asm

Go 在所有平台上使用其自身标准化的伪汇编语言,并且这些“指令”并不总是映射到所有平台的实际硬件指令。与其他汇编器将汇编助记符几乎精确地映射到特定指令不同,Go 汇编器是“智能”的,它会将伪汇编转换为真实硬件对应的实际汇编。

编辑: 这也是一个有用的链接:https://www.youtube.com/watch?v=KINIAgRpkDA

在Go语言的RISC-V架构实现中,确实使用了JMP指令而非标准的J指令。这不是错误,而是Go汇编器为RISC-V架构定义的指令别名。

在Go的汇编器实现中,JMP被定义为J指令的别名。相关代码可以在Go源码的汇编器文件中找到:

// src/cmd/internal/obj/riscv/obj.go
// 指令定义
var riscv64Op = map[string]obj.As{
    // ...
    "J":    riscv.AJAL,
    "JMP":  riscv.AJAL,  // JMP是J的别名
    "CALL": riscv.AJAL,
    // ...
}

在RISC-V架构中,J指令实际上是JAL(Jump And Link)指令的伪指令,其编码为:

jal x0, offset  # 跳转但不保存返回地址

Go汇编器使用JMP作为跨架构的统一跳转指令名称,这样可以在不同架构间保持汇编代码的一致性。例如:

// RISC-V汇编示例
TEXT ·Function(SB),NOSPLIT,$0
    JMP target
    // 其他代码...
target:
    RET

实际上,在生成的机器码中,JMP会被编码为标准的RISC-V JAL指令。你可以通过反汇编验证:

# 编译后使用objdump查看
go build -o test test.s
riscv64-linux-gnu-objdump -d test

输出会显示JMP被转换为jal指令。这种设计使得Go的汇编代码在不同架构间更具可移植性,开发者可以使用相同的JMP助记符,而汇编器会处理架构特定的指令映射。

回到顶部