Search code examples
assemblyconditional-statementsmipsmips32

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

Ok, so I know how to take sum of n natural numbers by user input with Branch instruction but my question is: "How do I execute that same program without using Branch instructions (bge, bltv bne etc.)"


Solution

  • When there is a formula to compute something, as is the case with the specific problem statement in question, that's generally the best approach.


    However, if you are looking more broadly for conditional execution without using classic conditional branch instructions, you can have it using unconditional branch through register instructions, with MIPS, the jr <reg>, jump register.

    Background: the conditional branch instructions test a condition and either branch or fall through to the next instruction — that is to say, there is a choice of two destinations (for the subsequently executing instruction stream) that is made dynamically.

    While a jump through register will always change the flow of control and never "fall through", by definition, a jump through register can set any number of different destinations, by computing one (of several) prior to that instruction.

    The simple way to look at it is to compute the following:

        done := i < N
        whereToGo := (&doneLabel * done) + (&LoopTop * !done)
    

    First, a boolean is computed, whose value is either 1 or 0.  In the above whereToGo computation, only one of the two terms will be non-zero, using multiplicative identity, 1, in one case and the null factor, 0, in the other case.

    (Let's note that in MIPS the < operation to form a boolean is done with slt and similar, and in particular, without use of conditional branch instructions.)

    Here's a larger example, using a loop:

        ... // loop initialization
    loopTop:
        <do something>
        done := i < N
        <reg> := (&doneLabel * done) + (&LoopTop * !done)
        jr <reg>
     doneLabel:
        ...
    

    For those who wish to avoid multiplication to accomplish this, we can use the AND instead.  To use an AND operation, we need not a boolean 1 vs. 0, but an altered boolean -1 vs. 0.  For AND, -1 is the identity and 0 is the null factor.

        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)
    

    In the above, mask will be will be 0 when done is true (and we want to exit, so we use ~mask on that term), while it will be -1 when done is false.

    Since one term will always be 0, then addition, + vs. OR, | are equivalent.


    This approach can be generalized with more terms to choose between more destinations, of course, as long as only one term's boolean evaluates to identity and all the others are null.