Hello everybody I am back with the last part of Lab3 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 112 (“1 x 1 = 1” through “12 x 12 = 144”).
The output looks like this.
[ymulani@aarch64001 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:
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
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,
andtable
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:
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]
 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]

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]

add x15, x20, 0x30
converts the multiplierx20
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
dividesx20
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]

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]

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]
 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
 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
 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!!!!
Top comments (0)