让我们带着问题来阅读本篇文章
- 型参在哪里开辟内存?
- 型参的入栈顺序?
- 函数返回值怎么带出来?
- 函数的返回值为什么会回退到栈里?
- 函数调用结束为什么会沿着调用点继续执行?
我们先来了解一下堆与栈是怎样的一种存在
什么是栈?
栈用于维护函数调用的上下文,离开栈,函数就没有办法实现。栈通常在用户空间的最高地址处分配,通常有数兆字节大小。
栈在程序运行中具有举足轻重的地位。最重要的是,栈保存了一个函数调用所需要的的维护信息,这常常被称为堆帧栈或者活动记录。堆栈帧一般包括以下几个内容:
- 帧栈是一个main函数的活动空间范围。
- 函数的返回地址和参数。
- 临时变量:包括函数的非静态局部变量以及编辑器自动生成的其他临时变量。
- 保存的上下文:包括在函数调用前后需要保持不变寄存器。
什么是堆?
堆是用来容纳应用程序动态分配内存的内存区域,当程序使用malloc或new分配内存时,得到的内存来自堆里,堆也可能没有固定统一的存储区域。堆一般比栈大很多,可能有几十数百兆自己的容量。
认识函数堆栈调用的一些简单指令
mov 移值指令
lea 移地址
push 用栈
pop 出栈
call
- 压入下一行指令地址
- jump到被调用方函数
认识寄存器的存在
寄存器是CPU内部的元件,寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。
寄存器的用途:
1.可将寄存器内的数据执行算术及逻辑运算。
2.存于寄存器内的地址可用来指向内存的某个位置,即寻址。
3.可以用来读写数据到电脑的周边设备。
eax 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
add eax,4; eax+=4
sub eax,4; eax-=4
ebx 是"基地址"(base)寄存器, 在内存寻址时存放基地址。
ecx 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
edx 总是被用来放整数除法产生的余数。
ebp 栈底指针寄存器
esp 栈顶指针寄存器
pc 下一行指令寄存器
在i386中,一个函数的活动记录用ebp(栈底指针寄存器)和esp(栈顶指针寄存器)这两个寄存器划定范围。esp寄存器始终指向栈的顶部,同时也就指向了当前函数的活动记录的顶部。而相对的,ebp的寄存器指向了函数活动记录的一个固定范围。