test.c (bare metal)
#include <stdio.h>
int add1(int a, int b)
{
int c;
c = a + b;
return c;
}
int main()
{
int x, y, z;
x = 3;
y = 4;
z = add1(x,y);
printf("z = %d\n", z);
}
I do aarch64-none-elf-gcc test.c -specs=rdimon.specs
and get a.out. I do aarch64-none-elf-objdump -d a.out
and got the assemlby code. Here is the main function.
00000000004002e0 <add1>:
4002e0: d10083ff sub sp, sp, #0x20 <-- reduce sp by 0x20 (just above it are saved fp and lr of main)
4002e4: b9000fe0 str w0, [sp, #12] <-- save first param x at sp + 12
4002e8: b9000be1 str w1, [sp, #8] <-- save second param y at sp + 8
4002ec: b9400fe1 ldr w1, [sp, #12] <-- load w1 with x
4002f0: b9400be0 ldr w0, [sp, #8] <-- load w0 with y
4002f4: 0b000020 add w0, w1, w0 <-- w0 = w1 + w0
4002f8: b9001fe0 str w0, [sp, #28] <-- store x0 to sp+28
4002fc: b9401fe0 ldr w0, [sp, #28] <-- load w0 with the result (seems redundant)
400300: 910083ff add sp, sp, #0x20 <-- increment sp by 0x20
400304: d65f03c0 ret
0000000000400308 <main>:
400308: a9be7bfd stp x29, x30, [sp, #-32]! <-- save x29(fp) and x30(lr) at sp - 0x20
40030c: 910003fd mov x29, sp <-- set fp to new sp, the base of stack growth(down)
400310: 52800060 mov w0, #0x3 // #3
400314: b9001fe0 str w0, [sp, #28] <-- x is assigned in sp + #28
400318: 52800080 mov w0, #0x4 // #4
40031c: b9001be0 str w0, [sp, #24] <-- y is assiged in sp + #24
400320: b9401be1 ldr w1, [sp, #24] <-- load func param for y
400324: b9401fe0 ldr w0, [sp, #28] <-- load func param for x
400328: 97ffffee bl 4002e0 <add1> <-- call add1 (args are in w0, w1)
40032c: b90017e0 str w0, [sp, #20] <-- store x0(result z) to sp+20
400330: b94017e1 ldr w1, [sp, #20] <-- load w1 with the result (why? seems redundant. it's already in w0)
400334: d0000060 adrp x0, 40e000 <__sfp_handle_exceptions+0x28>
400338: 91028000 add x0, x0, #0xa0 <-- looks like loading param x0 for printf
40033c: 940000e7 bl 4006d8 <printf>
400340: 52800000 mov w0, #0x0 // #0 <-- for main's return value..
400344: a8c27bfd ldp x29, x30, [sp], #32 <-- recover x29 and x30 (look's like values in x29, x30 was used in the fuction who called main)
400348: d65f03c0 ret
40034c: d503201f nop
I added my understanding with <--
mark. Could someone see the code and give me some corrections? Any small comment will be appreciated. (please see from <main>
)
ADD : Thanks for the comments. I think I forget to ask my real questions. At the start of main, the program who called main should have put it's return address(after main) in x30. And since main should call another function itself, it should modify x30, so it saves x30 in its stack. But why does it store it in sp - #0x20? and why are the variables x,y,z stored in sp + #20, sp + #24, sp + #28? If the main function calls printf, I guess sp and x29 will be decremented by some amount. Is this amount dependent on how much stack area the called function(here printf) uses? or is it constant? and how is the x29, x30 storage location in main determined? Is it determined so that those two values are located just above the called function(printf)'s stack area? Sorry for too many questions.