对mips I-Type指令语法感到困惑

confused over mips I-Type Instruction syntax

抱歉这个非常愚蠢的问题。但是我整天都在看我的课本,它变得非常混乱。

我想用 MIPS I 型指令澄清一些与语法相关的问题。

我理解

addi , , -50

是可能的,立即数被解释为小数(2s 补码)。

但是我可以这样写 addi , , 0xF1DF? 使得立即数是十六进制的吗?

这让我想到了 andi , , 0xFFFFori , [=13=], 0x0FA5 的下一个问题。我知道这 2 个代码是正确的。

但是我可以写 andi , , 120ori , [=15=], -16 使得立即值是十进制的吗?如果可能的话,它是将 120 解释为十六进制还是将十进制 120 转换为十六进制等于十六进制的 78

我很迷茫

您可以用 10 进制或十六进制表示立即数。要表示十进制值,您需要在数字前使用 0x 前缀(例如 0x10,即以 10 为基数的 16)。如果您不在数字前使用前缀 0x,汇编程序将假定数字是十进制表示法。

使用您的示例,如果您想添加 120(基数 10),您应该像 addi , , 120addi , , 0x78 那样对指令进行编码。汇编程序将生成相同的二进制指令 0x20000000。您可以使用此在线汇编程序亲自尝试 here

MIPS addi / addiu 将 16 位立即数符号扩展为 32 位 (2's complement):
-32768 (0xFFFF8000) 到 32767 (0x00007FFFF) 的值是可编码的。

MIPS andi / ori zero-将16位立即数扩展为32位,
0 (0x00000000) 到 65535 (0x0000FFFFF) 的值是可编码的。

所以不,你不能写ori , [=19=], -16,你必须使用addiu
(或者效率低下,lui , 0xFFFF / ori , , 0xfff0)。

通常你可以把这个决定交给assembler,让它选择如何用li , 0xFFFFFFF0li , -16创建常量。这些将 assemble 完全相同。

但是如果您不只是创建一个常量,您就必须知道什么是可编码的。例如on the Godbolt compiler explorer,gcc5.4针对MIPS编译这些函数如下:

unsigned mask(unsigned a) {
    return a & -16UL;
}

      # not encodeable as an immediate for andi
    li      ,-16                  # 0xfffffffffffffff0
    j       
    and     ,,



unsigned mask_positive(unsigned a) {
    return a & 0xFF;
}

    j       
    andi    ,,0x00ff   # encodeable as an immediate

源中的表示完全不相关;十六进制和十进制是两种不同的数字序列化格式。 0x1016 字面意思是一样的。 在 MIPS 机器代码中,它们以 16 位二进制存储,而不是十六进制或十进制

-327680xFFFF8000 也是一回事(在 32 位 2 的补码中)。它也是 16 位 2 的补码中的 0x8000。而且它不能表示为 16 位无符号数,因为 0x8000 零扩展到 0x00008000 (+32768).