1

假设 $t2= 0x55555550,然后执行以下指令:

andi $t2, $t2, -1

$t2 变成0x0005550

MIPS 仿真器1证实了这一点

然而,这不是我所期望的。我认为答案应该是 0x55555550 & 0xFFFFFFFF = 0x55555550。我认为常数 -1 在 and 逻辑之前被符号扩展为 0xFFFFFFFF 。但似乎答案是 0x55555550 & 0x0000FFFF

为什么 -1 符号扩展为 0x0000FFFF 而不是 0xFFFFFFFF


脚注 1:编者注:启用“扩展伪指令”的 MARS 确实将其扩展为多个指令以0xffffffff在 tmp 寄存器中生成,因此保持$t2不变。否则,MARS 和 SPIM 都会以不可编码的错误拒绝它。其他汇编程序可能不同。

4

3 回答 3

6

您的期望是正确的,但您对实验结果的解释不正确

$t2 变为 0x0005550 这由 MIPS 仿真器确认。

不,这是不正确的。因此,以下之一:

  1. 不知何故,你误读了模拟器在做什么。模拟器的实际值您所期望的。
  2. 或者,您没有像您假设的那样,0x55555550而是$t2 即)您的测试程序设置不正确。andi0x5550$t2

然而,这不是我所期望的。我认为答案应该是 0x55555550 & 0xFFFFFFFF = 0x55555550。我认为常数 -1 在 and 逻辑之前被符号扩展为 0xFFFFFFFF 。

是的,这正确的。而且,我将在下面解释发生了什么以及为什么。

但似乎答案是 0x55555550 & 0x0000FFFF。为什么 -1 符号扩展为 0x0000FFFF 而不是 0xFFFFFFFF

不是。_ 它符号扩展到0xFFFFFFFF。同样,您正在错误地阅读实验结果[或者您的测试程序有错误]。


mips模拟器和汇编器有伪操作

这些指令可能作为真实的物理指令存在,也可能不存在。但是,它们由汇编器解释以生成一系列物理/实际指令。

“纯”伪操作的一个示例是li(“立即加载”)。它没有对应的指令,但通常会生成两个指令序列:lui, ori(它们物理指令)。

伪操作不应汇编指令混淆,例如.text, .data, .word,.eqv等。

一些伪操作可以与实际的物理指令重叠。这就是您的示例所发生的情况。

事实上,汇编器将任何给定指令视为潜在的伪操作。它可以确定 in 可以通过单个物理指令实现意图。如果不是,它将生成一个 1-3 指令序列,并且可以使用 [reserved]$at寄存器 [which is $1] 作为该序列的一部分。

mars中,要查看实际的真实说明,请查看Basic源窗口的列。

为了我的回答的完整性,接下来的所有内容都以最热门的评论开头。

我创建了三个示例程序:

  1. addi您原来的帖子一样
  2. andi您更正的帖子中所述
  3. 使用andi符号参数的

(1) 这是您原始问题的汇编源代码addi

    .text
    .globl  main
main:
    li      $t2,0x55555550
    addi    $t3,$t2,-1
    nop

以下是它的mars解释方式:

 Address    Code        Basic                     Source

0x00400000  0x3c015555  lui $1,0x00005555         4     li      $t2,0x55555550
0x00400004  0x342a5550  ori $10,$1,0x00005550
0x00400008  0x214bffff  addi $11,$10,0xffffffff   5     addi    $t3,$t2,-1
0x0040000c  0x00000000  nop                       6     nop

addi符号扩展其 16 位立即数,所以我们有0xFFFFFFFF. 然后,做一个补码加操作,我们有一个最终的结果0x5555554F

因此,汇编器不需要为 生成额外的指令addi,因此addi 伪操作生成了单个实数 addi


(2)andi来源:

    .text
    .globl  main
main:
    li      $t2,0x55555550
    andi    $t3,$t2,-1
    nop

这是组装:

 Address    Code        Basic                     Source

0x00400000  0x3c015555  lui $1,0x00005555         4     li      $t2,0x55555550
0x00400004  0x342a5550  ori $10,$1,0x00005550
0x00400008  0x3c01ffff  lui $1,0xffffffff         5     andi    $t3,$t2,-1
0x0040000c  0x3421ffff  ori $1,$1,0x0000ffff
0x00400010  0x01415824  and $11,$10,$1
0x00400014  0x00000000  nop                       6     nop

哇!发生了什么?andi生成三个指令。

一个真正的 andi指令没有符号扩展它的直接参数。因此,我们可以在实数中使用的最大无符号andi值是0xFFFF

但是,通过指定-1,我们告诉汇编器我们确实想要符号扩展(即0xFFFFFFFF

因此,汇编器无法一条指令完成意图,我们得到了上面的序列。并且生成的序列不能使用andi但必须使用寄存器形式:and. 以下是将andi生成的代码转换回更友好的 asm 源代码:

    lui     $at,0xFFFF
    ori     $at,$at,0xFFFF
    and     $t3,$t2,$at

至于结果,我们是 anding0x55555550并且0xFFFFFFFF是 [仍然未更改] 的值0x55555550


(3) 以下是 的未签名版本的来源andi

    .text
    .globl  main
main:
    li      $t2,0x55555550
    andi    $t3,$t2,0xFFFF
    nop

这是汇编程序的输出:

 Address    Code        Basic                     Source

0x00400000  0x3c015555  lui $1,0x00005555         4     li      $t2,0x55555550
0x00400004  0x342a5550  ori $10,$1,0x00005550
0x00400008  0x314bffff  andi $11,$10,0x0000ffff   5     andi    $t3,$t2,0xFFFF
0x0040000c  0x00000000  nop                       6     nop

当汇编器看到我们使用的是十六进制常量(即0x前缀)时,它会尝试将值作为无符号操作来完成。所以,它不需要签名扩展。并且,真正的andi可以满足要求。

结果是0x5550

请注意,如果我们使用掩码值0x1FFFF,那将是无符号的。但是,它大于 16 位,因此汇编器会生成一个多指令序列来满足请求。

而且,这里的结果是0x15550

于 2016-10-18T21:15:21.440 回答
0

根据规范,立即数是 16 位宽的。

因此,andi $t2, $t2, -1可以读作andi $t2, $t2, 0xFFFF

所有逻辑运算都将立即数视为位串,并将其零扩展为 32 位。

于 2016-10-18T12:49:38.833 回答
0

MIPS 参考表

从这个参考表中,对于andi指令,它清楚地表明在立即数上进行的符号扩展是零扩展。ori指令也类似。对于您正在使用的操作序列,这正是 MIPS 应该做的。为了做你想做的事情,你应该将 0xFFFFFFFF 存储在其他寄存器中,并使用“”操作。

于 2017-04-16T09:37:46.900 回答