SPO600 Lab5 64-Bit Assembly Language Lab Pt.2 ---x86_64 part

In the part 2 of this Lab , I am going to experiment with assembler on the x86_64 platforms, similar to the Lab part 1.

Task 1 Observe the difference between source code and the object file of the x86 assembly language 

Source code (gas / AT&T ):

Source code (nasm / Intel):


object file (gas): 

Task 2 -- modify a loop code in the x86 system to print loop for 6 times.


Before that, I want to modifty the Makefile so that it can make file for the loop-gas.s
Revised Makefile:

code:
 BINARIES=hello-nasm hello-gas loop-gas

all:    ${BINARIES}
AS_ARGS=-g

hello-nasm:     hello-nasm.s
                nasm    -g      -o hello-nasm.o -f elf64        hello-nasm.s
                ld              -o hello-nasm                   hello-nasm.o

hello-gas:      hello-gas.s
                as      ${AS_ARGS}      -o hello-gas.o          hello-gas.s
                ld                      -o hello-gas            hello-gas.o

loop-gas:       loop-gas.s
                as      ${AS_ARGS}      -o loop-gas.o           loop-gas.s
                ld                      -o loop-gas             loop-gas.o


clean:
                rm ${BINARIES} *.o || true
Modified Code of loop-gas.s:
 /*
   This is a 'hello world' program in x86_64 assembler using the
   GNU assembler (gas) syntax. Note that this program runs in 64-bit
   mode.

   CTyler, Seneca College, 2014-01-20
   Licensed under GNU GPL v2+
*/

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


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

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

        inc     %r15                /* increment the loop index */
        cmp     $max,%r15           /* see if we've hit the max */
        jne     loop                /* if not, then continue the loop */


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

.section .data

msg:    .ascii      "loop\n"
output:


Task 3: Modify the code so that the output show the iteration number also.

Modified Code:
 /*
   This is a 'hello world' program in x86_64 assembler using the
   GNU assembler (gas) syntax. Note that this program runs in 64-bit
   mode.

   CTyler, Seneca College, 2014-01-20
   Licensed under GNU GPL v2+
*/

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


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

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

        /*update the iteration number to be displayed*/
        mov     %r15, %r10
        add     $'0', %r10
        mov     %r10b, num


        /* print iteration number*/
        movq    $len2,%rdx
        movq    $num,%rsi
        movq    $1,%rdi
        movq    $1,%rax
        syscall

        inc     %r15                /* increment the loop index */


        cmp     $max,%r15           /* see if we've hit the max */
        jne     loop                /* if not, then continue the loop */


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

.section .data

msg:    .ascii      "loop: "
        len = . - msg

num:    .byte '0'
        .byte 10
        len2 = . - num

Output:

Task 4: Extend the code to loop from 00 to 32


In part of AArch64, I used the method just to set up a ten digits and units digit. This time, I would like
to use another method. I will calculate the loop number from the iteration count directly.

Modified code:

 /*
   This is a 'hello world' program in x86_64 assembler using the
   GNU assembler (gas) syntax. Note that this program runs in 64-bit
   mode.

   CTyler, Seneca College, 2014-01-20
   Licensed under GNU GPL v2+
*/

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


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

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

        /*div the iteration number*/
        mov     %r15, %rax      /* the value to be divided must be moved to %rax*/
        xor     %rdx, %rdx
        mov     $10, %r10
        div     %r10            /* after division, quotient will be in rax and remainder will be in rdx*/

        /*update the iteration number to be displayed*/
        mov     %rax, %r10
        add     $'0', %r10
        mov     %r10b, num

        mov     %rdx, %r11
        add     $'0', %r11
        mov     %r11b, num+1

        /* print iteration number*/
        movq    $len2,%rdx
        movq    $num,%rsi
        movq    $1,%rdi
        movq    $1,%rax
        syscall

        inc     %r15                /* increment the loop index */


        cmp     $max,%r15           /* see if we've hit the max */
        jne     loop                /* if not, then continue the loop */


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

.section .data

msg:    .ascii      "loop: "
        len = . - msg

num:    .ascii  "00\n"
        len2 = . - num

Yellow highlighted code: divide the iteration counter by 10 and get the units digit and tens digit.
Red highlighted code: update the display value.

Output:


Task 5. Modify the code so that it suppress the leading zero


