assembly 为什么我不能将64位正确加载到寄存器中?

vmpqdwk3  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(911)

我尝试将一个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。
我这样做有什么问题吗?

yqyhoc1h

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对luioriaddi都使用16位立即数。然而,ori使用零扩展,而addi使用符号扩展。
因此,您可能会认为最好的方法是将luiori一起使用,以避免符号扩展和-1偏移,从而需要lui中的+1。然而,在编程中,我们经常需要lui后跟lw这样的序列,在这两个序列之间,也形成一个32位常量然而,由于lw就像addi一样对立即数执行符号扩展,社区(汇编程序和链接程序)提供了+1偏移,并选择不创建第二个机制(不+1高位立即数),用于ori和零扩展立即数。

相关问题