在 RISC-V 程序集中的 .data 段中的地址写入一个字节

Gia*_*lli 0 assembly illegal-instruction riscv

我正在编写一个 RISC-V 汇编程序,需要将一个字(保存到寄存器中)存储到一个 .data 段中:

.section .rodata
msg:
    .string "Hello World\n"

.section .data
num:
    .word 97 

.section .text
.global _start

_start:

    li a1, 100
    sw a1, num

    loop:
        j loop
Run Code Online (Sandbox Code Playgroud)

但是当程序到达时,sw a1, num我收到错误“非法操作数`sw a1,num'”。如何将数据存储到 .data 段内的内存位置?你能给我一些提示吗?

小智 5

作为一般经验法则,您编写到汇编器中的程序集是它自己的编程语言,恰好看起来很像 RISC-V ISA 手册中的内容。RISC-V 是一个非常简单的 ISA,因此对于大多数指令,ISA 手册的语法和汇编程序接受的语法实际上没有区别。这开始崩溃的地方是引用符号时,因为虽然您可以直接在汇编代码中填写立即数,但您可能希望依靠链接器来这样做,因为在链接时间之前您不会知道实际的符号地址(它可能会随着您修改程序而改变)。

为了使链接器能够在您的代码中填写符号地址,您需要从汇编器发出重定位,以便链接器稍后可以填写这些地址。我在 SiFive 的博客上有一篇关于它如何工作的完整博客文章,但我们刚刚刷新了网站,我不知道如何找到它:)。

在这种情况下,您实际上是在尝试编写实现以下 C 代码的程序集

int num = 97;
void func(int val) { num = val; }
Run Code Online (Sandbox Code Playgroud)

您已经在原始答案中获得了正确的所有数据内容,因此这里唯一需要担心的是如何发出正确的指令。关于如何发出这些,您有几种选择。一种选择是将每条指令和重定位显式写入您的源代码中,如下所示

func:
    lui t0, %hi(num)
    sw  a0, %lo(num)(a0)
    ret
Run Code Online (Sandbox Code Playgroud)

您可以通过使用-mcmodel=medlow -mexplicit-relocs -O3. GCC 手册定义了控制代码生成的其他 RISC-V 后端特定选项。

如果您对更多详细信息感兴趣,我们在 GitHub 上提供了汇编程序员手册:https : //github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md。它还远未完成,但我们很乐意帮助您指出问题或提供更多内容。