Function Call In Detail
When you perform a function call, CPU would call a
branch link
instruction (a.k.a bl), the return address will be placed at LR register, the PC register is changed to the address you are branching to.
This note describes the relationships with stack pointer, function arguments, function call[1][2][3], return values and how compilers works on this.
a frame pointer is used to maintain a fixed point of reference within a stack frames. It make it easier to access local variable and function parameters.
Stack Frame (Activation Record)
A stack frame is a localized memory portion within the stack which dedicated for a specific function.
Experiment
The following steps are tested on ARM64 CPU.
For example, a function sum
has two arguments:
int a
int b
and a return value which is integer data type.
int sum(int a, int b) {
return a + b;
}
int main() {
int a = sum(1, 2);
return 0;
}
We then use gcc
to compile it and gdb
to inspect it's assembly code.
$> gcc -o sum -g main.c
$> gdb ./sum
(gdb) disas main
...
...
(gdb) disas sum
...
...
We may first see the assembly of disas main
Dump of assembler code for function main:
0x0000000000000704 <+0>: stp x29, x30, [sp, #-32]!
0x0000000000000708 <+4>: mov x29, sp
0x000000000000070c <+8>: mov w1, #0x2 // #2
0x0000000000000710 <+12>: mov w0, #0x1 // #1
0x0000000000000714 <+16>: bl 0x6e4 <sum>
0x0000000000000718 <+20>: str w0, [x29, #28]
0x000000000000071c <+24>: mov w0, #0x0 // #0
0x0000000000000720 <+28>: ldp x29, x30, [sp], #32
0x0000000000000724 <+32>: ret
End of assembler dump.
Then we see the assembly of disas sum
Dump of assembler code for function sum:
0x00000000000006e4 <+0>: sub sp, sp, #0x10
0x00000000000006e8 <+4>: str w0, [sp, #12]
0x00000000000006ec <+8>: str w1, [sp, #8]
0x00000000000006f0 <+12>: ldr w1, [sp, #12]
0x00000000000006f4 <+16>: ldr w0, [sp, #8]
0x00000000000006f8 <+20>: add w0, w1, w0
0x00000000000006fc <+24>: add sp, sp, #0x10
0x0000000000000700 <+28>: ret
End of assembler dump.
where sp
is stack point.
📸 FlashCards
- Calling and returning
- How does caller function jump to callee function ?
- How does callee function jump back to the right place in caller function ?
- Passing parametters
- How does caller function pass parameters to callee function ?
- Storing local variables
- Where does callee function store it's local value ?
- Handling registers
- How do caller and callee functions use same register without interference ?
- Returing a value
- How does callee function send return value back to caller function ?
Jump to the address of the address of the callee's first instruction.
Jump to the instruction immediately following the most-recently-executed
call instruction.
^1654504087976