assembly - MIPS 中 lui 之后的 ori 操作和 add 操作有什么区别?
问题描述
我想存储3*2^16 + 9
在$t0
. 我做到了lui $t0,3
,我做到了addi $t0,$t0,3
。顺便说一句,在教科书中,价值是通过ori
after 的操作创造出来的lui
。我这样做的方式有问题吗?两者有什么区别?
解决方案
两者有什么区别?
两者都ori
允许addi
16 位立即数。
但是,ori
零会扩展立即数,因此换句话说,立即数总是被视为正数,因此在 32 位中,扩展立即数的高 16 位将为零。
而addi
将符号扩展立即数,因此它被视为 16 位有符号值,可以是正数或负数。
两者都可以,但使用时addi
要注意:如果低16位设置了符号位,那么由于符号扩展和加法的性质,它会产生递减高位的效果,所以需要添加一到上立即。例如,假设我们要加载一个常量 0x23458765。lui
应该给定 0x2346 而不是 0x2345,然后得到addi
0x8765,它作为 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 位变为负数时减少高位的潜在影响)。(例如,如果意图访问全局变量,这些序列(; / )可以在这里和那里保存指令。)%lo
lw
sw
addiu
lui
lw
sw
推荐阅读
- php - 如何对另一个wordpress php文件进行href?
- reactjs - React + Redux + Storybook:在编写故事书故事时如何使用连接的 React 路由器的 useParams?
- scala - 在 IntelliJ 中使用 Gradle 构建具有依赖项的 Jar,包括多个主类
- spring-data-jpa - 如何转换为 JPQL 用于内联视图?
- c++ - 仅当我们在优先级队列中使用自定义比较器时才需要传递容器类型?
- javascript - 根据重复出现修改数组值
- ios - 我可以使用 NavigationController 来解除屏幕移动吗?
- php - 如何在 PHP 标记 echo 内的脚本中使用 jquery 变量?
- javascript - 在 Django 中弹出消息
- react-native - React Native 是否支持 Apple 的 M1 macbook pro?