| 1. | ARM 64-bit Assembly |
| 2. | Simplest programs |
| 3. | Integers |
| 4. | Main memory |
| 5. | Arrays |
| 6. | Branching and loops |
| 7. | Functions |
| 8. | Floating point |
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). IfX5-X6is 0, then the value ofEQwill be 1. Otherwise, ifX5-X6is not 0, then the value ofEQwill be 0.NE(not-equal). The flagNEis the opposite ofEQ. If the result ofX5-X6is not 0, then the value ofNEwill be 1. Otherwise, ifX5-X6is 0, then the value ofNEwill be 0.GT(greater than - signed version). IfX5-X6is bigger than 0, then the value ofGTwill be 1. IfX5-X6is smaller than or equal to 0, then the value ofGTwill be 0. The numbers are treated as signed integers.LT(less than - signed version). IfX5-X6is smaller than 0, then the value ofLTwill be 1. IfX5-X6is greater than or equal to 0, then the value ofLTwill be 0.GE(greater than or equal to - signed version). IfX5-X6is greater than or equal to 0, then the value ofGEwill be 1. IfX5-X6is smaller than 0, then the value ofGEwill be 0.LE(less than or equal to - signed version). IfX5-X6is less than or equal to 0, then the value ofLEwill be 1. IfX5-X6is greater than 0, then the value ofLEwill be 0.HI(greater than - unsigned version). IfX5-X6is bigger than 0, then the value ofHIwill be 1. IfX5-X6is smaller than or equal to 0, then the value ofHIwill be 0. The numbers are treated as unsigned integers.LO(less than - unsigned version). IfX5-X6is smaller than 0, then the value ofLOwill be 1. IfX5-X6is greater than or equal to 0, then the value ofLOwill be 0.HS(greater than or equal to - unsigned version). IfX5-X6is greater than or equal to 0, then the value ofHSwill be 1. IfX5-X6is smaller than 0, then the value ofHSwill be 0.LS(less than or equal to - unsigned version). IfX5-X6is less than or equal to 0, then the value ofLSwill be 1. IfX5-X6is greater than 0, then the value ofLSwill 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
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.
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.
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\).
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.
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.
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.