DEV Community

Yukti Manoj Mulani
Yukti Manoj Mulani

Posted on

64-Bit Assembly Language Lab 3 part-4

Hello everybody I am back with the last part of Lab-3 which is some optional challenges on the assembler. So, lets get right into it.

In todays post we will be writing a program to print tables in the assembler. The exact spec goes like this.
Write a program in aarch64 assembly language to print the times tables from 1-12 (“1 x 1 = 1” through “12 x 12 = 144”).

The output looks like this.

[ymulani@aarch64-001 aarch64]$ ./tables
 1 x  1 =   1
 2 x  1 =   2
 3 x  1 =   3
 4 x  1 =   4
 5 x  1 =   5
 6 x  1 =   6
 7 x  1 =   7
 8 x  1 =   8
 9 x  1 =   9
10 x  1 =  10
11 x  1 =  11
12 x  1 =  12
 1 x  2 =   2
 2 x  2 =   4
 3 x  2 =   6
 4 x  2 =   8
 5 x  2 =  10
 6 x  2 =  12
 7 x  2 =  14
 8 x  2 =  16
 9 x  2 =  18
10 x  2 =  20
11 x  2 =  22
12 x  2 =  24
 1 x  3 =   3
 2 x  3 =   6
 3 x  3 =   9
 4 x  3 =  12
 5 x  3 =  15
 6 x  3 =  18
 7 x  3 =  21
 8 x  3 =  24
 9 x  3 =  27
10 x  3 =  30
11 x  3 =  33
12 x  3 =  36
 1 x  4 =   4
 2 x  4 =   8
 3 x  4 =  12
 4 x  4 =  16
 5 x  4 =  20
 6 x  4 =  24
 7 x  4 =  28
 8 x  4 =  32
 9 x  4 =  36
10 x  4 =  40
11 x  4 =  44
12 x  4 =  48
 1 x  5 =   5
 2 x  5 =  10
 3 x  5 =  15
 4 x  5 =  20
 5 x  5 =  25
 6 x  5 =  30
 7 x  5 =  35
 8 x  5 =  40
 9 x  5 =  45
10 x  5 =  50
11 x  5 =  55
12 x  5 =  60
 1 x  6 =   6
 2 x  6 =  12
 3 x  6 =  18
 4 x  6 =  24
 5 x  6 =  30
 6 x  6 =  36
 7 x  6 =  42
 8 x  6 =  48
 9 x  6 =  54
10 x  6 =  60
11 x  6 =  66
12 x  6 =  72
 1 x  7 =   7
 2 x  7 =  14
 3 x  7 =  21
 4 x  7 =  28
 5 x  7 =  35
 6 x  7 =  42
 7 x  7 =  49
 8 x  7 =  56
 9 x  7 =  63
10 x  7 =  70
11 x  7 =  77
12 x  7 =  84
 1 x  8 =   8
 2 x  8 =  16
 3 x  8 =  24
 4 x  8 =  32
 5 x  8 =  40
 6 x  8 =  48
 7 x  8 =  56
 8 x  8 =  64
 9 x  8 =  72
10 x  8 =  80
11 x  8 =  88
12 x  8 =  96
 1 x  9 =   9
 2 x  9 =  18
 3 x  9 =  27
 4 x  9 =  36
 5 x  9 =  45
 6 x  9 =  54
 7 x  9 =  63
 8 x  9 =  72
 9 x  9 =  81
10 x  9 =  90
11 x  9 =  99
12 x  9 = 198
 1 x 10 =  10
 2 x 10 =  20
 3 x 10 =  30
 4 x 10 =  40
 5 x 10 =  50
 6 x 10 =  60
 7 x 10 =  70
 8 x 10 =  80
 9 x 10 =  90
10 x 10 = 190
11 x 10 = 110
12 x 10 = 120
 1 x 11 =  11
 2 x 11 =  22
 3 x 11 =  33
 4 x 11 =  44
 5 x 11 =  55
 6 x 11 =  66
 7 x 11 =  77
 8 x 11 =  88
 9 x 11 =  99
10 x 11 = 110
11 x 11 = 121
12 x 11 = 132
 1 x 12 =  12
 2 x 12 =  24
 3 x 12 =  36
 4 x 12 =  48
 5 x 12 =  60
 6 x 12 =  72
 7 x 12 =  84
 8 x 12 =  96
 9 x 12 = 198
10 x 12 = 120
11 x 12 = 132
12 x 12 = 144
Enter fullscreen mode Exit fullscreen mode

