Lin*_*eng 1 assembly mips sign-extension zero-extension immediate-operand
假设 $t2= 0x55555550,然后执行以下指令:
andi $t2, $t2, -1
Run Code Online (Sandbox Code Playgroud)
$t2 变成 0x0005550
MIPS 仿真器1证实了这一点
然而,这不是我所期望的。我认为答案应该是 0x55555550 & 0xFFFFFFFF = 0x55555550。我认为常量 -1 在和逻辑之前被符号扩展为 0xFFFFFFFF。但似乎答案是 0x55555550 & 0x0000FFFF
为什么 -1 被符号扩展为 0x0000FFFF 而不是 0xFFFFFFFF
脚注 1:编者注:启用“扩展伪指令”的 MARS 确实将其扩展为多条指令以0xffffffff在 tmp 寄存器中生成,因此保持$t2不变。否则 MARS 和 SPIM 都会以不可编码的错误拒绝它。其他汇编程序可能有所不同。
您的期望是正确的,但您对实验结果的解释不正确
$t2 变为 0x0005550 这是 MIPS 模拟器确认的。
不,这是不正确的。因此,以下情况之一:
0x55555550在$t2 之前的andi为你承担,但0x5550代替(即)你的测试程序没有设置$t2正确。然而,这不是我所期望的。我认为答案应该是 0x55555550 & 0xFFFFFFFF = 0x55555550。我认为常量 -1 在和逻辑之前被符号扩展为 0xFFFFFFFF。
是的,这是正确的。而且,我将在下面解释正在发生的事情以及原因。
但似乎答案是 0x55555550 & 0x0000FFFF。为什么 -1 被符号扩展为 0x0000FFFF 而不是 0xFFFFFFFF
这是不是。这是符号扩展到0xFFFFFFFF。同样,您错误地阅读了实验结果[或您的测试程序有错误]。
mips模拟器和汇编器有伪操作。
这些指令可能作为真实的物理指令存在,也可能不存在。但是,它们由汇编程序解释以生成一系列物理/实际指令。
“纯”伪操作的一个例子是li(“立即加载”)。它没有相应的指令,但通常会生成两个指令序列:lui, ori(它们是物理指令)。
伪操作应该不与汇编相混淆的指令,例如.text,.data,.word,.eqv,等。
一些伪操作可能与实际的物理指令重叠。这就是你的例子正在发生的事情。
事实上,汇编器将任何给定指令检查为潜在的伪操作。它可以确定可以通过单个物理指令实现意图。如果不是,它将生成一个 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
Run Code Online (Sandbox Code Playgroud)
以下是它的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
Run Code Online (Sandbox Code Playgroud)
addi将立即对其 16 位进行符号扩展,因此我们有0xFFFFFFFF. 然后,做一个二进制补码加法运算,我们得到最终结果0x5555554F
因此,汇编程序不需要为 生成额外的指令addi,因此addi 伪操作生成了一个实数 addi
(2)andi来源:
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,-1
nop
Run Code Online (Sandbox Code Playgroud)
这是大会:
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
Run Code Online (Sandbox Code Playgroud)
哇!发生了什么?将andi产生三条指令。
一个真正的 andi指令并没有签署延长其直接的说法。因此,我们可以在实数中使用的最大无符号值andi是0xFFFF
但是,通过指定-1,我们告诉汇编器我们确实想要符号扩展(即0xFFFFFFFF)
所以,汇编器可能不fulfull意图用一条指令,我们得到上面的序列。并且生成的序列不能使用andi而不得不使用注册表:and。这是andi转换回更友好的 asm 源代码的生成代码:
lui $at,0xFFFF
ori $at,$at,0xFFFF
and $t3,$t2,$at
Run Code Online (Sandbox Code Playgroud)
至于结果,我们正在 anding0x55555550并且0xFFFFFFFF这是一个 [仍然不变] 的值0x55555550
(3) 以下是未签名版本的来源andi:
.text
.globl main
main:
li $t2,0x55555550
andi $t3,$t2,0xFFFF
nop
Run Code Online (Sandbox Code Playgroud)
这是汇编器输出:
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
Run Code Online (Sandbox Code Playgroud)
当汇编器看到我们正在使用十六进制常量(即0x前缀)时,它会尝试将值作为无符号运算来实现。所以,它不需要签署扩展。而且,真正的andi可以满足要求。
这样做的结果是 0x5550
请注意,如果我们使用了 的掩码值0x1FFFF,那将是无符号的。但是,它大于 16 位,因此汇编器会生成一个多指令序列来满足请求。
而且,这里的结果将是 0x15550
| 归档时间: |
|
| 查看次数: |
9020 次 |
| 最近记录: |