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


It had been a busy week with tons of midterm tests and homework, so I will continue with X86_64 later with a separate blog...


Comments

Popular posts from this blog

SPO600 Lab 2

SPO600 Lab 1

SPO600 Lab 3