Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在RISC-V汇编中数据段的地址处写入一个字节_Assembly_Riscv_Illegal Instruction - Fatal编程技术网

Assembly 在RISC-V汇编中数据段的地址处写入一个字节

Assembly 在RISC-V汇编中数据段的地址处写入一个字节,assembly,riscv,illegal-instruction,Assembly,Riscv,Illegal Instruction,我正在编写一个RISC-V汇编程序,该程序需要将保存在寄存器中的一个字存储到.数据段中: .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 但是当程序到达sw a1,num时,我得到错

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

.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
但是当程序到达sw a1,num时,我得到错误非法操作数'sw a1,num'。
如何将数据存储到.data段内的内存位置?你能给我一些提示吗?

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

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

在本例中,您实际上是在尝试编写实现以下C代码的程序集

int num = 97;
void func(int val) { num = val; }
您的原始答案中的所有数据都是正确的,所以这里唯一需要担心的是如何发出正确的指令。关于如何发射这些,您有几个选项。一种选择是将每个指令和重新定位显式写入源代码,如下所示

func:
    lui t0, %hi(num)
    sw  a0, %lo(num)(a0)
    ret
通过使用-mcmodel=medlow-mexplicit relocs-O3编译,可以从上面的C代码生成此程序集。GCC手册定义了控制代码生成的其他RISC-V后端特定选项

如果您对更多细节感兴趣,我们在GitHub上提供了一本汇编程序员手册:。它还远未完成,但我们希望得到帮助,指出问题或提供更多内容。

store word sw指令的语法是

sw rs2, offset(rs1)
其中,偏移量是12位立即数操作数

编写sw a1、num时,会出现语法错误,汇编程序会出现以下故障:

foo.s: : Assembler messages:
foo.s::13: Error: illegal operands `sw a1,num'
解决此问题的最简单方法可能是使用load address la伪指令:

li a1, 100
la t0, num
sw a1, 0(t0)
由于la指令将地址完全加载到寄存器中,因此我们必须使用0作为偏移量

la伪指令扩展到程序计数器PC相对寻址,即使用objdump检查:


请注意,%hi和%lo汇编程序宏将32位地址拆分为其高20位和低12位部分,即%hinum+符号\ U ext%lonum=num。

使用支持伪指令的汇编程序,并将地址num的高部分加载到暂存寄存器中。或者自己做。请记住,sw机器指令只有12个位移位。谢谢你的回复,我正在使用汇编程序riscv64未知elf,我如何使用这个汇编程序?感谢在编译器输出处查看存储到全局的函数,以了解如何使用lui。RISC-V有叮当声。准确地说,当你组装你的程序时,你会得到错误,而不是“当程序到达软件时”。错误消息由GNU as发出。我如何用0填充引导扇区来实现等效的x86。乘以508-$-$$db 0 sw a0,%lonuma0应该是sw a0,%lonumt0,对吗?
00000000000100b0 <_start>:
   100b0:   06400593            addi    a1,zero,100
   100b4:   00001297            auipc   t0,0x1
   100b8:   01028293            addi    t0,t0,16 # 110c4 <__DATA_BEGIN__>
   100bc:   00b2a023            sw  a1,0(t0)
li a1, 100
lui t0, %hi(num)
sw a1, %lo(num)(t0)