Confused by the if Jumps in MIPS

Viewed 211

I am having difficulty understanding why the jump in my bge statement jumps over to the label and then ends while the other two execute the label and return. I am somewhat new to this, and hopefully, there is a link or another post with a similar question that I couldn't find. I have left comments on how it looks to me and the result of the code at the end of nop, and I might be wrong, and if I am hopefully, I can be guided on how it should work.

.globl main
.data
.text
main:

    li $t5, 8
    li $t6, 9 
    blt $t6,$t5, L1 // if (9 < 8) goto L1
    addi $t1, $t1, 2 // $t1 = 2
L1: 
    addi $t1, $t1, 1 // $t1 = 3
    nop // $t1 = 3 
    li $t7, 2
    li $t3, 2
    bne $t7,$t3, L2 // if ( 2 == 2) goto L2
    addi $t3, $t3, 2 // $t3 = 9
L2: 
    addi $t3, $t3, 5 // $t3 = 7
    nop // $t3 = 9
    li $t6, 4
    li $t5, 1
    bge $t6,$t5, L3 // if (4 >= 1) goto L3
    add $t6, $t6, $t5
    addi $t6, $t6, 3  
L3: 
    addi $t6, $t6, 5 // $t6 = 9
    nop // $t6 = 9
2 Answers

First, terminolgy:

Labels don't execute.  They are in the assembly code but take/get no machine code, and the processor never sees them.  Thus, labels alone cannot change the flow of control, only processor instructions can do that.

Labels are there in assembly code, and they are used to inform the assembler what offsets to chose in the machine code instruction for assembly instructions that reference them (the labels).

Nothing in this code has anything that "returns".  Typically we reserve the term return for subroutine returning back to its caller, via an indirect branch.

As far as ending goes, you do not have a valid end of program instruction sequence so, it simply runs off the end when it is done.

The first branch, blt should not fire (should instead fall throuh) b/c 9 is indeed not less than 8.

Your comment on the bne is inverse to the operation written in assembly, perhaps that will clear something up.  This branch will also not fire because 2 is indeed equal to 2.

The last branch will fire because 4 is >= 1, and so will skip a few instructions ahead.

Your should initialize $t1 to zero at the beginning instead of relying on the simulator to clear it to zero.

You are correct that $t6 will end up with 9 = 4+5.

The thing that may be confusing you is that MIPS has branch delay slots -- which means that whenever you have a branch (conditional or unconditional, it doesn't matter), the instruction immediately after the branch instruction will always be executed before the branch actually branches. So in this code:

    blt $t6,$t5, L1 // if (9 < 8) goto L1
    addi $t1, $t1, 2 // $t1 = 2
L1: 

even if the condition was true, the branch would appear to have no effect, since the instruction after the branch (whch is the only one between it and the target) would be executed anyways.

In the code

    li $t6, 4
    li $t5, 1
    bge $t6,$t5, L3 // if (4 >= 1) goto L3
    add $t6, $t6, $t5
    addi $t6, $t6, 3  
L3: 
    addi $t6, $t6, 5 // $t6 = 9

The add $t6, $t6, $t5 instruction will always be executed, so when the branch condition is true, only the addi $t6, $t6, 3 will be skipped.

The easiest way to deal with this is to just always put a nop instruction after a branch. That will work but is inefficient (wasted one instruction slot and cycle), so it is better if you can figure out how to put a useful instruction there. Note that the instruction after the branch is not executed until after the conditional branch computes its test, so you can't just move the instruction before the branch after the branch.

Recent MIPS implementation have 'compact' versions of the branch instructions that do not have delay slots. You can use them by adding a c to the instruction

bgec $t6,$t5, L3 // if (4 >= 1) goto L3

if your simulator/system supports them

Related