首页 > 解决方案 > MIPS 中 lui 之后的 ori 操作和 add 操作有什么区别?

问题描述

我想存储3*2^16 + 9$t0. 我做到了lui $t0,3,我做到了addi $t0,$t0,3。顺便说一句,在教科书中,价值是通过oriafter 的操作创造出来的lui。我这样做的方式有问题吗?两者有什么区别?

标签: assemblymips

解决方案


两者有什么区别?

两者都ori允许addi16 位立即数。

但是,ori零会扩展立即数,因此换句话说,立即数总是被视为正数,因此在 32 位中,扩展立即数的高 16 位将为零。

addi将符号扩展立即数,因此它被视为 16 位有符号值,可以是正数或负数。

两者都可以,但使用时addi要注意:如果低16位设置了符号位,那么由于符号扩展和加法的性质,它会产生递减高位的效果,所以需要添加一到上立即。例如,假设我们要加载一个常量 0x23458765。lui应该给定 0x2346 而不是 0x2345,然后得到addi0x8765,它作为 16 位有符号立即数是负数,因此,将从 0x23460000 提供的 0x23460000 中减去 1 lui,使其成为 0x23458765。

另一个区别是addi溢出时会陷入陷阱,这将是一个非常不受欢迎的副作用。  ori不会陷入溢出。但是,我们可以addiu改用它,因为它也不会在溢出时捕获并使用与addi.

注意:汇编程序通常按照您的意图执行,而不是完全按照您指定的方式执行。addi在某些汇编程序中或在某些汇编程序中使用 0x8765addiu将生成多条指令以将该数字作为正数。例如,如果您想用 MARS 测试上述序列,我们将不得不使用 -30875 (10)而不是 0x8765 来让汇编器生成立即数 0x8765,否则它将使用多条指令来构建 +34661 (10 ) . (使用 -30875ori也会生成多条指令,因此我们必须使用 0x8765 或 34661 才能在一条指令中立即获得该指令。)

我这样做的方式有问题吗?

总之,您可以使用任何您喜欢的代码序列来构建常量。虽然有些文本只会显示一种方式,但其他文本肯定是可能的,而且没有“正确”的方式。

话虽这么说,但是,如果您使用的是汇编器伪函数%hi%lo,它们是为与一起使用而设计的addiu——这意味着%hi如果低 16 位出现为负立即数,它将执行 +1。这些函数的用法如下:lui $t0, %hi(label); addiu $t0, $t0, %lo(label)— wherelabel是(代码或数据)标签,但也可以是 32 位常量。(MARS 不支持这些功能,所以我们使用 MARSli代替la伪指令,它会根据需要生成一两条指令。)

以这种方式工作的原因是有时序列使用加载(例如%hi)或存储(例如)而不是当低 16 位变为负数时减少高位的潜在影响)。(例如,如果意图访问全局变量,这些序列(; / )可以在这里和那里保存指令。)%lolwswaddiuluilwsw


推荐阅读