汇编器将访问
.data
部分中的第一个标签翻译为没有问题,但随后的标签转换为一些 gp
相对地址,如果我不明白其目的是什么。
我正在尝试编写一个简单的 riscv 汇编程序,该程序将有一些数组操作(我认为在 .data 部分分配)
就这么简单,分配空间,例如需要有 .data 部分和 .rodata 部分,我就有了
.section .rodata <---- **okay access**
.align 2
sentence1:
.string "Sentence number one\n"
.align 2
sentence2:
.string "Sentence number two\n"
.section .data
.align 2
num1: <---- **okay access**
.word 0
num2: <---- **can't find**
.word 0
.align 2
arr: <---- **can't find**
.space 1024
.section .text
__start:
<my program logic>
我正在使用 RISCV 工具链的汇编器:
riscv64-unknown-elf-as -v
GNU assembler version 2.40.0 (riscv64-unknown-elf) using BFD version (GNU Binutils) 2.40.0.20230214
问题是,执行时总是出现段错误,开始访问
.data
部分中第一个标签之后的任何内容,第一个标签,在本例中为 num1
,翻译得很好,还有 .rodata
中的任何内容,例如 sentence1
和 sentence2
也可以访问
by accessed 我的意思是可以通过以下指令找到该地址:
la a0, num1
或
auipc a0, %hi(num1)
addi a0, %lo(num1)
然后在
lw
上加载和存储诸如 sw
或 a0
就没有问题了。
当尝试访问第一个标签之后的
.data
(不是 .rodata
,.rodata
没有问题!)中的任何内容(例如 num2
或 arr
)时,就会出现问题。
当我在 gdb 中运行程序来查找发生了什么情况时,查看每个装配线的执行情况,它将对地址的第一次访问转换为一对
auipc
和 addi
以获得正确的地址(对于 num1
),但之后,获取后续地址将使用 addi
全局指针转换为 gp
指令。
哪个,因为我要么只与
ld
链接,没有库,也没有crt0.o
,crtstart.o
或gcc
告诉--nostartfiles
和--nostdlib
。我认为可能是在那里设置了gp
?或者 gp
引用只是意味着汇编器无法拾取的东西?
我尝试编写一些具有类似意图和结构的 C 代码,并执行了
gcc -S
,并在其输出文件中,它为这些标签分配了空间,不仅仅是使用名称和空间,而是使用
.local .comm
的组合例如:
.local sum1
.comm sum1, 4, 4
(我有
sum1
作为文件范围静态变量,如果删除 static
,我认为它会有 .globl .comm .type .size
的东西)
他们是否负责发射(我实际上不知道这个词的意思)标签,以便汇编器可以拾取符号并翻译成正确的地址?如果我不想使用
.comm
而只想写 .word
或 .byte
,我应该如何发出(?)地址?
或者我的理论中的其他地方是错误的?
我认为您遇到了未初始化的全局指针的问题。
默认链接描述文件(当您不使用
ld
参数将 1 传递给 -T
时使用)定义 __global_pointer
,其值应该用于初始化 gp
。此初始化通常在未在 -nostartfiles
上编译的启动文件中完成。
所以你可以取消这个标志,或者在开始时自己设置
gp
或.text
,就像这样,
.option push
.option norelax
la gp, __global_pointer$
.option pop