问题描述
假设$ t2 = 0x55555550,然后执行以下指令:
andi $t2, $t2, -1
$ t2变为0x0005550
这已由MIPS模拟器
确认.但是,这不是我所期望的.我认为答案应该是0x55555550& 0xFFFFFFFF = 0x55555550.我认为常数-1在和逻辑之前被符号扩展为0xFFFFFFFF.但看来答案是0x55555550& 0x0000FFFF
为什么将-1的符号扩展为0x0000FFFF而不是0xFFFFFFFF
脚注1:编者注:启用了扩展伪指令"的MARS确实会将其扩展为多条指令,以在tmp寄存器中生成0xffffffff,从而使$t2保持不变.否则,MARS和SPIM都将其拒绝,并出现错误,表明该错误不可编码.其他汇编程序可能有所不同.
您的期望是正确的,但是您对实验结果的解释是不是
否,这是不正确的.因此,请执行以下操作之一:
- 不知何故,您误解了模拟器的功能.模拟器的实际值是您期望的 .
- 或,假设您没有在andi之前的$t2 中插入0x55555550,而是使用0x5550代替(即)测试程序无法正确设置$t2.
是的,这是正确的.而且,我将在下面解释发生了什么以及为什么.
不是. 是符号扩展到了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)这是>的 unsigned 版本的来源:
.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 emulator
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
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 the andi as you assume, but 0x5550 instead (i.e.) your test program doesn't set up $t2 correctly.
Yes, this is correct. And, I'll explain what is happening and why below.
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指令的立即数为负的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!