## DEV Community

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
``````

## 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:
mov        x12, 10
udiv       x13, x19, x12
cmp        x16, 0x30
b.eq       ones
strb       w16, [x14]

ones:
msub       x13, x13, x12, x19
strb       w13, [x14]

tensTable:
mov        x12, 10
udiv       x13, x20, x12
cmp        x16, 0x30
b.eq       onesTable
strb       w16, [x14]
onesTable:
msub       x13, x13, x12, x20
strb       w13, [x14]

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

mov        X0, 1
mov        x2, len

mov        x8, 64
svc        0

cmp     x19, max
b.ne    loop

mov     x19, min
mov     x13, ' '
strb    w13, [x14]
strb    w13, [x14]
strb    w13, [x14]
cmp     x20, max
b.ne    loop

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

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

``````

## Walkthrough

### Data Section

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

``````
• `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

``````
• `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)

``````
• Initialize x19 with min (1), representing the starting row index.
• Initialize x20 with table (1), representing the starting column index.

### Main Loop

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

ones:
msub       x13, x13, x12, x19
strb       w13, [x14]
``````
• The loop starts by converting the current row index x19 to a character.
• 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:
msub       x13, x13, x12, x19
strb       w13, [x14]
``````
• `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:
mov        x12, 10
udiv       x13, x20, x12
cmp        x16, 0x30
b.eq       onesTable
strb       w16, [x14]

onesTable:
msub       x13, x13, x12, x20
strb       w13, [x14]

``````
• `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:
msub       x13, x13, x12, x20
strb       w13, [x14]

``````
• `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
mov        x12, 100
udiv       x15, x21, x12
cmp        x13, 0x30
b.eq       tensres
strb       w13, [x14]

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

onesres:
msub       x17, x17, x12, x15
strb       w17, [x14]

``````
• `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
mov        x12, 10
udiv       x17, x15, x12
cmp        x13, 0x30
b.eq       onesres
strb       w13, [x14]

onesres:
msub       x17, x17, x12, x15
strb       w17, [x14]

``````
• These sections handle formatting the tens and ones digits for the result similarly to the previous sections.

### Printing the Formatted Message

``````     mov        X0, 1
mov        x2, len

mov        x8, 64
svc        0
``````
• 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, ' '
strb    w13, [x14]
strb    w13, [x14]
strb    w13, [x14]
cmp     x20, max
b.ne    loop
``````
• 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!!!!