不使用分支指令的 n 个自然数(1 到 n)的 MIPS 代码总和
MIPS CODE sum of n natural numbers (1 to n) WITHOUT USING BRANCH INSTRUCTION
.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, $t5, 1
j iteration
end:
li $v0, 4
la $a0, show
syscall
li $v0, 1
move $a0, $s2
syscall
好的,所以我知道如何使用分支指令通过用户输入获取 n 个自然数的总和,但我的问题是:“如何在不使用分支指令的情况下执行相同的程序(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 case 和 null 因子 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)
在上面,当 done
为真时,mask
将为 0(我们想退出,所以我们在该术语上使用 ~mask
),而它会当 done 为 false 时为 -1。
既然一项永远是0,那么加法,+
与OR,|
是等价的。
当然,可以使用更多项在更多目的地之间进行选择来推广这种方法,只要只有一个项的布尔值评估为同一性,而所有其他项都为空即可。
.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, $t5, 1
j iteration
end:
li $v0, 4
la $a0, show
syscall
li $v0, 1
move $a0, $s2
syscall
好的,所以我知道如何使用分支指令通过用户输入获取 n 个自然数的总和,但我的问题是:“如何在不使用分支指令的情况下执行相同的程序(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 case 和 null 因子 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)
在上面,当 done
为真时,mask
将为 0(我们想退出,所以我们在该术语上使用 ~mask
),而它会当 done 为 false 时为 -1。
既然一项永远是0,那么加法,+
与OR,|
是等价的。
当然,可以使用更多项在更多目的地之间进行选择来推广这种方法,只要只有一个项的布尔值评估为同一性,而所有其他项都为空即可。