06. 函数栈

函数设计原则:高内聚,低耦合

内聚:所需资源自给自足,不依赖其他资源,重用性强,维护容易

责任清晰,容易移植到其他工程所需模块中

耦合:资源相互依赖,单一模块无法完成单一功能,重用性差,维护困难

责任不清晰,难以移植到其他工程所需模块中

函数调用时:

1.需要维护一个栈结构用于记录函数调用依赖关系

2.按调用约定传参

调用者caller

被调用者callee

调用约定主要约以下内容:

参数的传递顺序

参数的存储媒介(栈或寄存器)

谁负责释放参数空间(有且仅有一方实施)

返回值的存储媒介(栈或寄存器)

__cdecl:

函数参数从右往左传递

使用栈传递参数

caller负责释放参数空间

返回值在寄存器

__stdcall:

函数参数从右往左传递

使用栈传递参数

callee负责释放参数空间

返回值在寄存器

__fastcall:

左数前2个参数用寄存器传递,其余参数使用栈从右往左传递

callee释放参数空间

返回值在寄存器

3.保存返回地址

4.保存caller的栈底

5.更新当前栈底到callee的栈位置

6.为局部变量分配空间

7.保存其他受影响的寄存器(3个)

*8.编译选项/ZI /Zi会把局部变量的空间初始化为0xcccccccc(烫烫)

9.执行函数体

10.恢复保存的寄存器

11.释放局部变量占的空间

12.还原caller的栈底

13A. 如果是__fastcall__stdcall,取出返回地址并按此更新流程。则由callee释放占空间

13B. 如果是__cdelc,取出返回地址并按此更新流程,这时流程回到caller

14.如果是__cdelc,则由caller释放栈空间

 

 

一个函数栈大概样子:

保存的寄存器

局部变量

Caller的栈底

返回地址

参数

猜你喜欢

转载自www.cnblogs.com/Nutshelln/p/12662133.html