Page 151 - ARM 64 Bit Assembly Language
P. 151
Structured programming 137
Listing 5.29 Automatic variables in AArch64 assembly.
1 .type doit, %function
2 .global doit
3 doit:
4 sub sp, sp, #80 // int x[20];
5 mov w2, #0 // w2 is i
6 loop:
7 cmp w2, #20 // pre-test loop
8 bge done // if (i >= 20) goto done
9 str w2, [sp, x2, lsl #2] // x[i] = i;
10 add w2, w2, #1 // i++
11 b loop // go back to loop test
12 done:
13 mov w0, w2 // return i
14 add sp, sp, #80 // destroy automatic variable
15 ret // return from function
16 .size doit,(. - doit)
14 the storage is released by restoring the stack pointer to its original contents. It is critical
that the stack pointer be restored, no matter how the function returns. Otherwise, the pro-
gram will mysteriously fail at some point when it attempts to use data from the stack. For this
reason, each function should have exactly one block of instructions for returning. If the func-
tion needs to return from some location other than the end, then it should branch to the return
block rather than returning directly in the middle of the function.
5.4.8 Recursive functions
A function that calls itself is said to be recursive. Certain problems are easy to implement
recursively, but are more difficult to solve iteratively. A problem exhibits recursive behavior
when it can be defined by two properties:
1. a simple base case (or cases), and
2. a set of rules that reduce all other cases toward the base case.
For example, we can define person’s ancestors recursively as follows:
1. one’s parents are one’s ancestors (base case),
2. the ancestors of one’s ancestors are also one’s ancestors (recursion step).
Recursion is a very powerful concept in programming. Many functions are naturally recur-
sive, and can be expressed very concisely in a recursive way. Numerous mathematical axioms