SPO600 Lab 4
In lab 4, I have to do a simple program to print numbers from 0 to 30 with X86_64 and AArch64 Assembly. It was my bad to forget the passphrase of my SSH key, so I could not log in to the server to do the lab. Fortunately, I found a package on Ubuntu APT-GET library that simulates AArch64 architecture, which is QEMU. The command to install it: sudo apt-get install qemu-user gcc-aarch64-linux-gnu. With the program, I was able to compile and run AArch64 Assembly without ARM hardware like a Raspberry Pi 4.
Back to the
main program, this is my code to print from 0 to 9:
.text
.globl main
min = 0
max = 10
main:
mov x19, min
loop:
adr x1, msg
mov x2, len
mov x0, 1
mov x8, 64
svc 0
adr x23, msg
add x19, x19, 1
mov x20, x19
add x20, x20, '0'
strb w20, [x23,0]
cmp x19, max
bne loop
mov x0, 0
mov x8, 93
svc 0
.data
msg:
.ascii "0\n"
len = . – msg
And this is the result:
Firstly, I define min
and max to 0 and 10, respectively. Then I store min to register x19 and
increase it after each iterator. “msg” is declared with “0\n”. “0” is the initial
output, and it is replaced with a digit after each loop. After increasing register x19
by 1, I store the value to x20 register then convert it from integer to digit character.
Finally, “0” in msg will be replaced and printed to the console by accessing location
0 of x23 register – where I store msg.
Next, to add "Loop:", I
can simply change "msg" to "Loop: 0\n" and change the way I
replace a digit in "msg" to address 6.
It is definitely more work to print from 0 to 29. We can not just change the max to 30. We have to determine if the number has two digits or one. To do that, we can find the remainder and quotient by dividing the value stored in register x19 with 10. If the quotient is not 0, we proceed to write two digits. The way we can print "0" in front of numbers that are under ten is that we can have extra empty space (i.e., "Loop: 0 \n"). In case the number is under ten, we print the digit at the address after "0". Similarly, if we do not want the extra "0", we can put an empty space before "0" (i.e., "Loop: 0\n") to print numbers that are bigger than 10, while "0" is to replace for one-digit number and the second digit of the two-digit number. To sum up, I have the code to print from 0 to 29:
.text
.globl main
min = 0
max = 30
ten = 10
main:
mov x19, min
mov x22, ten
loop:
adr x1, msg
mov x2, len
mov x0, 1
mov x8, 64
svc 0
adr x23, msg
add x19, x19, 1
udiv x20, x19, x22
msub x21, x22, x20, x19
cmp x20, 0
beq onedigitonly
// print 2 digits
add x20, x20, '0'
strb w20, [x23,6]
onedigitonly:
// print 1 digit only
add x21, x21, '0'
strb w21, [x23,7]
cmp x19, max
bne loop
mov x0, 0
mov x8, 93
svc 0
.data
msg: .ascii "Loop: 0 \n"
len = . - msg
Comments
Post a Comment