lab4 - 64 bit Assembly language Lab - Part 2
This is the second part of the lab 4 for my course SPO600. I am continuing for my previous blog, part 1 of lab4 which can be found at this link - Lab4-Part-1.
In the previous labs I covered three tasks in which I have to write the assembly language for aarch64 and x86_64 programs. We wrote the loop along with loop counter and printed the counter with each increment from 0 to 9. In this blog I am going to cover remaining tasks
Task 4: Extend code for aarch64 to loop up to 30 with 2 digits.
.text
.globl _start
min = 0 /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
mov x21, 10
loop:
/*Start of loop*/
adr x25, msg /*setting the address of string*/
udiv x20, x19, x21 /*unsigned divide - calculating first digit*/
msub x22, x21, x20, x19 /* calulating reminder - second digit */
add x20, x20, '0'
strb w20, [x25, 5] /*writing first digit*/
add x22, x22, '0'
strb w22, [x25, 6] /*writing second digit*/
mov x0, 1
adr x1, msg
mov x2, len
mov x8, 64
svc 0
/*End of loop*/
add x19, x19, 1
cmp x19, max
b.ne loop
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop ##\n"
len= . - msg
Here is the output of the above code after successful build:
Task 5: update task 4 to suppress the leading zero for single digits
In task 5, we have to modify the code from the task for to remove the zero for digits 0-9 so that our loop should print 0-30 instead of 00-30.
This can be done easily by adding a label. I added a label before the second writing the second digits so that I can skip the first digit. To accomplish this used cmp command to compare the register holding loop counter with register having value 10 and then I used another command b.lt to branch to the label if counter is less than 10 meaning there is single digit. Moreover, I slightly modified my msg string so that it can work according to above. mechanism. Here is the improved code:
.text
.globl _start
min = 0 /* starting value for the loop index; note that this is a symbol (constant), not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
mov x21, 10
loop:
/*Start of loop*/
adr x25, msg /*setting the address of string*/
udiv x20, x19, x21 /*unsigned divide - calculating first digit*/
msub x22, x21, x20, x19 /* calulating reminder - second digit */
cmp x19, x21
b.lt DoubleDigits
add x20, x20, '0'
strb w20, [x25, 5] /*writing first digit*/
DoubleDigits:
add x22, x22, '0'
strb w22, [x25, 6] /*writing second digit*/
mov x0, 1
adr x1, msg
mov x2, len
mov x8, 64
svc 0
/*End of loop*/
add x19, x19, 1
cmp x19, max
b.ne loop
mov x0, 0 /* status -> 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop #\n"
len= . - msg
Here is the output:
Task 5. Repeat same code for x86_64
Now, in the second part of task 5, we have to write the similar code for the x86_64 platform.
I followed the similar procedure to modify the previous code and updated it to loop till 30. Instead using two separate commands like aarch64, I only used div command which calculated both quotient and remainders and stored them in rax and rdx registers. Now both of these registers hold the first and second digit of number. Just like in case of aarch64, I used label to skip the first digit, for comparison I used cmp and to jump to label, I used jl command. Here is the code:
.text
.globl _start
min = 0 /* starting value for the loop index; note that this is a symbol (constan*t), not a variable */
max = 31 /* loop exits when the index hits this number (loop condition is i<max) */
ten = 10
_start:
mov $min,%r15 /* loop index */
mov $ten, %r10
loop:
/*Start*/
movq %r15, %rax
movq $0, %rdx
div %r10
cmp %r10, %r15
jl digit
addq $'0', %rax
movq $msg + 5, %r11
movb %al, (%r11)
digit:
addq $'0', %rdx
movq $msg + 6, %r11
movb %dl, (%r11)
movq $len,%rdx /* message length */
movq $msg,%rsi /* message location */
movq $1,%rdi /* file descriptor stdout */
movq $1,%rax /* syscall sys_write */
syscall
/*End*/
inc %r15 /* increment index */
cmp $max,%r15 /* see if we're done */
jne loop /* loop if we're not */
mov $0,%rdi /* exit status */
mov $60,%rax /* syscall sys_exit */
syscall
.section .data
msg: .ascii "Loop #\n"
len= . - msg
Here is the output:
During this part, I learned about division in both platforms, in aarch64 we have to perform two different commands to calculate quotient and remainder separately whereas in x86_64 we can calculate both and store them in rax and rdx using a very simple command but for this we have to prepare those registers. I found division more simple for x86_64 but overall I like aarch64.
Comments
Post a Comment