Modified code:

 /*
   This is a 'hello world' program in x86_64 assembler using the
   GNU assembler (gas) syntax. Note that this program runs in 64-bit
   mode.

   CTyler, Seneca College, 2014-01-20
   Licensed under GNU GPL v2+
*/

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


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

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

        /*div the iteration number*/
        mov     %r15, %rax      /* the value to be divided must be moved to %rax*/
        xor     %rdx, %rdx
        mov     $10, %r10
        div     %r10            /* after division, quotient will be in rax and remainder will be in rdx*/

        /*update the iteration number to be displayed*/
        cmp     $0, %rax
        je space

        mov     %rax, %r10
        add     $'0', %r10
        jmp update
space:  mov     $' ', %r10

update: mov     %r10b, num

        mov     %rdx, %r11
        add     $'0', %r11
        mov     %r11b, num+1

        /* print iteration number*/
        movq    $len2,%rdx
        movq    $num,%rsi
        movq    $1,%rdi
        movq    $1,%rax
        syscall

        inc     %r15                /* increment the loop index */


        cmp     $max,%r15           /* see if we've hit the max */
        jne     loop                /* if not, then continue the loop */


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

.section .data

msg:    .ascii      "loop: "
        len = . - msg

num:    .ascii  "00\n"
        len2 = . - num
Yellow highlighted code: check if the quotient is zero, if yes, replace the first digit to be displayed by space. 

output:

Task 6. Modify the code so that it show the counter as hexadecimal

Modified code:


/*
   This is a 'hello world' program in x86_64 assembler using the
   GNU assembler (gas) syntax. Note that this program runs in 64-bit
   mode.

   CTyler, Seneca College, 2014-01-20
   Licensed under GNU GPL v2+
*/

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


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

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

        /*div the iteration number*/
        mov     %r15, %rax      /* the value to be divided must be moved to %rax*/
        xor     %rdx, %rdx
        mov     $16, %r10
        div     %r10            /* after division, quotient will be in rax and remainder will be in rdx*/

        /*update the iteration number to be displayed*/
        cmp     $0, %rax
        je space

        mov     %rax, %r10
        add     $'0', %r10
        jmp check
space:  mov     $' ', %r10

//check if the unit digits greater than 9
check:  cmp     $9, %rdx
        jg add
        jmp update
add:    add     $7, %rdx

update: mov     %r10b, num

        mov     %rdx, %r11
        add     $'0', %r11
        mov     %r11b, num+1


        /* print iteration number*/
        movq    $len2,%rdx
        movq    $num,%rsi
        movq    $1,%rdi
        movq    $1,%rax
        syscall

        inc     %r15                /* increment the loop index */


        cmp     $max,%r15           /* see if we've hit the max */
        jne     loop                /* if not, then continue the loop */


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

.section .data

msg:    .ascii      "loop: "
        len = . - msg

num:    .ascii  "00\n"
        len2 = . - num
Yellow highlighted code: check if the remainder is greater than 9. if yes, add 7 so that the value after 9 is A.

output:

Reflection:

In this lab, I experienced on writing and debugging in assembler. Since the program is quit simple, I did not face too many difficulties. I have different experience on 6502, x86_64 and aarch64 assembler. 6502 is the one with the most limited resources. With only x, y and accumulator register and only 16 bit for each register, we are forced to keep reading variable from the memory even performing very simple task. Since I learn 6502 in a simulator, I can easily check the machine code, status of the processor or even use the step-by-step debugger, I have more confident to coding with 6502 assembler. 
As for the x86 and AArch64, their program structure are quite similar. Gratefully, both of them have more register available to use. Although the instructions of each system are not exactly the same, that of both system are quite well-rounded. More useful instruction are provided. for example the div instruction in x86 gas syntax. Without that, we may have to iterate the number deduction by 10 until it is smaller than 10. 
Finally, Coding in assembly language really take a lot of time and exhausting. It's hard to imagine I spend multiple hours just to write a few for-loop. It is 3am now. I need some sleep.



Comments

Popular posts from this blog

SPO600 Project Stage 1 (Pt.1) - Create a GCC Pass

SPO600 Project Stage 2 (Pt.1) - GCC pass locating clone function

SPO600 Project Stage 3 - Identify clones of multiple functions and compare them