RISCV .data段标签添加方法:后续标签访问异常问题排查
解决RISCV汇编中.data段标签使用gp相对地址导致的段错误问题
问题根源
RISCV汇编器(riscv64-unknown-elf-as 2.40.0)默认会对.data段中处于全局指针(gp)±4KB范围内的标签生成gp相对寻址指令。如果未链接crt0.o等启动文件,gp未被初始化,访问这些标签就会触发段错误。而.rodata和.data首个标签能正常访问,是因为它们的地址超出gp默认覆盖范围,汇编器自动生成了基于auipc+addi的绝对寻址指令;.comm定义的变量属于未初始化数据段(.bss),汇编器不会使用gp相对寻址,因此也能正常访问。
不用.comm仅用.word/.byte的解决方法
1. 强制汇编器生成绝对寻址指令
在.data段开头添加.option norelax指令,禁用汇编器的寻址优化,让所有标签都通过auipc+addi(或la指令)生成绝对地址:
.section .rodata msg: .string "Hello" .section .data .option norelax # 禁用寻址优化,强制生成auipc+addi num1: .word 10 num2: .word 20 arr: .byte 1,2,3,4 .section .text .global _start _start: la t0, num1 # 生成auipc+addi la t1, num2 # 同样生成auipc+addi,而非gp相对指令 # ...后续操作
2. 手动初始化全局指针gp
如果需要保留gp相对寻址的效率,可以在程序入口手动初始化gp,指向.data段的中间位置(覆盖±4KB的寻址范围):
.section .text .global _start _start: # 将gp指向.data段偏移0x800的位置(4KB范围的中点) auipc gp, %pcrel_hi(.data) addi gp, gp, %pcrel_lo(.data + 0x800) # 之后即可正常访问gp范围内的.data标签 lw t0, num2 # 使用gp相对寻址,无需段错误 lb t1, arr # ...后续操作 .section .data num1: .word 10 num2: .word 20 arr: .byte 1,2,3,4
3. 调整标签位置至gp默认覆盖范围外
如果.data段内容较少,可以将标签放在距离程序入口足够远的位置,让汇编器自动选择绝对寻址。但这种方法灵活性差,不适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者Mark J
相关产品推荐
相关产品推荐

