函数调用过程的汇编代码分析(arm64指令集),顺便关注一下栈空间的分配与回收

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int add(int a, int b){
int t = a + b;
return t;
}

int main(){
int x = 3;
x = add(x,2);
printf("%d",x);
return 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
add(int, int):
sub sp, sp, #32 // 将寄存器 sp 的值减去32,结果仍存储到 sp 中
str w0, [sp, 12] // 将寄存器 w0 中的32位数值存储到内存地址 sp+12 处
str w1, [sp, 8]
ldr w1, [sp, 12] // 将内存 sp+12 处的32位数值存储到寄存器 w1 中
ldr w0, [sp, 8]
add w0, w1, w0 // 将寄存器 w1 与 w0 的值相加,结果存入 w0
str w0, [sp, 28]
ldr w0, [sp, 28]
add sp, sp, 32
ret // 从函数调用中返回
.LC0:
.string "%d"
main:
stp x29, x30, [sp, -32]! // store pair: 将 x29 与 x30 两个64位寄存器的值同时存入内存地址 sp-32 处
mov x29, sp // 将64位寄存器 x29 中的值存入寄存器 sp 中
mov w0, 3
str w0, [sp, 28]
mov w1, 2
ldr w0, [sp, 28]
bl add(int, int) // branch & link指令,将 pc+4 的值存入 x30 寄存器,并跳转到 'add(int, int):' 处,此处的pc+4对应下一行的str w0...
str w0, [sp, 28]
ldr w1, [sp, 28]
adrp x0, .LC0 // 将 .LC0 的地址左移12位,将其与 pc 的值相加,并将结果的低12位置0,最后存入寄存器 x0 中
add x0, x0, :lo12:.LC0 // 将 x0 的值与 .LC0 地址的低12位相加,地址存入 x0 寄存器中
bl printf
mov w0, 1
ldp x29, x30, [sp], 32 //load pair: 将内存 sp+32 处的连续两个64位值读取到 x29 和 x30 寄存器中
ret //返回到x30寄存器所标识的地址继续执行

[wi是xi的低32位]。

image-20220514225243460

image-20220514224955809