The Code reveal

 .text
 .globl _start
 min = 1                          /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
 max = 13                         /* loop exits when the index hits this number (loop condition is i<max) */
 table = 1
 _start:
     mov     x19, min      //Initialize the multipler (row index)
     mov     x20, table    // initialise the multiplicand (Column index)
 loop:
     add        x15, x19, 0x30
     adr        x14, msg
     mov        x12, 10
     udiv       x13, x19, x12
     add        x16, x13, 0x30
     cmp        x16, 0x30
     b.eq       ones
     strb       w16, [x14]

 ones:
     adr        x14, msg+1
     msub       x13, x13, x12, x19
     add        x13, x13, 0x30
     strb       w13, [x14]

 tensTable:
     add        x15, x20, 0x30
     adr        x14, msg+5
     mov        x12, 10
     udiv       x13, x20, x12
     add        x16, x13, 0x30
     cmp        x16, 0x30
     b.eq       onesTable
     strb       w16, [x14]
 onesTable:
     adr        x14, msg+6
     msub       x13, x13, x12, x20
     add        x13, x13, 0x30
     strb       w13, [x14]

 hundredres:
     mul        x21, x19, x20
     adr        x14, msg+10
     mov        x12, 100
     udiv       x15, x21, x12
     add        x13, x15, 0x30
     cmp        x13, 0x30
     b.eq       tensres
     strb       w13, [x14]
 tensres:
     msub       x15, x15, x12, x21
     mul        x21, x19, x20
     adr        x14, msg+11
     mov        x12, 10
     udiv       x17, x15, x12
     add        x13, x17, 0x30
     cmp        x13, 0x30
     b.eq       onesres
     strb       w13, [x14]
 onesres:
     adr        x14, msg+12
     msub       x17, x17, x12, x15
     add        x17, x17, 0x30
     strb       w17, [x14]

     mov        X0, 1
     adr        x1, msg
     mov        x2, len

     mov        x8, 64
     svc        0

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

     mov     x19, min
     mov     x13, ' '
     adr     x14, msg
     strb    w13, [x14]
     adr     x14, msg+10
     strb    w13, [x14]
     adr     x14, msg+11
     strb    w13, [x14]
     add     x20, x20, 1
     cmp     x20, max
     b.ne    loop

     mov     x0, 0           
     mov     x8, 93         
     svc     0               /* syscall */

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

Enter fullscreen mode Exit fullscreen mode

Walkthrough

Data Section

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

Enter fullscreen mode Exit fullscreen mode
  • msg is the format string used for printing each line of the multiplication table. It contains placeholders for the two numbers being multiplied and the result.
  • len is calculated as the length of the msg string.

Text Section

.text
.globl _start
min = 1
max = 13
table = 1

Enter fullscreen mode Exit fullscreen mode
  • min, max, and table are constants used for loop control.
  • The entry point _start is defined as a global label.

Start of the Program

_start:
     mov     x19, min      //Initialize the multipler (row index)
     mov     x20, table    // initialise the multiplicand (Column index)

Enter fullscreen mode Exit fullscreen mode
  • Initialize x19 with min (1), representing the starting row index.
  • Initialize x20 with table (1), representing the starting column index.

Main Loop

 loop:
     add        x15, x19, 0x30
     adr        x14, msg
     mov        x12, 10
     udiv       x13, x19, x12
     add        x16, x13, 0x30
     cmp        x16, 0x30
     b.eq       ones
     strb       w16, [x14]

 ones:
     adr        x14, msg+1
     msub       x13, x13, x12, x19
     add        x13, x13, 0x30
     strb       w13, [x14]
Enter fullscreen mode Exit fullscreen mode
  • The loop starts by converting the current row index x19 to a character.
  • adr x14, msg loads the address of the msg string into x14.
  • udiv x13, x19, x12 divides x19 by 10 to get the tens digit.
  • add x16, x13, 0x30 converts the tens digit to its ASCII representation.
  • cmp x16, 0x30 checks if the tens digit is zero.
  • If the tens digit is zero, it branches to the ones label.
  • Otherwise, it stores the tens digit in msg and proceeds.

Formatting Ones Digit for Row Index

ones:
     adr        x14, msg+1
     msub       x13, x13, x12, x19
     add        x13, x13, 0x30
     strb       w13, [x14]
Enter fullscreen mode Exit fullscreen mode
  • adr x14, msg+1 loads the address of the second character in msg.
  • msub x13, x13, x12, x19 calculates the remainder to get the ones digit.
  • add x13, x13, 0x30 converts the ones digit to its ASCII representation.
  • strb w13, [x14] stores the ones digit in msg.

Formatting Multiplier

tensTable:
    add        x15, x20, 0x30
    adr        x14, msg+5
    mov        x12, 10
    udiv       x13, x20, x12
    add        x16, x13, 0x30
    cmp        x16, 0x30
    b.eq       onesTable
    strb       w16, [x14]

onesTable:
    adr        x14, msg+6
    msub       x13, x13, x12, x20
    add        x13, x13, 0x30
    strb       w13, [x14]

