LAB5

 INTRODUCTION

This lab is about exploring assembly language on x86_64 and AArch64 architectures. We will start by running "Hello World" programs written in C and assembly, then use tools like objdump and gcc -S to examine machine code and compiler-generated assembly. The main task is to modify an AArch64 assembly loop to print numbers, first from 0 to 5, then extending it to 00-32 with two-digit formatting, and finally converting it to hexadecimal. After that, we will repeat similar steps for x86_64 assembly. The goal is to understand how low-level programming works, compare different architectures, and gain experience with assembly instructions, system calls, and debugging.

Extracting the Archive

First, we need to unpack the tar archive on x86_64 and AArch64 using the command:tar xvf /public/spo600-assembler-lab-examples.tgz


(AArch64)
(x86_64)

Building and Running the C Program on x86_64 and AArch64

Building and running the C program using make command.

Disassembling Machine Code for Different Architectures

Then we use the objdump -d hello | less command to disassemble the compiled binaries and inspect their machine code(<main> section).
(AArch64)

(x86_64)

And Compare the disassembled output from previous step with the assembly language output of the C compiler, produced by running gcc with the -S option.
Compile the C program into assembly language using gcc -S hello.c command:
(AArch64)
(x86_64)


The main difference is that objdump -d shows the final binary, including everything needed to run the program, such as system calls, optimizations, and setup. On the other hand, the output from gcc -S is just the assembly code generated directly from source code.

Modify an AArch64 assembly loop

Provided Code:

 .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     x19, min
 loop:

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

     add     x19, x19, 1     /* increment the loop counter */
     cmp     x19, max        /* see if we've hit the max */
     b.ne    loop            /* if not, then continue the loop */
     
     mov     x0, 0           /* set exit status to 0 */
     mov     x8, 93          /* exit is syscall #93 */
     svc     0               /* invoke syscall */

Step 1: Modify the code above to print "loop" 6 times:
Modified code:
    .text
    .globl _start
    min = 0                          /* starting value for the loop index; **note that this is a symbol (constant)**, not>    
    max = 6                          /* loop exits when the index hits this number (loop condition is i<max) */

    _start:
        mov     x19, min

    loop:
        mov     x0, 1              /* File descriptor 1 is stdout */
        adr     x1, loop_msg       /* Load the address of the string "loop" */
        mov     x2, 5              /* Length of the string "loop" */
        mov     x8, 64             /* syscall number for write */
        svc     0                  /* invoke syscall to print the string */

        add     x19, x19, 1        /* increment the loop counter */
        cmp     x19, max           /* see if we've hit the max */
        b.ne    loop               /* if not, then continue the loop */

        mov     x0, 0              /* set exit status to 0 */
        mov     x8, 93             /* exit is syscall #93 */
        svc     0                  /* invoke syscall */

.data
loop_msg:
    .asciz "Loop\n"              /* String */


Output:



Step 2: Modify the message with the loop index values:
Modified code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 6                          /* loop exits when the index hits this number */

_start:
        mov     x19, min            /* initialize loop counter */

    loop:
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, loop_msg        /* Load the address of the string "Loop: " */
        mov     x2, 6               /* Length of the string "Loop: " */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        mov     w20, w19            /* Move the loop index to w20 */
        add     w20, w20, 48        /* Convert integer to ASCII by adding '0' */
        
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, int_str         /* Address of the string "0 \n" */
        mov     x2, 4               /* Length of the string (since it's "0 \n", length is 4) */
        mov     x8, 64              /* syscall number for write */
        
        strb    w20, [x1]           /* Store the ASCII character in the string */
        svc     0                   /* invoke syscall to print the string */

        add     x19, x19, 1         /* increment the loop counter */
        cmp     x19, max            /* see if we've hit the max */
        b.ne    loop                /* if not, then continue the loop */

        mov     x0, 0               /* set exit status to 0 */
        mov     x8, 93              /* exit is syscall #93 */
        svc     0                   /* invoke syscall */

.data
loop_msg:
    .asciz "Loop: "                /* String */

int_str:
    .ascii "0 \n"                  /* String "0 \n" that will be printed for each loop iteration */

Output:


Step 3:Extend the AArch64 code to loop from 00-32, printing each value as a 2-digit decimal number.
Modified code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 32                         /* loop exits when the index hits 32 */

