我是靠谱客的博主 危机山水,这篇文章主要介绍函数调用栈,现在分享给大家,希望可以做个参考。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void swap(int * a, int *b) { int c; c = *a; *a = *b; *b = c; } int main() { int a, b; a = 16; b = 32; swap(&a, &b); return (a - b); }
复制代码
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
30
31
32
33
.text _swap: pushl %ebp # 保存原ebp值,设置当前函数的帧指针。 movl %esp,%ebp subl $4,%esp # 为局部变量c在栈内分配空间。 movl 8(%ebp),%eax # 取函数第1个参数,该参数是一个整数类型值的指针。 movl (%eax),%ecx # 取该指针所指位置的内容,并保存到局部变量c中。 movl %ecx,-4(%ebp) movl 8(%ebp),%eax # 再次取第1个参数,然后取第2个参数。 movl 12(%ebp),%edx movl (%edx),%ecx # 把第2个参数所指内容放到第1个参数所指的位置。 movl %ecx,(%eax) movl 12(%ebp),%eax # 再次取第2个参数。 movl -4(%ebp),%ecx # 然后把局部变量c中的内容放到这个指针所指位置处。 movl %ecx,(%eax) leave # 恢复原ebp、esp值(即movl %ebp,%esp; popl %ebp;)。 ret _main: pushl %ebp # 保存原ebp值,设置当前函数的帧指针。 movl %esp,%ebp subl $8,%esp # 为整型局部变量a和b在栈中分配空间。 movl $16,-4(%ebp) # 为局部变量赋初值(a=16,b=32)。 movl $32,-8(%ebp) leal -8(%ebp),%eax # 为调用swap()函数作准备,取局部变量b的地址, pushl %eax # 作为调用的参数并压入栈中。即先压入第2个参数。 leal -4(%ebp),%eax # 再取局部变量a的地址,作为第1个参数入栈。 pushl %eax call _swap # 调用函数swap()。 movl -4(%ebp),%eax # 取第1个局部变量a的值,减去第2个变量b的值。 subl -8(%ebp),%eax leave # 恢复原ebp、esp值(即movl %ebp,%esp; popl %ebp;)。 ret

img

before call:准备实参压入栈,

call 指令:

​ 压入返回值(函数调用结束后执行的下一条语句地址)

​ 执行call ( eip 入栈 jump )

Callee execution(被调用者执行):

​ 保存旧ebp,没更新ebp、esp。

​ 分配临时变量内存

leave指令:

​ 恢复原ebp、esp值

ret指令:

​ 取栈顶值作为eip (这时候栈顶的值是函数调用结束需要执行的下一条指令地址)

总结下:

每次进行函数调用就是创建一个新栈帧保存旧栈帧,还有就是通过EIP进行跳转到被调用的代码,和返回调用出继续执行。

被调用者的栈帧就是保存函数局部变量,和恢复到调用者栈帧执行环境的必要信息。

帧,还有就是通过EIP进行跳转到被调用的代码,和返回调用出继续执行。

被调用者的栈帧就是保存函数局部变量,和恢复到调用者栈帧执行环境的必要信息。

最后

以上就是危机山水最近收集整理的关于函数调用栈的全部内容,更多相关函数调用栈内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(90)

评论列表共有 0 条评论

立即
投稿
返回
顶部