Enter fullscreen mode Exit fullscreen mode
  • add x15, x20, 0x30 converts the multiplier x20 to a character.
  • adr x14, msg+5 loads the address of the character in msg where the multiplier should be placed.
  • udiv x13, x20, x12 divides x20 by 10 to get the tens digit.
  • add x16, x13, 0x30 converts the tens digit to its ASCII representation.
  • cmp x16, 0x30 checks if the tens digit is zero.
  • If the tens digit is zero, it branches to the onesTable label.
  • Otherwise, it stores the tens digit in msg.

Formatting Ones Digit for Multiplier

onesTable:
    adr        x14, msg+6
    msub       x13, x13, x12, x20
    add        x13, x13, 0x30
    strb       w13, [x14]

Enter fullscreen mode Exit fullscreen mode
  • adr x14, msg+6 loads the address of the sixth character in msg.
  • msub x13, x13, x12, x20 calculates the remainder to get the ones digit.
  • add x13, x13, 0x30 converts the ones digit to its ASCII representation.
  • strb w13, [x14] stores the ones digit in msg.

Formatting Result

hundredres:
    mul        x21, x19, x20
    adr        x14, msg+10
    mov        x12, 100
    udiv       x15, x21, x12
    add        x13, x15, 0x30
    cmp        x13, 0x30
    b.eq       tensres
    strb       w13, [x14]

tensres:
    msub       x15, x15, x12, x21
    mul        x21, x19, x20
    adr        x14, msg+11
    mov        x12, 10
    udiv       x17, x15, x12
    add        x13, x17, 0x30
    cmp        x13, 0x30
    b.eq       onesres
    strb       w13, [x14]

onesres:
    adr        x14, msg+12
    msub       x17, x17, x12, x15
    add        x17, x17, 0x30
    strb       w17, [x14]

Enter fullscreen mode Exit fullscreen mode
  • mul x21, x19, x20 calculates the product of the row and column indices.
  • adr x14, msg+10 loads the address where the result should start being placed in msg.
  • udiv x15, x21, x12 divides the product by 100 to get the hundreds digit.
  • add x13, x15, 0x30 converts the hundreds digit to its ASCII representation.
  • cmp x13, 0x30 checks if the hundreds digit is zero.
  • If the hundreds digit is zero, it branches to the tensres label.
  • Otherwise, it stores the hundreds digit in msg.

Formatting Tens and Ones Digit for Result

tensres:
    msub       x15, x15, x12, x21
    mul        x21, x19, x20
    adr        x14, msg+11
    mov        x12, 10
    udiv       x17, x15, x12
    add        x13, x17, 0x30
    cmp        x13, 0x30
    b.eq       onesres
    strb       w13, [x14]

onesres:
    adr        x14, msg+12
    msub       x17, x17, x12, x15
    add        x17, x17, 0x30
    strb       w17, [x14]

Enter fullscreen mode Exit fullscreen mode
  • These sections handle formatting the tens and ones digits for the result similarly to the previous sections.

Printing the Formatted Message

     mov        X0, 1
     adr        x1, msg
     mov        x2, len

     mov        x8, 64
     svc        0
Enter fullscreen mode Exit fullscreen mode
  • Prepares the syscall to write the message to the standard output.
  • mov X0, 1 sets the file descriptor to 1 (standard output).
  • adr x1, msg loads the address of the message.
  • mov x2, len sets the length of the message.
  • mov x8, 64 sets the syscall number for write.
  • svc 0 makes the syscall.

Loop Control

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

     mov     x19, min
     mov     x13, ' '
     adr     x14, msg
     strb    w13, [x14]
     adr     x14, msg+10
     strb    w13, [x14]
     adr     x14, msg+11
     strb    w13, [x14]
     add     x20, x20, 1
     cmp     x20, max
     b.ne    loop
Enter fullscreen mode Exit fullscreen mode
  • add x19, x19, 1: Increment the row index (x19).
  • cmp x19, max: Compare the current row index (x19) with the maximum limit (max, which is 13).
  • b.ne loop: If x19 is not equal to max, branch back to loop.
  • mov x19, min: Reset the row index (x19) to the minimum value (min, which is 1).
  • Insert spaces in the msg string to create a visual spacer between tables.
  • add x20, x20, 1: Increment the column index (x20).
  • cmp x20, max: Compare the current column index (x20) with the maximum limit (max).
  • b.ne loop: If x20 is not equal to max, branch back to loop.
  • If both row and column indices reach their maximum limits, the loop exits, and the program proceeds to termination.

So, that is it I wont talk much after this long and boring blog of walkthroughs and explainations. I hope you enjoyed it.

Until next time Happy Coding!!!!

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs