我已经为我的问题创建了一个最小的例子。在c文件中,我用16个元素初始化一个数组。然后我用数组指针和它的大小作为参数调用一个函数。函数本身可以工作,我已经用反汇编文件验证了这一点。stackpointer初始化也很好。问题是数组指针的函数参数错误。我查过了,失败的根源就在主要章节的开头。这里指针存储在堆栈上。
我不明白的是:数组值存储在.rodata节中。本节从0x1000开始。所以指向数组的指针也应该是0x1000。在反汇编中,0x1000加载到a5(正确的值)。但随后它将地址a5的值加载到a4中。所以0x1000表示指向数组指针的指针,这是没有意义的。有人知道我做错了什么吗?
以下是所需的所有信息:
c程序:

void test(uint8_t *array, int size){
    for(int i=0; i<size; ++i){
        LED_ADDR = array[i];
    }
}
int main(){
    uint8_t buf[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    test(buf, 16);
}

链接器脚本:
OUTPUT_ARCH( "riscv" )
ROMSIZE = 0x1000;
ROM_OFFSET = 0x0000;
RAMSIZE = 0x1000;
RAM_OFFSET = 0x1000;
/* provide variables for startup code (stack init) */
STACK_TOP = ( RAMSIZE + RAM_OFFSET - 4 );
ENTRY (start)
MEMORY {
    rom (rx) : ORIGIN = ROM_OFFSET, LENGTH = ROMSIZE
    ram (!rx) : ORIGIN = RAM_OFFSET, LENGTH = RAMSIZE
}
SECTIONS {
    .reset : { <PROJECTPATH>/obj/startup.o } > rom    /* startup code */
    .text : { *(.text) } > rom                        /* executable data */
    .rodata : { *(.rodata) } > ram                    /* read only data */
    .sdata : { *(.sdata) } > ram                      /* init vars */
    .bss (NOLOAD) : { *(.bss) FILL(0x0f); } > ram     /* uninit data */
}

反汇编文件重要部分:
-在.text中,main()的开头:数组的指针应该存储在堆栈上我假定:
80:  000017b7    lui     a5,0x1      # a5 = first ram addr: begin of .rodata
84:  0007a703    lw      a4,0(a5)    # a4 = content of this addr?!?!?!
88:  fee42023    sw      a4,-32(s0)  # a4 gets stored on stack

-.rodata,包含数组的值:
Disassembly of section .rodata:
00001000 <.rodata>:
1000:   0100
1002:   0302
1004:   0504
...
100e:   0f0e

编辑:
我的CPU是哈瓦德架构,它不能直接从ROM访问数据。所以.rodata和.data必须在RAM中。我的方法是程序进程将指令写入ROM,同时也将.rodata和.data写入RAM。我对硬件的实现促进了这一点。(我的一个脚本将二进制文件的这两个数据块分离,并将其转换成我的程序单元可以处理的协议。)
而在二进制文件中,乍一看它是有效的:.text在ROM的地址空间中,.rodata和.data在RAM的地址空间中。但是链接器计算的.rodata地址是错误的。
我的这个程序只是测试这个的功能,否则我不会写这样的代码。(优化标志也是-o0。)
因此,首先,我想了解main()开头的行,这应该将数组指针放在堆栈上。
80:  000017b7    lui     a5,0x1      # a5 = first ram addr: begin of .rodata
84:  0007a703    lw      a4,0(a5)    # a4 = content of this addr?!?!?!
88:  fee42023    sw      a4,-32(s0)  # a4 gets stored on stack

为什么链接器将.rodata的开头视为指向数组的指针,而不是数组的实际地址?

最佳答案

你的链接器脚本中有很多奇怪的东西
.rodata通常位于ROM中

.rodata : { *(.rodata) } > ROM

。数据在RAM中,但数据在启动期间从ROM复制:
.data : { *(.data) } > ram AT > rom

您的局部变量buff不必从.rodata初始化。编译器可能会对其进行优化,以存储代码中的即时值。它可以完全优化它并内联测试函数。有很多可能的优化,因为代码非常简单。使buffvolatile然后编译。

08-18 07:00