您的期望是正确的,但您对实验结果的解释不正确
$t2 变为 0x0005550 这由 MIPS 仿真器确认。
不,这是不正确的。因此,以下之一:
- 不知何故,你误读了模拟器在做什么。模拟器的实际值是您所期望的。
- 或者,您没有像您假设的那样,
0x55555550
而是$t2
(即)您的测试程序设置不正确。andi
0x5550
$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
源窗口的列。
为了我的回答的完整性,接下来的所有内容都以最热门的评论开头。
我创建了三个示例程序:
- 与
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
伪操作生成了单个实数 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