RE-POST February: SPO600 Week 5 Part 1

This post would be about what I have learned during my fifth week of Software Portability and Optimization (SPO600) class.

Continuing off from the previous post, first access the server and then go to the following link to copy and paste the basic loop in AArch64 and x86 assembler: https://toronto.tylers.info/dokuwiki-toronto/doku.php?id=spo600:64-bit_assembly_language_lab (updated 2024-04-17, due to the previous wiki not working)

 .text

 .globl _start

 min = 0                          /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */

 max = 10                         /* loop exits when the index hits this number (loop condition is i<max) */

 _start:

     mov     x19, min

 loop:

     /* ... body of the loop ... do something useful here ... */

     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 */


Similarly, do the same for the x86 machine, however, using the following code instead:


    

 .text

 .globl    _start

 min = 0                         /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */

 max = 10                        /* loop exits when the index hits this number (loop condition is i<max) */

 _start:

     mov     $min,%r15           /* loop index */

 loop:

     /* ... body of the loop ... do something useful here ... */

     inc     %r15                /* increment index */

     cmp     $max,%r15           /* see if we're done */

     jne     loop                /* loop if we're not */

     mov     $0,%rdi             /* exit status */

     mov     $60,%rax            /* syscall sys_exit */

     syscall

Notice that in aarch64, the add line has 3 arguments while in x86 have a function called increment. In another programming language, it would look something like this:

min = min + 1; OR min++;

To run the file, make a Makefile first:

vi Makefile

add the following code:

loop:        loop.s

                as -g loop.s -o loop.o

                ld -g loop.o -o loop

The run the make command:

Then the executable can now be run: ./loop
Nothing would show up since there is nothing in the body. To display some data, we can copy and paste the hello .data part and change the display like so:


    

.data

msg:    .ascii      "Loop\n"

len=    . - msg

In addition, copy and paste the print message:

    
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 */

Then we can execute it:

    
make loop
./loop
Now to make it show the numbers beside the Loop:

    
 .text
 .globl _start
 min = 0                          /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
 max = 10                         /* loop exits when the index hits this number (loop condition is i<max) */
 _start:
     mov     x19, min
 loop:
     /* Convert loop counter to char*/
     add     x15, x19, 0x30     /* add 48 to convert to char */
     adr     x14, msg+6
     strb    w15, [x14]

     /* Print the message */
     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 */

     /* Continue the loop */
     add     x19, x19, 1
     cmp     x19, max
     b.ne    loop

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

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

Then, re-run the code with make loop command and ./loop:

It is also possible to just write the character '0' instead of 0x30.
Then, do the same for x86 machine.

    
 .text
 .globl    _start
 min = 0                         /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
 max = 10                        /* loop exits when the index hits this number (loop condition is i<max) */
 _start:
     mov     $min,%r15           /* loop index */
 loop:
     /* Convert loop counter to char */
     mov     %r15, %r14
     add     $'0', %r14
     mov     $msg+6, %r13
     mov     %r14b,(%r13)

     /* Print the message */
     movq    $len,%rdx                       /* message length */
     movq    $msg,%rsi                       /* message location */
     movq    $1,%rdi                         /* file descriptor stdout */
     movq    $1,%rax                         /* syscall sys_write */
     syscall

     /* Continue the loop */
     inc     %r15                /* increment index */
     cmp     $max,%r15           /* see if we're done */
     jne     loop                /* loop if we're not */

     /* Exit the program */
     mov     $0,%rdi             /* exit status */
     mov     $60,%rax            /* syscall sys_exit */
     syscall

.section .data

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

This result in a segmentation fault, which is a good change to try and use the debugger:
gdb loop


The issue was the missing $ sign on the msg line.


To make the code better:

    
 .text
 .globl    _start
 min = 0                         /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
 max = 10                        /* loop exits when the index hits this number (loop condition is i<max) */
 _start:
     mov     $min,%r15           /* loop index */
 loop:
     /* Convert loop counter to char */
     mov     %r15, %r14
     add     $'0', %r14
     mov     %r14b,msg+6

     /* Print the message */
     movq    $len,%rdx                       /* message length */
     movq    $msg,%rsi                       /* message location */
     movq    $1,%rdi                         /* file descriptor stdout */
     movq    $1,%rax                         /* syscall sys_write */
     syscall

     /* Continue the loop */
     inc     %r15                /* increment index */
     cmp     $max,%r15           /* see if we're done */
     jne     loop                /* loop if we're not */

     /* Exit the program */
     mov     $0,%rdi             /* exit status */
     mov     $60,%rax            /* syscall sys_exit */
     syscall

.section .data

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

Comments

Popular posts from this blog