MIPS中的Andi与Addi指令的立即数为负 [英] andi vs. addi instruction in MIPS with negative immediate constant
问题描述
假设$ 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都将其拒绝,并出现错误,表明该错误不可编码.其他汇编程序可能有所不同.
您的期望是正确的,但是您对实验结果的解释是不是
$ t2变为0x0005550,这已由MIPS仿真器确认.
否,这是不正确的.因此,请执行以下操作之一:
- 不知何故,您误解了模拟器的功能.模拟器的实际值是您期望的 .
- 或,假设您没有在
andi
之前的$t2
中插入0x55555550
,而是使用0x5550
代替(即)测试程序无法正确设置$t2
.
但是,这不是我所期望的.我认为答案应该是0x55555550& 0xFFFFFFFF = 0x55555550.我认为常数-1在和逻辑之前被符号扩展为0xFFFFFFFF.
是的,这是正确的.而且,我将在下面解释发生了什么以及为什么.
但似乎答案是0x55555550& 0x0000FFFF.为什么-1的符号扩展为0x0000FFFF而不是0xFFFFFFFF
不是. 是符号扩展到了0xFFFFFFFF
.同样,您错误地读取了实验结果[或您的测试程序有错误].
mips
模拟器和汇编器具有伪操作 .
这些指令可能以真实的物理指令形式存在或不存在.但是,它们由汇编程序解释以生成一系列物理/真实指令.
纯"伪操作的一个示例是li
(立即加载").它没有相应的指令,但通常会生成两个指令序列:lui
,ori
(这是 物理指令).
不应将伪操作与汇编指令 (例如.text
,.data
,.word
,.eqv
等)混淆.
某些伪操作可能与实际的物理指令重叠.这就是您的示例所发生的情况.
实际上,汇编程序将给定指令的任何检查为潜在伪操作.它可以确定in可以通过一条物理指令满足意图.如果没有,它将生成1-3条指令序列,并且可以使用[reserved] $at
寄存器[$1
]作为该序列的一部分.
在mars
中,要查看实际的实际指令,请查看源代码窗口的Basic
列.
为使我的回答更加完整,以下所有内容均以开头的评论开头.
我创建了三个示例程序:
- 您的原始帖子中的
addi
- 已更正帖子中的
andi
- 使用 unsigned 自变量的
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
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
生成了三个指令.
real andi
指令不会 not 符号扩展其直接参数.因此,我们可以在实际andi
中使用的最大 unsigned 值是0xFFFF
但是,通过指定-1
,我们告诉汇编程序我们 did 需要符号扩展名(即0xFFFFFFFF
)
因此,汇编器可能只用一条指令 not 就无法实现意图,我们得到了上面的序列.并且生成的序列可以不使用andi
,但是必须使用寄存器形式:and
.这是andi
生成的代码,这些代码被转换回更友好的asm源:
lui $at,0xFFFF
ori $at,$at,0xFFFF
and $t3,$t2,$at
结果是,我们对0x55555550
和0xFFFFFFFF
进行和运算,这是[c0>的[仍然不变]]
(3)这是
.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
Assume $t2=0x55555550
, then executing the following instruction:
andi $t2, $t2, -1
$t2 becomes 0x0005550
This is confirmed by the MIPS emulator1
However, it is not what I expected. I think the answer should be 0x55555550 & 0xFFFFFFFF = 0x55555550. I think the constant -1 was sign extended to 0xFFFFFFFF before the and logic. But it appears that the answer was 0x55555550 & 0x0000FFFF
Why -1 is sign extended to 0x0000FFFF instead of 0xFFFFFFFF
Footnote 1: Editor's note: MARS with "extended pseudo-instructions" enabled does expand this to multiple instructions to generate 0xffffffff
in a tmp register, thus leaving $t2
unchanged. Otherwise MARS and SPIM both reject it with an error as not encodeable. Other assemblers may differ.
Your expectation is correct, but your interpretation of your experimental results is not
$t2 becomes 0x0005550 This is confirmed by the MIPS emulator.
No, this is incorrect. So, one of the following:
- Somehow, you're misreading what the emulator is doing. The actual value from the emulator is what you expected it to be.
- Or, you don't have
0x55555550
in$t2
before theandi
as you assume, but0x5550
instead (i.e.) your test program doesn't set up$t2
correctly.
However, it is not what I expected. I think the answer should be 0x55555550 & 0xFFFFFFFF = 0x55555550. I think the constant -1 was sign extended to 0xFFFFFFFF before the and logic.
Yes, this is correct. And, I'll explain what is happening and why below.
But it appears that the answer was 0x55555550 & 0x0000FFFF. Why -1 is sign extended to 0x0000FFFF instead of 0xFFFFFFFF
It wasn't. It was sign extended to 0xFFFFFFFF
. Again, you're reading the experimental results incorrectly [or your test program has a bug].
mips
simulators and assemblers have pseudo ops.
These are instructions that may or may not exist as real, physical instructions. However, they are interpreted by the assembler to generate a sequence of physical/real instructions.
An example of a "pure" pseudo-op is li
("load immediate"). It has no corresponding instruction, but usually generates a two instruction sequence: lui
, ori
(which are physical instructions).
Pseudo-ops should not be confused with assembler directives, such as .text
, .data
, .word
, .eqv
, etc.
Some pseudo-ops can overlap with actual physical instructions. That is what is happening with your example.
In fact, the assembler examines any given instruction as a potential pseudo-op. It may determine that in can fulfill the intent with a single physical instruction. If not, it will generate a 1-3 instruction sequence and may use the [reserved] $at
register [which is $1
] as part of that sequence.
In mars
, to see the actual real instructions, look in the Basic
column of the source window.
For the sake of the completeness of my answer, all that follows is prefaced by the top comments.
I've created three example programs:
- The
addi
as in your original post - The
andi
as in your corrected post - An
andi
that uses an unsigned argument
(1) Here is the assembler source for your original question using addi
:
.text
.globl main
main:
li $t2,0x55555550
addi $t3,$t2,-1
nop
Here is how mars
interpreted it:
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
will sign extend its 16 bit immediate, so we have 0xFFFFFFFF
. Then, doing a two's complement add operation, we have a final result of 0x5555554F
Thus, the assembler didn't need to generate extra instructions for the addi
, so the addi
pseudo-op generated a single real addi
(2) Here is the andi
source:
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,-1
nop
Here is the assembly:
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
Whoa! What happened? The andi
generated three instructions.
A real andi
instruction does not sign extend its immediate argument. So, the largest unsigned value we can use in a real andi
is 0xFFFF
But, by specifying -1
, we told the assembler that we did want sign extension (i.e. 0xFFFFFFFF
)
So, the assembler could not fulfull the intent with a single instruction and we get the sequence above. And the generated sequence could not use andi
but had to use the register form: and
. Here is the andi
generated code converted back into more friendly asm source:
lui $at,0xFFFF
ori $at,$at,0xFFFF
and $t3,$t2,$at
As to result, we're anding 0x55555550
and 0xFFFFFFFF
which is a [still unchanged] value of 0x55555550
(3) Here is the source for an unsigned version of andi
:
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,0xFFFF
nop
Here is the assembler output:
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
When the assembler sees that we're using a hex constant (i.e. the 0x
prefix), it tries to fulfill the value as an unsigned operation. So, it doesn't need to sign extend. And, the real andi
can fulfill the request.
The result of this is 0x5550
Note that if we had used a mask value of 0x1FFFF
, that would be unsigned. But, it's larger than 16 bits, so the assembler would generate a multi-instruction sequence to fulfill the request.
And, the result here would be 0x15550
这篇关于MIPS中的Andi与Addi指令的立即数为负的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!