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:
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)