函数调用

Stack

函数生存在栈空间。其生长方向与堆空间的生长方向相反。
一次函数调用占用的一块连续空间,被称为栈帧stack frame,代表一个还未返回的函数调用。
Call Stack 由 Stack Frames 组成


void f(){  g(); }
void g(){  h(); }
void main(){ f(); }

+---------------+  高地址
|  main() 栈帧  |
+---------------+
|    f() 栈帧   |
+---------------+
|    g() 栈帧   |
+---------------+
|    h() 栈帧   | <- 当前正在执行的函数
+---------------+
|               |
| 未使用的栈    |
 
~               ~  
| 未使用的堆     |
|               |
| 已分配的堆     | <- 例如:new int[100];分配出去的内存
+---------------+
|     其它      | 低地址

现实中有很多这样的例子:两头掘进施工的山洞,施工快的一个分队掘进总距离就最长。
如果两队同向掘进,A队从起点,B队从1/2路程开始,则任何分队完成任务后都无法帮助另一个分队。

Calling Conventions

关于函数怎么调用,怎么返回,怎么传递参数,怎么使用栈帧的约定。

Activation Frame

当前活动帧位于栈顶部。它对应的函数h()执行时面对的一片自由的大海,剩余未使用栈空间全属于它。
意思就是当前函数h(),无需担心在执行代码分配栈空间时,会侵犯其它函数栈的地盘。
而g()帧,f()帧暂时被关押在栈的内部,他们的执行状态被保存在栈帧,等待恢复执行。
一般来说,只有活动帧中知道底层帧的变量指针或引用,才能修改非活动帧中的变量。
显然,底层帧的生存期大于上层的帧。当g()调用h()时,g()中变量的生存期长,h()变量的生存期短。

栈帧的范围

由%EBP和%ESP这两个寄存器确定范围

BP ( base pointer ) 寄存器,记录栈帧的位置,因此也称为Frame Pointer。
它的用途在于追踪和计算函数参数和局部变量等的位置。这些参数肯定不能用绝对地址,而要用相对地址。
相对地址的基础锚位就着落在%EBP值上。此寄存器的值是需要明确的指定和修改的,例如:mov %EBP, XXX

SP ( stack poinger ) 寄存器。
用于追踪帧顶位置,当活动函数需要分配局部变量等栈内存要求时,需要在%ESP基础上取。
很多指令会修改此寄存器,例如:PUSH 123; 等价于
sub %esp, 4     ; esp指针减去4字节,就是占用栈空间4字节
mov [%esp], 123 ; 把123拷贝到[esp]指向的内存

IP ( instruction pointer ) 寄存器。
存储了当前指令

参考:http://www.unixwiz.net/techtips/win32-callconv-asm.html


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值