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