GCC生成RISC-V的jal指令出现异常?请求排查操作问题
问题分析与解决
操作错误点
编译阶段误用链接器参数
你使用了-c参数编译,这个参数仅负责生成目标文件(.o),不会执行链接步骤,但同时添加的链接器参数-Wl,-Ttext=0x0在-c阶段完全无效——因为链接器根本没有参与该阶段的工作。未遵循RISC-V JAL指令的寻址规则
RISC-V的jal指令采用PC相对寻址,而非直接指定绝对地址:- 指令中的立即数是相对于当前指令下一条地址(即
PC = 当前指令地址 + 4)的偏移,且偏移以**字(4字节)**为单位,实际字节偏移为立即数左移1位。 - 你直接写
jal a0, 42时,汇编器在未链接的状态下(-c阶段)无法确定当前指令的加载地址,也就无法计算出正确的PC相对偏移,最终只能生成偏移为0的指令,即反汇编显示的jal a0,0x0。
- 指令中的立即数是相对于当前指令下一条地址(即
正确操作步骤
方式一:一步完成编译链接
去掉-c参数,让gcc直接完成编译+链接流程,同时传递链接器参数指定代码段起始地址:
riscv64-linux-gnu-gcc -Wl,-Ttext=0x0 -nostdlib -mno-relax -o test_jal test_jal.s
方式二:分阶段编译+链接
- 编译生成目标文件:
riscv64-linux-gnu-gcc -c -mno-relax -o test_jal.o test_jal.s
- 链接时指定代码段起始地址:
riscv64-linux-gnu-ld -Ttext=0x0 -nostdlib -mno-relax -o test_jal test_jal.o
生成原始二进制文件
完成链接后,再用objcopy生成二进制文件:
riscv64-linux-gnu-objcopy -O binary test_jal test_jal.bin
验证结果
如果你的需求是跳转到绝对地址0x42,链接完成后反汇编应该会显示正确的jal a0,0x42,对应的十六进制代码也会是计算后的正确值(当前指令位于0x0时,PC为0x4,偏移字节为0x42 - 0x4 = 0x3E,字偏移为0x3E >> 1 = 0x1F,指令二进制应为0x6F1F0000)。
内容的提问来源于stack exchange,提问作者Euphonious
相关产品推荐
相关产品推荐