_start:
        mov     x19, min            /* initialize loop counter */

    loop:
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, loop_msg        /* Load the address of the string "Loop: " */
        mov     x2, 6               /* Length of the string "Loop: " */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        /* Divide the index by 10 to get the tens place */
        mov     w20, w19            /* Copy loop counter to w20 */
        mov     w24, 10             /* Load the value 10 into w24 */
        sdiv    w21, w20, w24       /* Divide by 10: w21 gets the tens place */
        mov     w22, w19            /* Copy loop counter again to w22 */
        mul     w23, w21, w24       /* Multiply quotient by 10 to get the base for subtraction */
        sub     w23, w22, w23       /* Subtract the product from the original number to get the ones place */

        /* Convert tens place to ASCII */
        add     w21, w21, '0'       /* Convert to ASCII by adding '0' */
        adr     x2, int_str         /* Address for tens place */
        strb    w21, [x2]           /* Store the tens digit */

        /* Convert ones place to ASCII */
        add     w23, w23, '0'       /* Convert to ASCII by adding '0' */
        adr     x2, int_str + 1     /* Address for ones place */
        strb    w23, [x2]           /* Store the ones digit */

        /* Print the result */
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, int_str         /* Address of the string with 2 digits */
        mov     x2, 3               /* Length of the string (2 digits + newline) */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        add     x19, x19, 1         /* increment the loop counter */
        cmp     x19, max            /* see if we've hit the max */
        b.le    loop                /* if not, then continue the loop */

        mov     x0, 0               /* set exit status to 0 */
        mov     x8, 93              /* exit is syscall #93 */
        svc     0                   /* invoke syscall */

    .data
loop_msg:
    .asciz "Loop: "                /* String */

int_str:
    .ascii "00\n"                  /* Space for storing the 2-digit string */

Output:


Step 4: Remove the leading 0
Modified Code:
.text
.globl _start

min = 1                          /* starting value for the loop index */
max = 32                         /* loop exits when the index hits 32 */

_start:
        mov     x19, min            /* initialize loop counter */

    loop:
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, loop_msg        /* Load the address of the string "Loop: " */
        mov     x2, 6               /* Length of the string "Loop: " */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        /* Check if the number is less than 10 */
        cmp     x19, 10             /* compare loop counter with 10 */
        b.lt    single_digit        /* if less than 10, handle as single digit */

        /* Handle double-digit numbers (>= 10) */
        mov     w20, w19            /* Copy loop counter to w20 */
        mov     w24, 10             /* Load the value 10 into w24 */
        sdiv    w21, w20, w24       /* Divide by 10: w21 gets the tens place */
        mul     w23, w21, w24       /* Multiply quotient by 10 to get the base for subtraction */
        sub     w23, w20, w23       /* Subtract the product from the original number to get the ones place */

        /* Convert tens place to ASCII */
        add     w21, w21, '0'       /* Convert to ASCII by adding '0' */
        adr     x2, int_str         /* Address for tens place */
        strb    w21, [x2]           /* Store the tens digit */

        /* Convert ones place to ASCII */
        add     w23, w23, '0'       /* Convert to ASCII by adding '0' */
        adr     x2, int_str + 1     /* Address for ones place */
        strb    w23, [x2]           /* Store the ones digit */

        /* Add newline character */
        mov     w25, '\n'           /* Load newline character */
        adr     x2, int_str + 2     /* Address for newline */
        strb    w25, [x2]           /* Store the newline character */

        /* Print the result */
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, int_str         /* Address of the string with 2 digits and newline */
        mov     x2, 3               /* Length of the string (2 digits + newline) */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        b       next_iteration      /* skip single-digit handling */

    single_digit:
        /* Handle single-digit numbers (< 10) */
        add     w20, w19, '0'       /* Convert the loop counter to ASCII by adding '0' */
        adr     x2, int_str         /* Address for the single-digit string */
        strb    w20, [x2]           /* Store the ASCII character */

        /* Add newline character */
        mov     w25, '\n'           /* Load newline character */
        adr     x2, int_str + 1     /* Address for newline */
        strb    w25, [x2]           /* Store the newline character */

        /* Print the result */
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, int_str         /* Address of the string with the single digit and newline */
        mov     x2, 2               /* Length of the string (1 digit + newline) */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

    next_iteration:
        add     x19, x19, 1         /* increment the loop counter */
        cmp     x19, max            /* see if we've hit the max */
        b.le    loop                /* if not, then continue the loop */

        mov     x0, 0               /* set exit status to 0 */
        mov     x8, 93              /* exit is syscall #93 */
        svc     0                   /* invoke syscall */

    .data
loop_msg:
    .asciz "Loop: "                /* String to print */

int_str:
    .ascii "  \n"                  /* Space for storing the 2-digit string and newline */
Output:



Step 5: Change output in hexadecimal (0-20) instead of decimal (0-32).

Modified Code:

.text
.globl _start

min = 1                          /* starting value for the loop index */
max = 0x20                       /* loop exits when the index hits 0x20 (32 in decimal) */

_start:
        mov     x19, min            /* initialize loop counter */

    loop:
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, loop_msg        /* Load the address of the string "Loop: " */
        mov     x2, 6               /* Length of the string "Loop: " */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

        /* Convert the loop counter to hexadecimal */
        mov     w20, w19            /* Copy loop counter to w20 */
        mov     w24, 16             /* Load the value 16 into w24 (base for hexadecimal) */
        udiv    w21, w20, w24       /* Divide by 16: w21 gets the high digit */
        msub    w23, w21, w24, w20  /* Get the low digit: w23 = w20 - (w21 * 16) */

        /* Convert high digit to ASCII */
        cmp     w21, 9              /* Compare high digit with 9 */
        b.le    high_digit_digit    /* If less than or equal to 9, handle as digit */
        add     w21, w21, 'A' - 10  /* Otherwise, convert to 'A'-'F' */
        b       store_high_digit

    high_digit_digit:
        add     w21, w21, '0'       /* Convert to ASCII by adding '0' */

    store_high_digit:
        adr     x2, hex_str         /* Address for high digit */
        strb    w21, [x2]           /* Store the high digit */

        /* Convert low digit to ASCII */
        cmp     w23, 9              /* Compare low digit with 9 */
        b.le    low_digit_digit     /* If less than or equal to 9, handle as digit */
        add     w23, w23, 'A' - 10  /* Otherwise, convert to 'A'-'F' */
        b       store_low_digit

    low_digit_digit:
        add     w23, w23, '0'       /* Convert to ASCII by adding '0' */

    store_low_digit:
        adr     x2, hex_str + 1     /* Address for low digit */
        strb    w23, [x2]           /* Store the low digit */

        /* Add newline character */
        mov     w25, '\n'           /* Load newline character */
        adr     x2, hex_str + 2     /* Address for newline */
        strb    w25, [x2]           /* Store the newline character */

        /* Print the result */
        mov     x0, 1               /* File descriptor 1 is stdout */
        adr     x1, hex_str         /* Address of the string with 2 hexadecimal digits and newline */
        mov     x2, 3               /* Length of the string (2 digits + newline) */
        mov     x8, 64              /* syscall number for write */
        svc     0                   /* invoke syscall to print the string */

    next_iteration:
        add     x19, x19, 1         /* increment the loop counter */
        cmp     x19, max            /* see if we've hit the max */
        b.le    loop                /* if not, then continue the loop */

        mov     x0, 0               /* set exit status to 0 */
        mov     x8, 93              /* exit is syscall #93 */
        svc     0                   /* invoke syscall */

 .data
loop_msg:
    .asciz "Loop: "                /* String to print */

hex_str:
    .ascii "  \n"                  /* Space for storing the 2-digit hexadecimal string and newline */

Output:



Modify an x86_64 assembly loop

Provided Code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
 .text
 .globl    _start
 min = 0                         /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
 max = 5                        /* 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 the loop index */
     cmp     $max,%r15           /* see if we've hit the max */
     jne     loop                /* if not, then continue the loop */
     
     mov     $0,%rdi             /* set exit status to 0 */
     mov     $60,%rax            /* exit is syscall #60  */
     syscall                     /* invoke syscall */

Step 1: Modify the code above to print "loop" 6 times:
Modified code:
.text
.globl _start
min = 0                          /* starting value for the loop index */
max = 6                          /* loop exits when the index hits this number (loop condition is i < max) */

_start:
    mov     $min, %r15           /* Initialize loop counter */

loop:
    /* Write the string "loop\n" */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     loop_msg(%rip), %rsi /* Load the address of the string "loop\n" */
    mov     $5, %rdx             /* Length of the string "loop\n" (5 bytes, including newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    syscall                      /* invoke syscall to print the string */

    inc     %r15                 /* Increment the loop counter */
    cmp     $max, %r15           /* Compare the loop counter to max */
    jne     loop                 /* If not equal, continue the loop */

    mov     $0, %rdi             /* Set exit status to 0 */
    mov     $60, %rax            /* syscall number for exit (60) */
    syscall                      /* invoke syscall */

.data
loop_msg:
    .asciz "loop\n"               /* The message string*/


Output:

Step 2: Modify the message with the loop index values:
Modified code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 6                          /* loop exits when the index hits this number (loop condition is i < max) */

_start:
    mov     $min, %r15           /* Initialize loop counter */

loop:
    /* Write the string "Loop: " */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     loop_msg(%rip), %rsi /* Load the address of the string "Loop: " */
    mov     $6, %rdx             /* Length of the string "Loop: " (6 bytes) */
    syscall                      /* invoke syscall to print the string */

    /* Convert the loop index to ASCII and store it in int_str */
    add     $48, %r15            /* Convert integer to ASCII by adding '0' (ASCII value of '0' is 48) */
    mov     %r15b, int_str       /* Store the ASCII value of the loop index in int_str */
    sub     $48, %r15            /* Restore the loop index to its original value */

    /* Write the int_str (loop index + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     int_str(%rip), %rsi  /* Load the address of int_str */
    mov     $3, %rdx             /* Length of the string (1 byte for the digit + 2 bytes for " \n") */
    syscall                      /* invoke syscall to print the string */

    inc     %r15                 /* Increment the loop counter */
    cmp     $max, %r15           /* Compare the loop counter to max */
    jne     loop                 /* If not equal, continue the loop */

    mov     $60, %rax            /* syscall number for exit (60) */
    xor     %rdi, %rdi           /* Set exit status to 0 */
    syscall                      /* invoke syscall */

.data
loop_msg:   .asciz "Loop: "     /* String to print before the loop index */
int_str:    .ascii "0 \n"       /* Space to store the loop index and newline */

Output:




Step 3:Extend the code to loop from 00-32, printing each value as a 2-digit decimal number.
Modified code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 33                         /* loop exits when the index hits this number (loop condition is i < max) */

_start:
    mov     $min, %r15           /* Initialize loop counter */

loop:
    /* Write the string "Loop: " */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     loop_msg(%rip), %rsi /* Load the address of the string "Loop: " */
    mov     $6, %rdx             /* Length of the string "Loop: " (6 bytes) */
    syscall                      /* invoke syscall to print the string */

    /* Convert the loop index to a 2-digit ASCII string */
    mov     %r15, %rax           /* Copy loop index to %rax */
    mov     $10, %rbx            /* Divisor for tens place */
    xor     %rdx, %rdx           /* Clear %rdx for division */
    div     %rbx                 /* Divide %rax by 10: quotient in %rax, remainder in %rdx */

    /* Convert tens digit to ASCII */
    add     $48, %al             /* Convert quotient (tens digit) to ASCII */
    mov     %al, int_str         /* Store tens digit in int_str */

    /* Convert ones digit to ASCII */
    add     $48, %dl             /* Convert remainder (ones digit) to ASCII */
    mov     %dl, int_str+1       /* Store ones digit in int_str+1 */

    /* Write the int_str (2-digit number + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     int_str(%rip), %rsi  /* Load the address of int_str */
    mov     $3, %rdx             /* Length of the string (2 bytes for digits + 1 byte for newline) */
    syscall                      /* invoke syscall to print the string */

    inc     %r15                 /* Increment the loop counter */
    cmp     $max, %r15           /* Compare the loop counter to max */
    jne     loop                 /* If not equal, continue the loop */

    mov     $60, %rax            /* syscall number for exit (60) */
    xor     %rdi, %rdi           /* Set exit status to 0 */
    syscall                      /* invoke syscall */

 .data
loop_msg:   .asciz "Loop: "     /* String to print before the loop index */
int_str:    .ascii "00\n"       /* Space to store the 2-digit number and newline */

Output:

Step 4: Remove the leading 0
Modified Code:
.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 33                         /* loop exits when the index hits this number (loop condition is i < max) */

_start:
    mov     $min, %r15           /* Initialize loop counter */

