SPO600 Lab5 64-Bit Assembly Language Lab Pt.1 ---AArch64 part
In this Lab, I am going to experiment with assembler on the x86_64 and aarch64 platforms.
Task 1 Observe the difference between source code and the object file of the aarch64 assembly language
Task 2 -- A loop which print 6 "Loop" word
I have to modify a provided code block in the aarch64 system to print loop for 6 times.
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 6 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
loop:
/* ... body of the loop ... do something useful here ... */
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add x19, x19, 1 /* increment the loop counter */
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop\n"
len= . - msg
The yellow highlighted code : print the String "Loop"
result:
Task 3. Modify the code so that it also show the iteration number, i,e, Loop: 1, Loop: 2..etc
I would like to add an extra num variable to .data. Update the variable in every loop and print it.
code:
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 6 /* loop exits when the index hits this number (loop condition is i<max) */
start:
mov x19, min
adr x21, num
loop:
/* ... body of the loop ... do something useful here ... */
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len1 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
/* print the number*/
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, num /* message location (memory address) */
mov x2, len2 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add w19, w19, 1 /* increment the loop counter */
/* update the num value in .data*/
mov w20, w19
add w20, w20, 48
strb w20, [x21]
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: "
len1= . - msg
num: .ascii "0 \n"
len2= . - num
Yellow highlighted: the variable added to print the iteration number
Red highlighted: to change the num variable in .data
Green highlighted: to print the num variable in .data
result:
Task 4. Extend the code to loop from 00 to 32
I have two way to code. The first way is to do find the units digit and tens digits by division in every loop. But, it is quite boring and I tend to prevent performing division. As a result, I decide to use another way, which is use the registers to store each digit's ascii value to be display.
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 33 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
adr x22, num //address of first digit
add x23, x22, 1 //address of second digit
mov w21, 48 //the ten digit
mov w20, 48
loop:
/* ... body of the loop ... do something useful here ... */
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len1 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
/* print the number*/
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, num /* message location (memory address) */
mov x2, len2 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add x19, x19, 1 /* increment the loop counter */
add w20, w20, 1 /* increment the units digit*/
cmp w20, 58
b.lt update
/*update the tens digit when units digit >10*/
add w21, w21, 1
strb w21, [x22]
mov w20, 48
/* update the num value in .data*/
update:
strb w20, [x23]
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: "
len1= . - msg
num: .ascii "00\n"
len2= . - num
Yellow highlighted: Initialize the register to store the address of output and the counter
Red highlighted: check if the units digit>10, then check the tens digits accordingly
Green highlighted: update num variable which is going to be printed
result:
Task 5. modify the code to make it suppress the leading zero
My plan is to use a register to store the memory address to be edited during the iteration and increment it instead. Then, when the loop first reach 10, it change the memory address to the digit after.
code:
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 33 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
adr x22, num //address of first digit
adr x23, num //address which increment during the loop
mov w21, 48 //the ten digit
mov w20, 48
loop:
/* ... body of the loop ... do something useful here ... */
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len1 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
/* print the number*/
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, num /* message location (memory address) */
mov x2, len2 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add x19, x19, 1 /* increment the loop counter */
add w20, w20, 1 /* increment the units digit*/
cmp x19, 10
b.ne checkten
/*the first time reach 10*/
add x23, x22, 1
mov w20, 58
mov w21, 48
checkten:
cmp w20, 58
b.lt update
/*update the tens digit when units digit >10*/
add w21, w21, 1
strb w21, [x22]
mov w20, 48
/* update the num value in .data*/
update:
strb w20, [x23]
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: "
len1= . - msg
num: .ascii "0 \n"
len2= . - num
Red highlighted: check if the loop reach 10 the first time. If so, the incrementing digit will be changed. Also, move the current value in the digital to the new digit before the regular calculation with carry.
result:
Task 6. Modify the code so that it output in hexadecimal (0-20) instead of decimal (0-32)
This is easy. I just have to change the value to be compare before the branches and add an extra part to increase the ascii value stored in the register to "A"(65) whenever it reach 58 .
code:
.text
.globl _start
min = 0 /* starting value for the loop index; **note that this is a symbol (constant)**, not a variable */
max = 33 /* loop exits when the index hits this number (loop condition is i<max) */
_start:
mov x19, min
adr x22, num //address of first digit
adr x23, num //address which increment during the loop
mov w21, 48 //the ten digit
mov w20, 48
loop:
/* ... body of the loop ... do something useful here ... */
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, msg /* message location (memory address) */
mov x2, len1 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
/* print the number*/
mov x0, 1 /* file descriptor: 1 is stdout */
adr x1, num /* message location (memory address) */
mov x2, len2 /* message length (bytes) */
mov x8, 64 /* write is syscall #64 */
svc 0 /* invoke syscall */
add x19, x19, 1 /* increment the loop counter */
add w20, w20, 1 /* increment the units digit*/
cmp w20, 58
b.ne chknewdg
add w20, w20, 7
chknewdg:
cmp x19, 16
b.ne check16
/*the first time reach 16*/
add x23, x22, 1
mov w20, 71
mov w21, 48
check16:
cmp w20, 71
b.lt update
/*update the digit when units digit >16*/
add w21, w21, 1
strb w21, [x22]
mov w20, 48
/* update the num value in .data*/
update:
strb w20, [x23]
cmp x19, max /* see if we've hit the max */
b.ne loop /* if not, then continue the loop */
mov x0, 0 /* set exit status to 0 */
mov x8, 93 /* exit is syscall #93 */
svc 0 /* invoke syscall */
.data
msg: .ascii "Loop: "
len1= . - msg
num: .ascii "0 \n"
len2= . - num
Yellow highlighted: check if the digit reach 10. If so, increase it to "A"
Red highlighted: criteria changed from 10 to 16
result:
Comments
Post a Comment