0

我正在学习 MIPS 指令,当我测试需要签署扩展立即数的 I 型指令时,我对以下结果感到困惑(它们都在 MARS 中运行):

  1. 假设我们有源代码行 ori $s1, $s2, 0xfd10,MARS 给出了基本的汇编指令 ori $17, $18, 0x0000fd10。这是期望,因为零ori应该扩展16 位立即数。如果我们只将函数更改oriandi,即源代码行 andi $s1, $s2, 0xfd10,MARS 给出几乎相同的基本汇编指令 andi $17, $18, 0x0000fd10。但是,与 不同ori的是,andi应该使用符号扩展。所以基本的汇编指令应该是andi $17, $18, 0xfffffd10.

andi也应该使用零扩展!请忽略第一个问题。

  1. slti rt, rs, imm例如,当我尝试使用时slti $s1, $s2, 0x8000,MARS 拒绝执行该行并且错误消息是"0x8000": operand is out of range. 我看不出立即数超出范围的原因。如果我稍微改变一下立即数,比如说,slti $s1, $s2, 0x7fff它会起作用,并且立即数会扩展到0x00007fff. 我的期望是0x8000应该扩展到0xffff8000. 我的理解有什么问题吗?
4

1 回答 1

0

asm 源中的值表示您要使用的实际数值,而不仅仅是要编码到指令中的位模式。

0x8000与数字不同,0xffff8000因此汇编器会阻止您通过符号扩展来破坏您的值。如果您希望最终指令的机器代码对 value 进行编码0xffff8000,则应0xffff8000在 asm 源中编写对它们的立即数进行符号扩展的指令。

在我们的数字位值书写系统中,显式数字的左侧有无数个隐含的高位0数字。 与 , 相同的数字也是如此,这就是汇编器试图表示为 16 位符号扩展立即数的数字0x80000x00008000


您正在从 I 型指令如何编码的 PoV 中接近这一点。但是汇编程序旨在为您处理编码细节。这是使用一个的一部分。假设您编写addiu $t0, $t1, -123并且汇编程序编码-123为 16 位符号扩展立即数。

假设您写入ori $t0, $t0, -256设置低字节以上的所有位。但是汇编器拒绝了这一点,因为它不能编码为 的零扩展立即数ori,而不是像0x0000ff00. 所以你不必记住每条指令如何处理它的立即数;汇编程序会为您检查。这是一个有意的功能和一个好的设计。

特别是如果您有一个大型程序,它定义了一些汇编时常量,然后以各种方式使用它们:如果调整其中一个值导致指令不可编码,您会想知道它而不是默默地得到错误的结果。

(并且由于我使用了十进制示例,将数字写为十六进制数字文字不会改变汇编程序应该如何处理它们的任何内容。)


然而,与 ori 不同,andi 应该使用符号扩展。

不,在 MIPS 中,所有 3 条按位布尔逻辑指令 ( ori/ andi/ xori) 对其立即数进行零扩展。(符号扩展在 AND 的更多情况下会更有用,允许掩码在低位中只有几个零,但这不是 MIPS 的设计方式。尽管这会使截断到恰好 16 位的成本更高。)

https://ablconnect.harvard.edu/files/ablconnect/files/mips_instruction_set.pdf等文档确认了andi零扩展。我没有查看官方 MIPS 文档,但是这个信息在 Internet 上很普遍;您还可以测试以查看编译器以这种方式使用它来实现uint16_t或其他方式。

此外,MIPS 中的 andi vs. addi 指令具有负立即常数(涵盖启用扩展伪指令的 MARS,因此如果您使用andi不可编码为 16 位零的值,它将在另一个寄存器中构造完整的 32 位值-立即扩展)

于 2020-12-09T17:32:35.797 回答