CSc 116 notes

Previous page Back     Next Next page  Contents

5) Control structures

So far we have seen how to move data between memory and processor registers, and how to do arithmetic in the registers. All are programs have been linear, a list of instructions carried out from start to exit. In this chapter we look at the assembly language instructions that alter the control flow of a program, and then at how these can be used to implement the high-level language constructs of if, while, & for.

The order of program execution is determined by the PC (program counter). It can be altered by changing the PC. This can be done by jump and branch instructions. Jump is just the notorious go to that has been supressed from high level languages. Branch instructions are so named because they offer an alternative, to branch or not. A "flow chart" of a program "branches" where there is a branch instruction.

Assembly language instructions for control of execution

Unconditional jump

A jump instruction puts the address of a label into the PC. Execution continues from that point. jar also saves the old PC value as a "return address" in register $ra ($31). This is used for procedure call, see chapter 8.

Instruction Example Meaning
j label j do_it_again next instruction is at the label do_it_again:
jal label
(jump and link)
jal my_proc execution of procedure my_proc will start.
$ra holds address of instruction following the jal
jr Rsrc
(jump register)
jr $ra Retrun from procedure call, by putting
$ra value back into the PC

Conditional branch

These instructions branch, that is, change the PC to the label, when a condition is true. The condition is always a comparison of 2 registers, or a register and aconstant. Normally, they are compared as signed numbers. Where it matters, you get an unsigned compare by ending the operation code with a u.

Instruction Branch to label if Unsigned
beq Rsrc1, Src2, label Rsrc1 = Src2
bne Rsrc1, Src2, label Rsrc1 <> Src2
blt Rsrc1, Src2, label Rsrc1 < Src2 bltu
bgt Rsrc1, Src2, label Rsrc1 > Src2 bgtu
ble Rsrc1, Src2, label Rsrc1 <= Src2 bleu
bge Rsrc1, Src2, label Rsrc1 >= Src2 bgeu

Comparison with zero is useful, and can be done simply by using $0 as Src2 (remember, it always holds the value 0). For your convenience, you can write comparison with zero by putting a z at the end of the operation code. Thus these two instructions are the same:

               blt  $t0, $0, cold
               bltz $t0, cold

(You can't use both u and z. There would be no point.)

These are all the instructions you need to write very complicated programs. In fact, you can write programs that are too complicated with them, so complicated that you have to explain the flow with so many arrows that your paper looks like a bunch of spaghetti. You must avoid "spaghetti programs" and use the well-known, disciplined constructs you have learned in your other programming classes.

IF constructs: choosing alternatives

In an IF statement, you "branch around" a section of code. In an IF - THEN - ELSE construct, one of two alternatives is executed. Here are some pseudo code examples, with assembly language translations. (Assume that swim and cycle are labels of .asciiz strings containing the phrases.)

IF num < 0 THEN
    num := - num
ENDIF
{absolute value}
IF temperature >= 25 THEN
     activity := "go swimming"
ELSE
     activity := "ride bicycle"
ENDIF
print (activity)
    lw   $t0, num
    bgez $t0, endif0
# must be ltz------
        sub  $t0,$0,$t0   # 0-num 
        sw   $t0, num
endif0:
#  num is now guaranteed non-negative
    lw  $t0, temperature
    blt $t0, 25, else25
        la  $a0, swim
        j   endif25
else25:
        la  $a0, cycle
endif25:
    li  $v0, 4   # print string call code
    syscall

Note that the assembly "branch around" is the opposite of the high-level condition. Also note the jump instruction needed before ELSE.

Loops: repetition

If a jump (or branch) reloads the PC with a lower address, that instruction will be reached again, and again... A loop results, as the same block of instructions is repeated. One must be careful to avoid an infinite loop by providing a branch out of the repetitive region that will eventually be taken. Two well-known and well-behaved constructs are WHILE and FOR. FOR is actually a special case of WHILE that uses a counter. Both are pre-test loops, the test (branch instruction) comes at the beginning of the loop body, and there is a jump instruction at the end.

{sum non-negative numbers}
sum := 0
num := 0
WHILE num >= 0 DO
   sum := sum + num
   read (num)
ENDWHILE
{write 10 lines}
FOR countdown := 10 downto 1 DO
   print ("Hello again...")
ENDFOR
#   add    $t0, $0, $0 really:
    move   $t0, $0   #sum=0
    move   $v0, $0   #num=0
while5:
    bltz   $v0, endwhile5
        add  $t0, $v0
#       ---- $v0 switches role here
        li   $v0, 5  #read int call
        syscall
        j  while5
enendwhile5:
# set up print arguments before loop
    la  $a0, hello_again
    li  $v0, 4    #print string call
    li  $t0, 10   # countdown
for10:
    beqz  $t0, endfor10
        syscall   #print another line
        sub $t0, 1    #decr. countdown
        j  for10
endfor10:

A REPEAT loop is a post-test loop. It may be used in special situations when it is known that the loop body should be executed at least once.

Embarrasing historical note: The first version of FORTRAN implmented FOR loops as post-test loops. As a result, they always executed once even if it made no sense. It took 20 years to correct the situation.


Prepared by Lin Jensen, Bishop's University, 21 January 1999

Previous page Back    Next Next page         Contents