MIPS中的andi与addi指令的立即数为负

问题描述 投票:1回答:3

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

andi $t2, $t2, -1

$ t2成为0x0005550

这已由MIPS模拟器确认[<1

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

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


脚注1:编者注:启用了“扩展伪指令”的MARS确实会将其扩展为多条指令,以在tmp寄存器中生成0xffffffff,从而使$t2保持不变。否则,MARS和SPIM都将其拒绝,并出现错误,表明该错误不可编码。其他汇编程序可能有所不同。
assembly mips sign-extension zero-extension immediate-operand
3个回答
5
投票

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

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

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

    不知何故,您误解了模拟器的功能。仿真器
  1. 是的实际值。
  2. ,您在0x55555550中没有$t2,在andi中没有0x5550,但是您却没有设置$t2(即)您的测试程序[ C0]正确。
  3. 但是,这不是我所期望的。我认为答案应该是0x55555550和0xFFFFFFFF = 0x55555550。我认为常数-1在和逻辑之前被符号扩展为0xFFFFFFFF。
是,这
是正确。而且,我将在下面解释发生了什么以及为什么。

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

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

mips模拟器和汇编器具有pseudo ops


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

“纯”伪操作的示例是li(“立即加载”)。它具有no

对应的指令,但通常生成两个指令序列:luiori(其中are物理指令)。

伪操作应该

不是与汇编器伪指令

,例如.text.data.word.eqv等混淆某些伪操作可能与实际的物理指令重叠。这就是您的示例所发生的情况。

实际上,汇编器将any

给定的指令作为potential伪操作进行检查。它可以确定in可以通过单个物理指令满足

intent

。如果没有,它将生成1-3条指令序列,并且可以使用[reserved] $at寄存器[$1]作为该序列的一部分。

mars中,要查看实际的实际指令,请查看源代码窗口的Basic列。为了我的回答的完整性,下面的所有内容均以开头的评论开头。

我创建了三个示例程序:

addi和您的原始帖子一样>

andi与您更正后的帖子一样>>

使用[[unsigned

参数的andi
  1. ((1)这是使用addi的原始问题的汇编源:
  2. .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。然后,执行
    two'scomplement
    加法运算,我们得到的最终结果为0x5555554F

    因此,汇编程序不需要为addi生成额外的指令,因此addi

    pseudo-op
    生成了一个

    real

    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生成了三个指令。
    A 

    real

    andi指令不会
    not
    符号扩展其直接参数。因此,我们可以在实际andi中使用的最大

    unsigned

    值是0xFFFF但是,通过指定-1,我们告诉汇编器我们

    did

    想要符号扩展名(即0xFFFFFFFF
    所以,汇编器可以用单个指令not充分实现意图,我们得到了上面的序列。并且生成的序列可以not使用andi,但必须使用寄存器形式:and。这是将andi生成的代码转换回更友好的asm源:

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

    结果,我们对0x555555500xFFFFFFFF进行和运算,这是0x55555550的[仍然不变]的值

    (3)这是[andiunsigned版本的来源:

        .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前缀)时,它将尝试以unsigned

    操作的形式实现该值。因此,它不需要签署扩展。并且,实数andi可以满足请求。
    其结果是0x5550

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

    而且,这里的结果将是0x15550 

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

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

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


    0
    投票

    MIPS Reference Sheet

    从本参考表开始,对于

    andi

    指令,它清楚地表明立即数上的符号扩展名是零扩展名。对于指令也是如此。对于您正在使用的操作顺序,这正是MIPS应该执行的操作。为了完成您打算做的事情,应将0xFFFFFFFF存储在其他寄存器中,并使用“
    and
    ”操作。

    0
    投票
    © www.soinside.com 2019 - 2024. All rights reserved.