假设$ t2 = 0x55555550
执行以下后
andi $t2, $t2, -1
$ t2变为0x0005550
MIPS仿真器证实了这一点。但是,这不是我的预期。我认为答案应该是0x55555550& 0xFFFFFFFF = 0x55555550。 我认为常量-1在和逻辑之前符号扩展为0xFFFFFFFF。但似乎答案是0x55555550& 0x0000FFFF
为什么-1符号扩展为0x0000FFFF而不是0xFFFFFFFF
答案 0 :(得分:3)
您的期望是正确的,但您对实验结果的解释是不
$ t2变为0x0005550这由MIPS仿真器确认。
不,这是不正确的。所以,以下之一:
0x55555550
<{1}}之前$t2
中的andi
0x5550
,$t2
{} {1}}而是(即)您的测试程序未正确设置0xFFFFFFFF
。但是,这不是我的预期。我认为答案应该是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
列。
为了完整答案,以下所有内容均以最高评论开头。
我创建了三个示例程序:
addi
andi
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
伪操作生成了一个 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
至于结果,我们正在0x55555550
和0xFFFFFFFF
这是[{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)
在此参考表中,对于 andi 指令,它清楚地表明在立即数上完成的符号扩展是零扩展。它也适用于 ori 指令。对于您正在使用的操作序列,这正是MIPS应该做的。 为了做你想做的事,你应该在其他寄存器中存储0xFFFFFFFF,并使用“和”操作。