【问题标题】:MIPS: Clarification on Load/Store word base + offsetMIPS:关于加载/存储词库 + 偏移量的说明
【发布时间】:2019-10-15 23:27:51
【问题描述】:

我目前正在学习 MIPS,希望了解有关存储/加载字的一些说明。

是:

sw $t0, 4($s0) 

一样
addi $s0, $s0, 4 # offsets are in bytes/word 8*4*4
sw   $t0, 0($s0)

此外,我知道偏移量是 16 位有符号立即数。但是,如果它比 32 位立即数更大呢?

例子

sw $t0, x($s0) # x is a 32bits offset

【问题讨论】:

  • (1) 我不明白你为什么将 4 转换为 512。(2) 处理器不支持大于 16 位的立即偏移量,所以你必须想出一些其他的方式,可能是通过使用多个指令。
  • 与未修改寄存器的 4($s0) 不完全相同,它只是基址 + 偏移量的基址。至于要寻址的内存位置,是的,它们是相同的。偏移量的大小是有限的,请参阅指令定义,它不能远程 32 位可能是 16 或更少,但我必须检查。如果指令集具有寄存器基址 + 寄存器偏移寻址模式,那么您将这样做,否则您必须修改寄存器或使用第二个寄存器(或第三个,取决于偏移量)。
  • 你在问这个问题之前确实模拟了这些,是吗?关于您的问题,模拟器显示了什么?

标签: assembly mips mips32 mars-simulator mips64


【解决方案1】:

如果它比 32 位立即数更大呢?

那么 MIPS 指令字必须更长,比如 48 位,才能为操作码和寄存器号加上 32 位立即数留出空间。


但我想您是在问如果您有一个 32 位 偏移量 太大而无法用作 立即数怎么办?

显而易见的方法是自己进行所有地址计算,将 32 位值具体化到带有 lui/addiu 的临时寄存器中,然后使用 addu 计算寄存器中的最终地址。 (因为 MIPS 没有 reg+reg 寻址模式,只有reg+imm16)。但是,我们根本不会在负载中利用 imm16。

我们可以通过使用偏移量的低部分作为加载中的立即数来做得更好,只使用 2 个额外的指令而不是 3 个。编译器知道这个技巧,所以很容易展示一个例子:

char foo(char *p) {
    return p[0x123456];
}

MIPS gcc5.4 on the Godbolt compiler explorer 编译到这个asm:

# gcc5.4 -O3 -fno-delayed-branch
foo:
        li      $2,1179648              # 0x120000
        addu    $4,$4,$2
        lb      $2,13398($4)            # 0x3456($4)
        j       $31
        nop

$4$a0$2$v0。所以这是使用 lui / addu 执行 reg += %hi(0x123456),然后使用 %lo(0x123456) 作为偏移量。

如果您使用静态数组和寄存器索引,应该可以使用类似的技巧,但这不是 GCC 实际所做的。可能是因为它不知道静态地址的低 16 位是否会设置其高位,所以符号扩展为地址的上半部分创建了一个可能的非一。也许没有重定位类型可以解决这个问题,并根据%lo() 部分的高位调整%hi() 部分,使得这种优化不可能:/

我使用了char,所以 C 不会缩放我的索引:数组索引 = 字节偏移量,因为sizeof(char) = 1lb 是对字寄存器的符号扩展加载,因为这就是 MIPS 的调用约定适用于窄 args 的方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多