DEV Community

Qiwen Yu
Qiwen Yu

Posted on

SPO600-Lab5 64-bit Assembler Lab: Aarch64 VS. X84_64

Instruction

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

Particularly, example scripts were provided in the server. First we need to extract the content to a different folder with command:

tar -xvzf spo600-assembler-lab-examples.tgz -C ~/
Enter fullscreen mode Exit fullscreen mode

The code examples were shown as below:
Code Examples

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

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
Enter fullscreen mode Exit fullscreen mode

X86_64

objdump

Similarly, the main section:

X86_64 hello.c main

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
Enter fullscreen mode Exit fullscreen mode

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'.

Oldest comments (0)