Lab 5 – Aarch 64

In Lab 5, we will try to disassembly some C programs to look at how their assembly code is generated, and write a simple “Hello Word” program using assembly language.

Disassembly hello programs on Aarch64 machine

The <main> section is the code that inside of int main(){…}

hello:

hello2:

hello3:

Lab 5 on Aarch64

step 1: we need a program which is able to print “Hello Word”

.text
.globl _start
_start:

        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 */

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Hello, world!\n"
len=    . - msg

We are on Linux, so we need to perform system call “write” to output “Hello World” to screen.

write prototype:

ssize_t write(int fd, const void *buf, size_t count);

We can see the write function has 3 parameters: file descriptor, a pointer that points to where the data is in the memory, and the length of the data.

We declared a message in .data section and calculated the length of the message. Now we have all the data we need to perform “write” system call.

We move 1(stdout) to x0 as file descriptor, move address of msg to x1 as the pointer of the buffer, and len to x2 as the length of the message.

After all, we need to indicate the system call number to x8, which should be 64(write) here.

svc 0 to invoke the system call on Aarch64.

Now we can see the message “Hello World” on the screen.

After the output, we need to exit the program, so we performed another system call – exit. the parameter is 0.

Step 2:

We need to loop the output 30 times

.text

.globl _start



_start:

        mov     x19,min

loop:
        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
        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      "Hello, world!\n"
len=    . - msg
min = 0
max = 30

We indicated a counter in x19, and loop the out put until the counter is max, which is 30.

Step 3: print the digits

For the first 10 loops is easy, we just need to output the char 0-9, which are 30-39 in ascii code.

         add x20, x19, 30

then print it to the screen by replacing the char at 14th char of msg.

        adr     x30, msg+14
        strb    w20, [x30]

But the problem is print 10-30. We need to deal with the second digit:

        udiv    x25, x19, x18
        msub    x26, x25, x18, x19

We store 10 in x18, and divide the number by 10, then store the remainder in x26. Then we can use the way that we display the 1-digit number to display 2-digit number.

Lab 5 on Aarch64:

.text
.globl _start

_start:
        mov     x19,min         /*store the min value into x19 as a loop index*/
        mov     x18,division    /*store the division value(10) into x18*/
loop:
        mov     x0, 1           /* file descriptor: 1 is stdout */

        cmp     x19, 9          /* compare x19(loop index value) with 9*/
        b.gt    digit_2         /* if the value is greater than 9(2-digit), go to the subroutine digit_2*/
        bl      digit_1         /* if the value is less or equal than 9(1-digit), go to the subroutine digit_1*/

digit_1:
        add     x20, x19, '0'   /* ascii number character*/

        adr     x30, msg+14     /* the digit location within string */
        strb    w20, [x30]      /* store the digit at the location */
        bl      print           /* go to the print subroutine */


digit_2:
        udiv    x25, x19, x18   /* divide the value by 10 and store the value into the x25 */
        msub    x26, x25, x18, x19 /* store the remainder into x26 */

        add     x21, x25, '0'   /* ascii number character */
        add     x20, x26, '0'   /* ascii number character */

        adr     x25, msg+14     /* the digit location within string */
        strb    w21, [x25]      /* store the digit at the location */
        adr     x26, msg+15     /* the digit location within string */
        strb    w20, [x26]      /* store the digit at the location */

        bl      print

print:
        adr     x1, msg         /* store the locatio of message */
        mov     x2, len         /* store the string length into x2 */

        mov     x8, 64          /* write is syscall #64 */
        svc     0               /* invoke syscall */

        add     x19, x19, 1     /* increment x19 value which is loop index */
        cmp     x19, max        /* compare x19 with max value */

        b.ne    loop            /* if the value is not equal to max value, loop it again */

        mov     x0, 0           /* status -> 0 */
        mov     x8, 93          /* exit is syscall #93 */
        svc     0               /* invoke syscall */

.data
msg:    .ascii      "Hello World!:   \n"
len= .- msg
min = 0
max = 30
division=10

After we finished the program on Aarch64, we will code the program again on x86_64

Leave a comment

Design a site like this with WordPress.com
Get started