我正在阅读以下有关汇编语言代码的摘录:
“标签可用于组装,以替换[sic]计算分支和跳转指令的精确值。以下是一个例子。”
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分支,这相当于什么都不做。任何人都可以对此有所了解吗?
任何人都可以对此有所了解吗?
如果我理解正确,这个文本来自一本书。示例是显示某些指令的效果,而不是显示真正可以在实际程序中找到的“真实”代码(例如,在具有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
)指令,则beq
指令将跳过8个字节(通过jr
指令和后面的nop
指令) )。跳转之后执行add $v0 $0 $0
指令。