我尝试将一个64位加载到寄存器中,因此我将其拆分为两个32位,然后在最后将其组合在一起。
;Use lui and addi to store 0x1234587811223344 in x5
c: EQU 0x1234587811223344
lui x6, (c & 0xffffffff) >> 12
addi x6, x6, c & 0xfff
lui x7, c >> 44
addi x7, x7, (c & 0xfff00000000) >> 32
slli x7, x7, 32
or x5, x6, x7
所以第一部分工作正常,它将0x11223000加载到x6中,然后加上最后3,变成0x11223344。
第二部分是由于某种原因,它似乎没有加载。它加载0x12345000,然后当它应该添加32位序列的最后3位时,它将整个内容更改为0x12344878,而不是0x12345878。
我这样做有什么问题吗?
1条答案
按热度按时间yqyhoc1h1#
RISC V在所有12位立即数上使用符号扩展。
当试图加载一个不适合有符号12位的常量时,不同的工具会接受或给予不同的错误消息,并且这会根据所使用的语法而变化,例如十六进制与十进制表示法。
看起来你的汇编器允许这个值,然后创建指令
addi x7, x7, 0x878
。但是在执行过程中,处理器会在内部创建常量0xffffffff 878,并将其加到寄存器中,当然,这会产生从高20位减1的效果。如果你想在单步调试中看到更多的前面,使用
addi x8, x0, 0x878
,你会看到符号扩展,然后可能跟在add x7, x7, x8
后面,你会更清楚地看到在上面部分添加的效果。一些汇编器支持
li
来形成常量,la
来从标签形成地址--这些都是伪指令,可以扩展为两条实际的机器指令,而其他汇编器支持%hi()
和%lo()
函数。在这两种情况下,汇编程序都能看到完整的常量值,如果设置了常量的第12位,它会将高位(20位)常量调整+1,以减轻符号扩展,当两个部分一起使用时,符号扩展会对高位部分产生-1的影响。
显然,由于您使用的是带有硬编码常量的单独指令,因此您需要自己进行此调整。
我更希望汇编程序给予一个错误,或者至少给出一个警告,说明常量0x 878不适合12位有符号...
MIPS对
lui
、ori
和addi
都使用16位立即数。然而,ori
使用零扩展,而addi
使用符号扩展。因此,您可能会认为最好的方法是将
lui
与ori
一起使用,以避免符号扩展和-1偏移,从而需要lui
中的+1。然而,在编程中,我们经常需要lui
后跟lw
这样的序列,在这两个序列之间,也形成一个32位常量然而,由于lw
就像addi
一样对立即数执行符号扩展,社区(汇编程序和链接程序)提供了+1偏移,并选择不创建第二个机制(不+1高位立即数),用于ori
和零扩展立即数。