assembly RISC-V中的操作数类型问题:带标签Swing,无寄存器

vs3odd8k  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(153)
.macro read_char
    li a7, 7 # read a character from the standard input
    ecall
    lw t0, char_pos # load the current position
    sb a0, (t0) # store the character at the current position
    addi t0, t0, 1 # increment the current position
    sw t1, char_pos # store the updated position

在我的sw行中,它说操作数太少或不正确,我以为我把字符存储在char_pos的位置,char_pos定义为char1。

iyzzxitl

iyzzxitl1#

形式lw t1, labelsw t1, label是伪指令,其通过MIPS和RISC V(MARS和RARS)的汇编器扩展为多个指令。
然而,RISC V不支持sw t1, label。与MIPS相比,他们去掉了$at,又名$1,寄存器--一个专用于"汇编临时"的寄存器。RISC V确实支持lw t1, label,并且它使用目标(这里是t1)作为临时寄存器,然后用加载结果覆盖它。
然而,没有为sw写入寄存器,因此也没有寄存器可用作伪指令中的临时暂存器。由于RISC V在寄存器使用方面做出了更好的选择,因此他们删除了指定为"汇编程序临时"的寄存器。这一点,加上其他几个特性(消除$k0$k1,以及在参数传递中使用更多寄存器)帮助RISC V表现得好像它比MIPS实际上多3 - 5个寄存器,尽管两者都只有31个寄存器。
你能怎么办?
由于已知宏会覆盖a7,因此也可以按如下方式使用它:

la a7, char_pos
sw t1,(a7)

这将花费3条指令(la,也是伪指令,扩展为2条指令)。
理想情况下,虽然该序列只需要两条指令,所以您可以先执行lui a7, %hi(char_pos),然后执行sw t1,%lo(char_pos)(a7),从而利用sw中以前未使用的12位立即数-但是RARS不支持这些%函数。
因此,对于初学者,我只会执行上面的la/sw序列,而且,我只会执行一个la,并将其用作lw t0, (a7)和后来的sw t1, (a7),从而消除了lwsw伪指令形式的使用。
或者,您可以使用a7之外的任何寄存器,但是宏使用的寄存器越多,调用宏的代码可用的寄存器就越少(汇编程序员需要注意的寄存器也就越多)。
宏观经济学并没有买多少东西(但如果你应该使用宏,那么..)。那个宏是专用于使用特定的全局变量存储字符的,所以不是通用的。宏与伪指令的使用相结合掩盖了潜在的效率技术,正如@Peter所说,如果宏用在循环体中,这似乎是由于它的性质。
在一个小循环中,您可以将char_pos加载到循环外部和循环之前的寄存器中,并在循环期间将其保持在那里,而只将增量留在循环内部(如果需要,在循环完全完成后存储char_pos)-在某些用例中,我可以想象全局变量甚至不是必需的,一个寄存器本身就足以存储那个逻辑变量。

相关问题