具有负常数的MIPS中的addi指令

时间:2016-10-17 15:22:09

标签: mips

假设$ t2 = 0x55555550

执行以下后

andi $t2, $t2, -1

$ t2变为0x0005550

MIPS仿真器证实了这一点。但是,这不是我的预期。我认为答案应该是0x55555550& 0xFFFFFFFF = 0x55555550。 我认为常量-1在和逻辑之前符号扩展为0xFFFFFFFF。但似乎答案是0x55555550& 0x0000FFFF

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

3 个答案:

答案 0 :(得分:3)

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

  

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

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

  1. 不知何故,你误读了模拟器正在做的事情。模拟器的实际值期望的
  2. ,假设0x55555550 <{1}}之前$t2 中的andi 0x5550$t2 {} {1}}而是(即)您的测试程序未正确设置0xFFFFFFFF
  3.   

    但是,这不是我的预期。我认为答案应该是0x55555550&amp; 0xFFFFFFFF = 0x55555550。我认为常量-1在和逻辑之前符号扩展到0xFFFFFFFF。

    是的,此 正确无误。并且,我将解释正在发生的事情以及下面的原因。

      

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

    不是 符号已扩展为mips。同样,您不正确地阅读实验结果[或者您的测试程序有错误]。

    li模拟器和汇编程序有伪操作

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

    &#34;纯粹&#34;伪操作是lui(&#34;立即加载&#34;)。它有 no 对应的指令,但通常会生成两个指令序列:ori.text(其中物理指令)。

    伪操作应该与汇编程序指令混淆,例如.data.word.eqv,{{ 1}}等等。

    某些伪操作可能与实际的物理指令重叠。这就是你的例子。

    实际上,汇编程序将任何给定指令检查为 potential 伪操作。它可以确定使用单个物理指令可以实现 intent 。如果不是,它将生成1-3指令序列,并可以使用[reserved] $at寄存器[$1]作为该序列的一部分。

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

    为了完整答案,以下所有内容均以最高评论开头。

    我创建了三个示例程序:

    1. 原始帖子中的addi
    2. 正如您更正的帖子中的andi
    3. 使用无符号参数的andi
    4. (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 伪操作生成了一个 real < / em> 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
      

      至于结果,我们正在0x555555500xFFFFFFFF这是[{1}}

      的[仍未更改]值

      (3)以下是0x55555550 未签名版本的来源:

      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 前缀)时,它会尝试将该值作为 unsigned 操作来实现。因此,它不需要签名扩展。并且,真正的0x可以满足请求。

      结果是andi

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

      并且,此处的结果为0x1FFFF

答案 1 :(得分:0)

根据specification,立即值为16位宽。

因此,andi $t2, $t2, -1可以理解为andi $t2, $t2, 0xFFFF

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

答案 2 :(得分:0)

MIPS Reference Sheet

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