为 RISCV 数据部分添加标签的正确方法(以便汇编器可以拾取)

问题描述 投票:0回答:1

汇编器将访问

.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
,我应该如何发出(?)地址?

或者我的理论中的其他地方是错误的?

assembly gcc riscv gnu-assembler
1个回答
0
投票

我认为您遇到了未初始化的全局指针的问题。

默认链接描述文件(当您不使用

ld
参数将 1 传递给
-T
时使用)定义
__global_pointer
,其值应该用于初始化
gp
。此初始化通常在未在
-nostartfiles
上编译的启动文件中完成。

所以你可以取消这个标志,或者在开始时自己设置

gp
.text
,就像这样,

.option push
.option norelax
la gp, __global_pointer$
.option pop
© www.soinside.com 2019 - 2024. All rights reserved.