我正在阅读以下有关汇编语言代码的摘录:
“可以在组装中使用标签代替计算分支和跳转指令的精确值。以下是示例。”
int isNeg(int a0) {
if (a0 < 0) {
return 1;
} else {
return 0;
}
}
isNeg:
slt $t0 $a0 $0
beq $t0 $0 isPos
jr $ra
isPos:
add $v0 $0 $0
jr $ra
这就是我的解释方式(请根据我做的任何错误假设对我进行纠正):
isNeg:
slt $t0 $a0 $0 // store ($a0 < 0) in $t0
beq $t0 $0 isPos // if ($t0 == 0) branch by 0 bytes
jr $ra
isPos:
add $v0 $0 $0 // store 0+0=0 in $v0
jr $ra
因此,如果我的假设在这里是正确的,则如果$ a为负,则不执行任何操作;如果$ a为正,则以0进行分支,等效于不执行任何操作。谁能对此有所启发?
答案 0 :(得分:1)
有人能对此有所启发吗?
如果我理解正确,那么本文是从书中摘录的。该示例旨在显示某些指令的效果,而不是显示可以在真实程序中(例如,在具有MIPS CPU的WLAN路由器上)真正找到的“真实”代码。
这本书的作者唯一想展示的是标签的工作方式,因此他写了一个(愚蠢的)包含标签的示例。
如果$ a为负,我们什么也不做
正确(假设jr $ra
在实际MIPS CPU中不是不是 delayed branch)
我认为这本书的作者忘记了addi $v0 $0 -1
指令。
beq $t0 $0 isPos
如果$ a为正,那么我们以0分支
如果beq
是 delayed branch,这是正确的。
在这种情况下,CPU将首先在beq
或jr
指令之后立即执行该指令,然后才实际进行分支/跳转。
但是,在这种情况下,在大多数实际的MIPS CPU上,紧随jr
指令之后的beq
指令是不允许的。因此,我认为这里不是这种情况。
如果使用的模拟器不模拟延迟时隙,则beq
指令将跳4个字节(在jr
指令上)。
如果使用真正的MIPS CPU和汇编器,则在每个跳转/分支指令(GNU中的nop
选项)之后插入add $0 $0 $0
(例如.set reorder
)指令时,{{1} }指令将跳8个字节(在beq
指令及其后的jr
指令上方)。跳转之后,执行nop
指令。