.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。
1条答案
按热度按时间iyzzxitl1#
形式
lw t1, label
和sw 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
,因此也可以按如下方式使用它:这将花费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)
,从而消除了lw
和sw
伪指令形式的使用。或者,您可以使用
a7
之外的任何寄存器,但是宏使用的寄存器越多,调用宏的代码可用的寄存器就越少(汇编程序员需要注意的寄存器也就越多)。宏观经济学并没有买多少东西(但如果你应该使用宏,那么..)。那个宏是专用于使用特定的全局变量存储字符的,所以不是通用的。宏与伪指令的使用相结合掩盖了潜在的效率技术,正如@Peter所说,如果宏用在循环体中,这似乎是由于它的性质。
在一个小循环中,您可以将
char_pos
加载到循环外部和循环之前的寄存器中,并在循环期间将其保持在那里,而只将增量留在循环内部(如果需要,在循环完全完成后存储char_pos
)-在某些用例中,我可以想象全局变量甚至不是必需的,一个寄存器本身就足以存储那个逻辑变量。