6. Branching and Loops

1. Introduction to branching

Regular instructions in an assembly code are executed from top to bottom. Branching instructions provide a way to change the order of the execution. With appropriate branch instructions we can create conditional branches equivalent to if statements in high-level languages. We can also create loops and functions.

2. Labels

We need to put labels in the code before we can use the branching instructions. Labels are single words that end with the symbol :. The labels should be placed in separate lines in the code.

3. Unconditional branching instruction B

The instruction B requires one argument that must be a name of a label. The label must appear somewhere else in the code. The instruction will cause the program to immediately go to the specified label. Let us consider the following example.

          MOV     X1,     15
          MOV     X2,     20
          B       label001
          MOV     X1,     25
label001:
          MOV     X2,     30

The contents of X1 and X2 will be 15 and 30. The command MOV X1, 25 is not executed.

4. Conditional branching instructions

Conditional branching is achieved by two instructions. The first is the comparison instruction, whose execution sets values in comparison flags. The second instruction reads the flags and decides whether to do the branching or to continue executing the code without branching.

4.1. Comparison instruction CMP

The instruction has two registers as the arguments. If we give the instruction

CMP     X5,     X6

the computer will evaluate the difference X5-X6. However, instead of storing the difference in one of the registers, the CPU will update the conditional flags. There are more than 10 conditional flags. We will focus on the 10 most important ones.

  • EQ (equality). If X5-X6 is 0, then the value of EQ will be 1. Otherwise, if X5-X6 is not 0, then the value of EQ will be 0.
  • NE (not-equal). The flag NE is the opposite of EQ. If the result of X5-X6 is not 0, then the value of NE will be 1. Otherwise, if X5-X6 is 0, then the value of NE will be 0.
  • GT (greater than - signed version). If X5-X6 is bigger than 0, then the value of GT will be 1. If X5-X6 is smaller than or equal to 0, then the value of GT will be 0. The numbers are treated as signed integers.
  • LT (less than - signed version). If X5-X6 is smaller than 0, then the value of LT will be 1. If X5-X6 is greater than or equal to 0, then the value of LT will be 0.
  • GE (greater than or equal to - signed version). If X5-X6 is greater than or equal to 0, then the value of GE will be 1. If X5-X6 is smaller than 0, then the value of GE will be 0.
  • LE (less than or equal to - signed version). If X5-X6 is less than or equal to 0, then the value of LE will be 1. If X5-X6 is greater than 0, then the value of LE will be 0.
  • HI (greater than - unsigned version). If X5-X6 is bigger than 0, then the value of HI will be 1. If X5-X6 is smaller than or equal to 0, then the value of HI will be 0. The numbers are treated as unsigned integers.
  • LO (less than - unsigned version). If X5-X6 is smaller than 0, then the value of LO will be 1. If X5-X6 is greater than or equal to 0, then the value of LO will be 0.
  • HS (greater than or equal to - unsigned version). If X5-X6 is greater than or equal to 0, then the value of HS will be 1. If X5-X6 is smaller than 0, then the value of HS will be 0.
  • LS (less than or equal to - unsigned version). If X5-X6 is less than or equal to 0, then the value of LS will be 1. If X5-X6 is greater than 0, then the value of LS will be 0.

4.2. Conditional branching B**

Each of the branching flags has its corresponding conditional branching instruction. These are the corresponding branching instructions: BEQ, BNE, BGT, BLT, BGE, BLE, BHI, BLO, BHS, BLS.

4.3. Example

We will compare the values of the registers X5 and X6. Then we will put 5 in the register X0 if the content of X5 is bigger than the content of X6. If the content of X6 is bigger than or equal to the content of X5, then we will put the value 6 in the register X0.

There are multiple ways to solve this problem. Our first solution will be longer, but more intuitive. The second solution will be shorter and it will use a common technique to reduce the number of jumps.

4.3.1. First solution

We will create two blocks of code. One of them will treat the case X5>X6. The other block will treat the case X5<=X6. The first block of code will start with the label X5BiggerThanX6: and end with the unconditional jump to the label afterComparison. The second block will start with the label X6BiggerOrEqual: and terminate with another unconditional jump to afterComparison. We do not want our program to enter these two blocks of code, unless it the conditional branching requests so. Therefore, before the two blocks of code, we will have an unconditional branch to the label comparison. This label appears immediately after our two sub-routines.

                B     comparison               /* unconditional jump                    */
X5BiggerThanX6:                                /* we should enter here only if X5 > X6  */
                MOV     X0,     5
                B        afterComparison       
X6BiggerOrEqual:                               /* we should enter here only if X5 <= X6 */ 
                MOV     X0,     6
                B        afterComparison
comparison:
                CMP     X5,     X6
                BGT     X5BiggerThanX6
                B       X6BiggerOrEqual
afterComparison:

4.3.2. Second solution

We will first put the value 5 in the register X0. The number 5 is chosen to be the default value. Then, we will do the comparison of X5 and X6. If X5 is bigger than X6, then we will jump to the end of our code. This jump will cause us to skip the instruction that places the number 6 in the register X0. If the comparison result is false, then we will not jump. We will execute the instruction that puts 6 into X0.

                MOV     X0,     5
                CMP     X5,     X6
                BGT     endOfComparison
                MOV     X0,     6
endOfComparison:

5. Branching problems: practice with code auto-grader

Problem 1.

Create a code that places the number 5 in the register X1 if the value inside X5 is smaller than the value inside X6. If the value in X5 is greater than or equal to the value in X6, then place the number 6 in the register X1.

Code editor

Problem 2.

Create a code that places the number 5 in the register X1 if the value inside X5 is smaller than the value inside X6. If the value in X5 is larger than the value in X6, then place the number 6 in the register X1. If the contents of X5 and X6 are equal, then place 0 in the register X1.

Code editor

Problem 3.

You can assume that the integers \(a\), \(b\), \(c\), and \(d\) are stored in the registers X0, X1, X2, and X3, respectively. Create the code that stores either the value \(5a+b\) or the value \(a+5b\) in the register X5. If \(c> d\), then the register X5 should contain the value \(5a+b\). If \(c\leq d\), then the register X5 should contain the value \(a+5b\).

Code editor

6. Loops

In assembly languages, the loops do not exist in the same way as in the high level languages. The programmers have to make loops by using the branching instructions. The following practice problems illustrate how to implement loops.

Problem 4.

Assume that the register X0 contains the integer \(n\). Assume that the register X1 contains the address of the beginning of the block of memory that contains the sequence \(x_0\), \(x_1\), \(\dots\), \(x_{n-1}\) of integers. Create a code that multiplies by 2 every term of the sequence.

Code editor

Problem 5.

Assume that the register X0 contains the integer \(n\). Assume that the register X1 contains the address of the beginning of the block of memory that contains the sequence \(x_0\), \(x_1\), \(\dots\), \(x_{n-1}\) of integers. Create a code that finds the smallest index \(i\) for which \(x_i\) is greater than 100. The index \(i\) should be placed in the register X2. If all of the numbers \(x_0\), \(x_1\), \(\dots\), \(x_{n-1}\) are smaller than or equal to \(100\), then the number -1 should be placed in X2.

Code editor