【发布时间】:2019-07-13 16:40:25
【问题描述】:
我正在构建一个 RISC-V cpu 内核,并且我正在尝试为它构建一些 C 代码。我有一些基本的代码编译和链接我想要的方式并且工作得很好,例如:
asm("li sp, 0x390");
asm("li s0, 0x390");
asm("li ra, 0");
int main(void){
char *memptr = 0 ;
int sum = 0;
for(int i = 0; i < 8; i++)
*(memptr + i) = i;
for(int i = 0; i < 8; i++)
sum += *(memptr + i);
*((int*)0xC) = sum;
asm("lw x31, 0xc(x0)");
}
并使用这些命令编译/链接:
riscv64-unknown-elf-gcc -nostartfiles -nostdlib -mno-relax -march=rv32i -mabi=ilp32 -c main.c
riscv64-unknown-elf-ld -nostartfiles -nostdlib -march=rv32i -melf32lriscv -o main -T link.ld main.o
我的链接器脚本如下:
OUTPUT_ARCH( "riscv" )
ENTRY(main)
MEMORY
{
progmem (rx) : ORIGIN = 0x10000000, LENGTH = 8K
ram (!rx) : ORIGIN = 0x20000000, LENGTH = 64K
}
SECTIONS
{
.text : {
main.o(.text)
} > progmem
.data : {
main.o(.rodata)
main.o(.data)
main.o(.sdata)
main.o(.bss)
} > ram
}
通过这个设置,我得到了我想要的结果,没有问题。我得到了我的文本部分(我把它放在程序内存中),我得到了包含所有子部分的数据部分,并将它直接加载到 ram 中(它适用于我现在正在做的事情)。
当我尝试使用浮点加法时,问题就开始了:
asm("li sp, 0x390");
asm("li s0, 0x390");
asm("li ra, 0");
float a = 1.7;
float b = 0.7;
int main(void){
int *memptr = (int*)0x8;
float c = a - b;
}
编译后尝试链接会导致此错误:
riscv64-unknown-elf-ld -nostartfiles -march=rv32i -melf32lriscv -o main -T link.ld main.o
riscv64-unknown-elf-ld: main.o: in function `main':
main.c:(.text+0x3c): undefined reference to `__subsf3'
我可以在汇编文件中看到(使用 gcc -S 选项)有一条指令 call __subsf3,但在 .text 部分的任何地方都没有这样的标签。我相信我必须以某种方式链接数学库才能使其工作,所以我尝试添加 #include "math.h",然后将各种标志添加到 ld命令如“-lc”、“-lgcc”、“-lm”,但会导致以下错误:
riscv64-unknown-elf-ld: cannot find -lc
riscv64-unknown-elf-ld: cannot find -lgcc
riscv64-unknown-elf-ld: cannot find -lm
通过反复试验,我设法想出了这个
riscv64-unknown-elf-gcc -nostartfiles -mno-relax -march=rv32i -mabi=ilp32 -Wl,-emain -lm main.c -o main
这几乎可以满足我的需求,但不使用我的链接脚本。如果我添加 -Wl,link.ld 然后它再次不起作用,给出错误:
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o:(.sdata+0x0): multiple definition of `a'; /tmp/cc0LmWB4.o:(.sdata+0x0): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o:(.sdata+0x4): multiple definition of `b'; /tmp/cc0LmWB4.o:(.sdata+0x4): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: main.o: in function `main':
main.c:(.text+0xc): multiple definition of `main'; /tmp/cc0LmWB4.o:main.c:(.text+0xc): first defined here
/usr/lib/gcc/riscv64-unknown-elf/9.1.0/../../../../riscv64-unknown-elf/bin/ld: error: no memory region specified for loadable section `.sdata'
collect2: error: ld returned 1 exit status
如果有人能解释我做错了什么,以及我应该如何使用上面的浮点数学为裸机 RISC-V 构建代码,并让 ld 在我的.text 部分。
【问题讨论】:
-
你有没有尝试使用gcc链接程序,而不是直接调用ld?有时它知道在哪里可以找到合适的库..
-
-nostartfiles -nostdlib不是ld选项。它会将它们解析为像-n -o startfiles-n -o stdlib这样的单字母选项。后面的-o选项会覆盖前面的两个输出文件名选项。 -
可能你想静态链接
libm.a。所以静态链接时使用-lm。
标签: assembly compilation linker riscv bare-metal