loop:
    /* Write the string "Loop: " */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     loop_msg(%rip), %rsi /* Load the address of the string "Loop: " */
    mov     $6, %rdx             /* Length of the string "Loop: " (6 bytes) */
    syscall                      /* invoke syscall to print the string */

    /* Check if the number is less than 10 */
    cmp     $10, %r15            /* Compare loop index with 10 */
    jl      single_digit         /* If less than 10, handle as single digit */

    /* Handle double-digit numbers (>= 10) */
    mov     %r15, %rax           /* Copy loop index to %rax */
    mov     $10, %rbx            /* Divisor for tens place */
    xor     %rdx, %rdx           /* Clear %rdx for division */
    div     %rbx                 /* Divide %rax by 10: quotient in %rax, remainder in %rdx */

    /* Convert tens digit to ASCII */
    add     $48, %al             /* Convert quotient (tens digit) to ASCII */
    mov     %al, int_str         /* Store tens digit in int_str */

    /* Convert ones digit to ASCII */
    add     $48, %dl             /* Convert remainder (ones digit) to ASCII */
    mov     %dl, int_str+1       /* Store ones digit in int_str+1 */

    /* Write the int_str (2-digit number + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     int_str(%rip), %rsi  /* Load the address of int_str */
    mov     $3, %rdx             /* Length of the string (2 bytes for digits + 1 byte for newline) */
    syscall                      /* invoke syscall to print the string */

    jmp     next_iteration       /* Skip single-digit handling */

single_digit:
    /* Handle single-digit numbers (< 10) */
    mov     %r15, %rax           /* Copy loop index to %rax */
    add     $48, %al             /* Convert loop index to ASCII by adding '0' */
    mov     %al, int_str+1       /* Store the ASCII character in int_str+1 (skip leading zero) */

    /* Write the int_str (single-digit number + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     int_str+1(%rip), %rsi /* Load the address of int_str+1 (skip leading space) */
    mov     $2, %rdx             /* Length of the string (1 byte for digit + 1 byte for newline) */
    syscall                      /* invoke syscall to print the string */

next_iteration:
    inc     %r15                 /* Increment the loop counter */
    cmp     $max, %r15           /* Compare the loop counter to max */
    jne     loop                 /* If not equal, continue the loop */

    mov     $60, %rax            /* syscall number for exit (60) */
    xor     %rdi, %rdi           /* Set exit status to 0 */
    syscall                      /* invoke syscall */

.data
loop_msg:   .asciz "Loop: "     /* String to print before the loop index */
int_str:    .ascii "  \n"       /* Space to store the number and newline (2 digits + newline) */

Output:

Step 5: Change output in hexadecimal (0-20) instead of decimal (0-32).

Modified Code:

.text
.globl _start

min = 0                          /* starting value for the loop index */
max = 0x21                       /* loop exits when the index hits 0x21 (33 in decimal) */

_start:
    mov     $min, %r15           /* Initialize loop counter */

loop:
    /* Write the string "Loop: " */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     loop_msg(%rip), %rsi /* Load the address of the string "Loop: " */
    mov     $6, %rdx             /* Length of the string "Loop: " (6 bytes) */
    syscall                      /* invoke syscall to print the string */

    /* Convert the loop index to hexadecimal */
    mov     %r15, %rax           /* Copy loop index to %rax */
    mov     $16, %rbx            /* Divisor for hexadecimal conversion */
    xor     %rdx, %rdx           /* Clear %rdx for division */
    div     %rbx                 /* Divide %rax by 16: quotient in %rax, remainder in %rdx */

    /* Convert high digit to ASCII */
    cmp     $10, %al             /* Compare high digit with 10 */
    jl      high_digit_digit     /* If less than 10, handle as digit */
    add     $55, %al             /* Otherwise, convert to 'A'-'F' (55 = 'A' - 10) */
    jmp     store_high_digit

high_digit_digit:
    add     $48, %al             /* Convert to ASCII by adding '0' (48 = '0') */

store_high_digit:
    mov     %al, hex_str         /* Store high digit in hex_str */

    /* Convert low digit to ASCII */
    cmp     $10, %dl             /* Compare low digit with 10 */
    jl      low_digit_digit      /* If less than 10, handle as digit */
    add     $55, %dl             /* Otherwise, convert to 'A'-'F' (55 = 'A' - 10) */
    jmp     store_low_digit

low_digit_digit:
    add     $48, %dl             /* Convert to ASCII by adding '0' (48 = '0') */

