【C/C++】总结常用的函数调用约定
一、函数调用的基本步骤
函数调用大致包括以下几个步骤。
(1)参数入栈:将参数从右向左依次压入系统栈中。
(2)返回地址入栈:将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行。
(3)代码区跳转:处理器从当前代码区跳转到被调用函数的入口处。
(4)栈帧调整:具体包括:
保存当前栈帧状态值,已备后面恢复本栈帧时使用(EBP入栈)。
将当前栈帧切换到新栈帧(将ESP值装入EBP,更新栈帧底部)。
给新栈帧分配空间(把ESP减去所需空间的大小,抬高栈顶)。
二、函数调用约定:
调用约定的声明
参数入栈顺序
恢复栈平衡的位置
__cdecl
右→左
母函数
__fastcall
右→左
子函数
__stdcall
右→左
子函数
三、具体的表现
(1) __cdecl
函数本身不清理堆栈,调用者负责清理堆栈。由于这种变化,C调用约定允许函数的参数的个数是不固定的
(2) __fastcall
函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压栈
被调用函数清理堆栈
(3) __stdcall
参数从右向左压入堆栈
函数自身修改堆栈
四、VC下的表现
在VC的工程设置中可以设置函数调用方式,从表现可以看出明显的差别。
(1)如果设置成__cdecl*,那么对于下面的代码,汇编表现为:
00402692 push 8
00402694 push 5
00402696 push 3
00402698 call @ILT+275(GetNum) (00401118)
0040269D add esp,0Ch
(2)如果设置成__stdcall,那么对于下面的代码,汇编表现为:
00402692 push 8
00402694 push 5
00402696 push 3
00402698 call @ILT+280(GetNum) (0040111d)
(3)如果设置成__fastcall,那么对于下面的代码,汇编表现为:
00402692 push 8
00402694 mov
相关文档:
系统环境:Windows 7
软件环境:Visual C++ 2008 SP1 +SQL Server 2005
本次目的:编写一个航空管理系统
这是数据库课程设计的成果,虽然成绩不佳,但是作为我用VC++ 以来编写的最大程序还是传到网上,以供参考。用VC++ 做数据库设计并不容易,但也不是不可能。以下是我的程序界面,后面 ......
Boss说,要看OpenGL,看了快一个月,总算出了个像样的东西,用C写了个3D迷宫,
虽然只有350行
代码,不过边学边写,足足写了一周时间,还是小有成就感的,活活活!
&n ......
预备知识—程序的内存分配
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 ......
C及传统C++
#include <assert.h> //设定插入点
#include <ctype.h> //字符处理
#include <errno.h> //定义错误码
#include <float.h> //浮点数处理
#include <fstream.h> //文件输入/输出
#include <iomanip.h> //参数化输入/输出 ......