![](/img/trans.png)
[英]What's the difference between using ori and addi to initialize a value in MIPS?
[英]What is the difference between an ori operation and an add operation after lui in MIPS?
我想在$t0
存储3*2^16 + 9
。 我做了lui $t0,3
,我做addi $t0,$t0,3
。 顺便说一下,在教科书中,值是通过lui
之后的ori
操作创建的。 我的做法有问题吗? 两者有什么区别?
两者有什么区别?
ori
和addi
允许 16 位立即数。
但是, ori
将零扩展立即数,因此换句话说,立即数始终被视为正数,因此在 32 位中,扩展立即数的高 16 位将为零。
而addi
将对立即数进行符号扩展,因此它被视为 16 位有符号值,可以是正值也可以是负值。
两者都可以,但是在使用addi
我们必须小心如下:如果低 16 位设置了符号位,那么根据符号扩展和加法的性质,它将产生递减高位部分的效果,因此需要在上面的立即数上加一个。 例如,假设我们要加载一个常量 0x23458765。 在lui
应给予0x2346不是0x2345,那么addi
得到0×8765,这是否定的,因为直接签订16位,因此会减一经提供的0x23460000 lui
,使其0x23458765。
另一个区别是addi
会在溢出时陷入困境,这将是一个非常不受欢迎的副作用。 ori
不会陷入溢出。 但是,我们可以使用addiu
代替,因为这也将溢出不是陷阱,并使用相同的16位有符号立即为addi
。
注意:汇编程序通常会按照您的意图进行操作,而不是您指定的操作。 使用0×8765与addi
或addiu
在某些汇编器将生成的多个指令,以适应该数目为阳性。 例如,如果你想用 MARS 测试上述序列,我们将不得不使用 -30875 (10)而不是 0x8765 来让汇编器生成一个立即数 0x8765,否则它将使用多条指令来构建 +34661 (10 ) 。 (使用 -30875 和ori
也会生成多条指令,因此我们必须使用 0x8765 在一条指令中获得立即数。)
我的做法有问题吗?
总之,您可以使用任何您喜欢的代码序列来构建您的常量。 虽然有些文本只会显示一种方式,但其他文本肯定是可能的,并且没有“正确”的方式。
话虽如此,但是,如果您使用汇编器伪函数%hi
和%lo
,它们是为与addiu
一起使用而addiu
——这意味着如果低 16 位将显示为负立即数,则%hi
将执行 +1。 这些函数的用法如下: lui $t0, %hi(label); addiu $t0, $t0, %lo(label)
lui $t0, %hi(label); addiu $t0, $t0, %lo(label)
— 其中label
是(代码或数据)标签,但也可以是 32 位常量。 (MARS 不支持这些函数,所以在 MARS 中我们使用li
或la
伪指令代替,它会根据需要生成一两条指令。)
%hi
和%lo
以这种方式工作的原因是有时序列使用加载(例如lw
)或存储(例如sw
)而不是addiu
,并且加载和存储也使用相同的 16 位有符号立即数. (这些序列可以在这里和那里保存一条指令,例如,如果意图是访问全局变量。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.