I'm slowly getting used to aarch64 by translating trivial C programs to asm and learn on the go but is stuck here:
/*
int power(int i): a function to calculate exponential power
*/
.global power //function prologue to declare it as global
.p2align 2 // align for better access - align 2^2 bytes
power: // a label to start the proc
.cfi_startproc // declare proc start
cmp w1, #0 // check if base is 0
b.eq end // if true then just return 0
mov x8, x1 // i = exp, x8 is i
mov x9, x0 // use x0 as result, so x9 is base
subs x8, x8, #1 // since we count down to 0, sub 1
loop:
mul w0, w0, w9 // result = result * base (w0 is part of x0)
subs w8, w8, #1 // i = i - 1 (w0 is part of x8)
b.ne loop // if i != 0 then loop
end:
ret // return to caller
.cfi_endproc // end proc
/**
Main function
*/
.global _main // Provide program starting address to linker
.align 4 // Make sure everything is aligned properly
// Setup the parameters to print hello world
// and then call the Kernel to do it.
_main:
.cfi_startproc
.cfi_def_cfa_offset 16
// print the power
mov x0, #2
mov x1, #3
bl power
bl print_number
bl println // <--------- omit this line and the output will be gone
// exit
mov X0, #0 // return 0
mov X16, #1 // syscall 1 terminate program
svc #0x80 // call kernel
.cfi_endproc
/* static functions*/
.p2align 2
print_number:
.cfi_startproc
// stack stuff
sub sp, sp, #32 // substract 32 from sp
stp x29, x30, [sp, #16] // store ?
add x29, sp, #16
// call frame stuff
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
// grab the args
mov x8, x0
str x8, [sp]
// load string using two instructions
// load the 4kb page from this instruction
// can either use LDR or STR to read or write address inside
// this page or ADD to calculate the final address using
// the last 12 bit denoted by @PAGEOFF
adrp x0, format_string@PAGE
add x0, x0, format_string@PAGEOFF
bl _printf
// refresh stack stuff
ldp x29,x30, [sp, #16]
add sp, sp, #32
ret
.cfi_endproc
// println: print a newline
.p2align 2
println:
.cfi_startproc
//stackstuff
sub sp, sp, #32 // sp = sp - 32
stp x29, x30, [sp, #16] // store stuff
add x29, sp, #16 // x29 = sp + 16
//callframe
.cfi_def_cfa w29, 16
.cfi_offset w30, -8
.cfi_offset w29, -16
mov x8, x0
str x8, [sp]
adrp x0, newline@PAGE
add x0, x0, newline@PAGEOFF
bl _printf
//refresh stack
ldp x29, x30, [sp, #16]
add sp, sp, #32
ret
.cfi_endproc
/** Data */
.data
format_string: .asciz "Number is: %d"
newline: .asciz "\n"
basically I will get no output at all if I omit line 38. And when compile a C file to test it out, my printf turns out like this:
Number is: 3%
The %
is not supposed to be there. I suspect that I simplified the call too much by taking out some instructions but I'm not familiar enough with aarch64 to figure out what's wrong. Can you help point me to the right direction?
Thanks,