SPO600-Lab5 64-bit Assembler Lab: Aarch64 VS.  X84_64
Tags: assembler, spo600, x8664, aarch64
Published: 2021-12-14 23:10:59

## Instruction
This lab is to experiment with assembler on the x86_64 and aarch64 platforms. 

Particularly, example scripts were provided in the [server](https://wiki.cdot.senecacollege.ca/wiki/SPO600_Servers). First we need to extract the content to a different folder with command:

```
tar -xvzf spo600-assembler-lab-examples.tgz -C ~/
```
 
The code examples were shown as below:
![Code Examples](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jnub2qkg7cvw37mprmjo.png)

Tasks:
- Review assembly language programs using `objdump -d objectfile`, compared to source code, X86_64 VS. Aarch64.
- Write loop with digit in assembly language X86_64 VS. Aarch64. 

## Aarch64

### objdump

Overall, the `objdump` command is used to inspect compiled binaries. Thus, first using `gcc` to compile `hello.c` code to `hello`, then using `objdump` to inspect, taking the `main` section as the example:
![Aarch64 hello.c main](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vyobsms1f1rct030xcce.png)

### loop

The next part was to write and run loops with assembly language. For example, if you have a assembly language file `helloWorld.s`, then you have to use command `as -g -o helloWorld.o helloWorld.s` to compile it. And then you have to take the `helloWorld.o` file and link it using this command `ld -o helloWorld helloWorld.o` and then you can actually run the program using this command `./helloWorld`.

The following code can give us a sequence of 'Loop: ' in the terminal
```
.text
.globl _start

min = 0                          /* starting value for the loop index; note that this is a symbol (constant) */
max = 11                         /* loop exits when the index hits this number (loop condition is i<max) */
ten = 10
_start:

       	mov     x19, min
        mov     x17, ten
        mov     x0, 0           /* status -> 0 */

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

        mov     x18, x19        /*mov x19 into x18 */
        udiv    x9, x18, x17
        add     x13, x9, 0x30   
        msub    x10, x9, x17, x18 /*get remainder*/
        add     x14, x10, 0x30  
        adr     x15, msg        
        strb    w13, [x15, 8]   

        strb    w14, [x15, 9]  
        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x19, x19, 1
        cmp     x19, max
        b.ne    loop

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


## X86_64

### objdump

Similarly, the main section:

![X86_64 hello.c main](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qupvpp1zgskdxa76iwy2.png)

As shown above, the compiled code in Aarch64 and X86_64 are very different.

### loop

The similar program to produce a list of 'Loops: ' in X86_64 was shown as below:

```
.text
.globl  _start

_start:
        movq    $min, %r10      /*store the min vlaue into r10 as a loop index*/
        movq    $division, %r9   /*store the division value(10) into r9*/

loop:
        cmp     %r9, %r10      /*compare r10(loop index) with 10*/
        jl      digit_1          /*if r10 is less than 10, go to the subroutine digit_1*/
        jmp     digit_2          /*if r10 is greater or equal to 10, go to the subroutine digit_2*/


digit_1:
        movq    %r10, %r15      /*store the r10 value into r15*/
        add     $'0', %r15       /*add '0' to r15 so the value will be ascii number character value*/

        movq    $msg+15, %r11   /*the digit location within string*/
        movb    %r15b, (%r11)   /*store the digit at the location*/

        jmp     print           /*go to the subroutine print*/

digit_2:
        movq    $0, %rdx         /*initialize rdx to 0 for division*/
        movq    %r10, %rax     /*store the r10 value into rax for division*/
        div     %r9              /*divide rax value by 10(r9)*/

        movq    %rax, %r14    /*store the rax value(quotient) into r14*/
        movq    %rdx, %r15    /*store the rdx value(remainder) int r15*/

        add     $'0', %r14       /*add '0' to r14 so the value will be ascii number character value*/
        add     $'0', %r15       /*add '0' to r15 so the value will be ascii number character value*/

        movq    $msg+14, %r11   /*the digit location within string*/
        movb    %r14b, (%r11)   /*store the digit at the location*/

        movq    $msg+15, %r12   /*the digit loctaion within string*/
        movb    %r15b, (%r12)   /*store the digit at the location*/

        jmp     print   /*go to the subroutine print*/


print:
        movq    $len,%rdx                       /* message length */
        movq    $msg,%rsi                       /* message location */


        movq    $1,%rdi                         /* file descriptor stdout */
        movq    $1,%rax                         /* syscall sys_write */
        syscall
        inc             %r12b

        inc             %r10      /*increment loop index*/
        cmp             $max, %r10  /*compare the max with r10*/
        jne             loop      /*if the max value and the r10(loop index) value is not equal,*/
                                  /*   redo the loop subroutine*/

        movq    $0,%rdi                         /* exit status */
        movq    $60,%rax                        /* syscall sys_exit */
        syscall


.section .data
msg:    .ascii      "Loop:   \n"
        len = . - msg
min = 0
max = 10
division = 10
``` 

## Conclusion

It is relatively straight-forward to get the loop to print a list of 'Loop: ', but it is very difficult to figure out how to make the loop to print 'Loop: 0', 'Loop: 1', ..., 'Loop: 9', 'Loop: 10'. The challenging parts include to show the digit and to show only the second digit but not to show as 'Loop: 00', 'Loop: 01' ... 'Loop: 09'.