AArch64 Assembly Language Part II
Tags: assembly, assemblylanguage, aarch64
Published: 2022-03-21 20:08:04

This is the second post in a series on writing assembly language code for a program on the AArch64 architecture. You can find the first [here](https://dev.to/gusmccallum/aarch64-assembly-language-part-i-13a9).

Once again the task for this last stretch of our AArch64 exploration is to write a loop that iterates 30 times, which necessitates dealing with 2 digit numbers. This can be done by dividing the index by 10. The result goes into the first digit, with a branch to the secondDigit procedure if the first digit is 0. The full code is as follows:

```
.text
.globl _start

min = 0                          /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 31                         /* loop exits when the index hits this number (loop condition is i<max) */

_start:

    mov     x19, min
    mov     x20, 0x0A

loop:

    udiv    x21, x19, x20
    cmp     x21, 0
    b.eq    secondDigit

    add     x18, x21, '0'
    adr     x17, msg+6 
    strb    w18, [x17] 

secondDigit:
    msub    x22, x20, x21, x19

    add     x18, x22, '0' 
    adr     x17, msg+7 
    strb    w18, [x17] 

    mov     x0, 1           /* file descriptor: 1 is stdout */
    adr     x1, msg         /* message location (memory address) */
    mov     x2, len         /* message length (bytes) */

    mov     x8, 64          /* write is syscall #64 */
    svc     0               /* invoke syscall */

// Proceed with loop
    add     x19, x19, 1   
    cmp     x19, max
    b.ne    loop

    mov     x0, 0           /* status -> 0 */
    mov     x8, 93          /* exit is syscall #93 */
    svc     0               /* invoke syscall */

.data
msg:    .ascii      "Loop:  #\n"
len=    . - msg
```

With the following output:
```
Loop: #0
Loop: #1
Loop: #2
Loop: #3
Loop: #4
Loop: #5
Loop: #6
Loop: #7
Loop: #8
Loop: #9
Loop: #10
Loop: #11
Loop: #12
Loop: #13
Loop: #14
Loop: #15
Loop: #16
Loop: #17
Loop: #18
Loop: #19
Loop: #20
Loop: #21
Loop: #22
Loop: #23
Loop: #24
Loop: #25
Loop: #26
Loop: #27
Loop: #28
Loop: #29
Loop: #30
```

This looks like the output we're looking for which is great, let me break down the program in a little more detail and summarize my experiences writing AArch64 assembly.

```
_start:

    mov     x19, min
    mov     x20, 0x0A
```

We start the program by assigning 0 and 10 to registers 19 and 20, respectively. Both are being used as 64 bit widths as made evident by the `x` prefix.

```
loop:

    udiv    x21, x19, x20
    cmp     x21, 0
    b.eq    secondDigit
```

This portion divides the values in `x19` by `x20` and places it in `x21`. The syntax for AArch64 assembly is such that you can look at operations as `operand = value` or `operand = expression` in this case, as the destination register comes first in this syntax. 

The second line compares the first digit of the result with 0, branching to the secondDigit label if the expression evaluates true. That would be in the case that it's a single digit result, which it will be for the first 10 iterations. 

```
    add     x18, x21, '0'
    adr     x17, msg+6 
    strb    w18, [x17] 
```

The first line adds '0' to the value in `x21` and places it in `x18`, after which the address of the pound sign in `msg` is read into x17. The final line stores a byte from `w18` to the address pointed to by `x17`, the pound sign pointer we just created. 

```
secondDigit:
    msub    x22, x20, x21, x19
```

Finally, the secondDigit label gets the remainder with the msub instruction by setting `x22` to the result of `x20`-(`x21` * `x19`), or 10 - (result of the division) * (loop index).

The rest of the code is largely unchanged from the last few iterations of this program so I'll leave it at that.

This was a challenging program to write, although I thought the transition from 6502 assembly to 64 bit assembly would be harder. I'm sure my next step, writing the x86_64 equivalent, will be equally if not not more difficult. There's definitely a more robust feeling for lack of a better word, to writing and building assembly on a machine rather than an emulator, and during my debugging process it seemed like the error messages were more meaningful as well. Although I'm not very familiar with working with Linux and that made some things awkward I like knowing that if I need to dig deeper to find out why something's not working that's an option I have. That's it for this post, stay tuned for the x86_64 equivalent of this program coming soon.