问题描述
.data
input: .asciiz "Enter limit for the sum of natural number = "
show: .asciiz " \n sum of natural numbers are = "
.text
main:
#get the integer input from user
li $v0,4
la $a0,input
syscall
li $v0,5
syscall
move $s5,$v0
li $v0,1
move $a0,$s5
syscall
addi $t5,$t5,0
iteration:
blt $t5,$s5,increment
j end
increment:
add $s2,$s2,$t5
addi $t5,1
j iteration
end:
li $v0,show
syscall
li $v0,$s2
syscall
好的,所以我知道如何通过用户输入使用 Branch 指令计算 n 个自然数的总和,但我的问题是:“如何在不使用 Branch 指令(bge、bltv bne 等)的情况下执行相同的程序? "
解决方法
1..n 之和等于 (n*(n+1))/2
在伪代码中:
temp := (input + 1)
temp := (temp * input)
result := (temp >> 1)
,
当有一个公式来计算某些东西时,就像所讨论的特定问题陈述的情况一样,这通常是最好的方法。
但是,如果您更广泛地寻找不使用经典条件分支指令的条件执行,您可以使用无条件分支通过寄存器指令,使用 MIPS,jr <reg>
,跳转寄存器。
背景:条件分支指令测试一个条件,然后分支或落入下一条指令——也就是说,有两个目的地的选择(对于随后执行的指令流)是动态的。
>虽然跳转寄存器将始终改变控制流并且永远不会“失败”,但根据定义,跳转寄存器可以通过在该指令之前计算一个(多个)来设置任意数量的不同目标。
查看它的简单方法是计算以下内容:
done := i < N
whereToGo := (&doneLabel * done) + (&LoopTop * !done)
首先,计算一个布尔值,其值为 1 或 0。在上面的 whereToGo
计算中,只有两项中的一项是非零的,在一种情况下使用乘法恒等式 1,并且在另一种情况下,零因子为 0。
(请注意,在 MIPS 中,形成布尔值的 <
操作是使用 slt
和类似方法完成的,特别是没有使用条件分支指令。)
这是一个更大的例子,使用循环:
... // loop initialization
loopTop:
<do something>
done := i < N
<reg> := (&doneLabel * done) + (&LoopTop * !done)
jr <reg>
doneLabel:
...
对于那些希望避免乘法来实现这一点的人,我们可以使用 AND
代替。要使用 AND
运算,我们不需要布尔值 1 与 0,而是需要更改的布尔值 -1 与 0。对于 AND
,-1 是身份,0 是空因子。
done := i < N // produces 1 or 0 result (for true,false,resp.)
mask := done - 1 // produces 0 or -1 result
whereToGo := (&doneLabel & ~mask) | (&LoopTop & notDone)
在上面,当 mask
为真时,done
将是 0(并且我们想退出,所以我们在该术语上使用 ~mask
),而它将是 - 1 when done 是假的。
因为一项永远是 0,所以加法,+
与 OR,|
是等价的。
当然,这种方法可以通过更多的术语在更多目的地之间进行选择来推广,只要只有一个术语的布尔值计算为标识,而其他所有术语都为空。