store_low_digit:
    mov     %dl, hex_str+1       /* Store low digit in hex_str+1 */

    /* Determine the length of the hexadecimal string */
    cmp     $0, %al              /* Check if high digit is 0 */
    je      single_digit         /* If high digit is 0, print only the low digit */

    /* Write the hex_str (2-digit hexadecimal value + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     hex_str(%rip), %rsi  /* Load the address of hex_str */
    mov     $3, %rdx             /* Length of the string (2 bytes for digits + 1 byte for newline) */
    syscall                      /* invoke syscall to print the string */

    jmp     next_iteration       /* Skip single-digit handling */

single_digit:
    /* Write the hex_str (single-digit hexadecimal value + newline) */
    mov     $1, %rax             /* syscall number for sys_write (1) */
    mov     $1, %rdi             /* File descriptor 1 is stdout */
    lea     hex_str+1(%rip), %rsi /* Load the address of hex_str+1 (skip high digit) */
    mov     $2, %rdx             /* Length of the string (1 byte for digit + 1 byte for newline) */
    syscall                      /* invoke syscall to print the string */

next_iteration:
    inc     %r15                 /* Increment the loop counter */
    cmp     $max, %r15           /* Compare the loop counter to max */
    jne     loop                 /* If not equal, continue the loop */

    mov     $60, %rax            /* syscall number for exit (60) */
    xor     %rdi, %rdi           /* Set exit status to 0 */
    syscall                      /* invoke syscall */

.data
loop_msg:   .asciz "Loop: "     /* String to print before the loop index */
hex_str:    .ascii "  \n"       /* Space to store the hexadecimal value and newline *

Output:



Challenge:

Code:
.global _start

_start:
    // Load the address of the row_table into x0
    ldr x0, =row_table
    mov x4, 0                   // Initialize counter

print_loop:
    // Load the address of the current row into x1
    ldr x1, [x0, x4, lsl 3]     // x4 is the index, lsl 3 to multiply by 8 (size of pointer)
    cbz x1, exit                // If x1 is zero (end of table), exit

    // Call the print_string subroutine
    mov x0, x1                  // Move the string address to x0 (expected by print_string)
    bl print_string

    // Increment the counter and repeat
    add x4, x4, 1
    b print_loop

exit:
    mov x0, 0                   // Exit status 0
    mov x8, 93                  // syscall: exit
    svc 0                       // Make system call

// Subroutine to print a string
print_string:
    mov x1, x0                  // Address of string (x0 is the input)
    mov x2, 0                   // Initialize length counter

1:
    ldrb w3, [x1, x2]           // Load byte from string
    cbz w3, 2f                  // If null terminator, exit loop
    add x2, x2, 1               // Increment length counter
    b 1b                        // Repeat loop

2:
    mov x0, 1                   // File descriptor 1 (stdout)
    mov x8, 64                  // syscall: write
    svc 0                       // Make system call
    ret                         // Return from subroutine

.data
row1:    .asciz "  1 x  1 =   1\n"
row2:    .asciz "  2 x  1 =   2\n"
row3:    .asciz "  3 x  1 =   3\n"
row4:    .asciz "  4 x  1 =   4\n"
row5:    .asciz "  5 x  1 =   5\n"
row6:    .asciz "  6 x  1 =   6\n"
row7:    .asciz "  7 x  1 =   7\n"
row8:    .asciz "  8 x  1 =   8\n"
row9:    .asciz "  9 x  1 =   9\n"
row10:   .asciz " 10 x  1 =  10\n"
row11:   .asciz " 11 x  1 =  11\n"
row12:   .asciz " 12 x  1 =  12\n"
spacer:  .asciz "-------------\n"

// Table of row addresses
row_table:
    .quad row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12, 0

Output:

Explain:

I wanted to write an assembly program to print a complete multiplication table from 1 x 1 to 12 x 12.I planned to use two nested loops: An outer loop to iterate through the multiplicand (rows, e.g., 1 to 12). An inner loop to iterate through the multiplier (columns, e.g., 1 to 12).However,The loops did not continue as expected. After printing the first set of rows, the program stopped or the program crashed with a segmentation fault.Therefore I have to hardcode my all the rows in the .data section.


Comments

Popular posts from this blog

PROJECT STAGE2

PROJECT STAGE1

LAB 4