【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
相关文档:
其实VIM也能把编译 调试集成在一起,像是一个IDE一样。
首先现在VIM的源码,因为要集成调试环境的话需要重新编译VIM才行,所以我们不如重新安装一个。
VIM的现在地址:
http://www.vim.org/sources.php
然后下载VIMGDB,这是vim的集成调试环境的一个重要插件程序。
地址:http://sourceforge.net/projects/clewn/files ......
原文:http://blog.csdn.net/jackyvan/archive/2010/01/15/5193693.aspx
其实VIM也能把编译 调试集成在一起,像是一个IDE一样。
首先现在VIM的源码,因为要集成调试环境的话需要重新编译VIM才行,所以我们不如重新安装一个。
VIM的现在地址:
http://www.vim.org/sources.php
然后下载VIMGDB,这是vim的集成调试环境的 ......
C及传统C++
#include <assert.h> //设定插入点
#include <ctype.h> //字符处理
#include <errno.h> //定义错误码
#include <float.h> //浮点数处理
#include <fstream.h> //文件输入/输出
#include <iomanip.h> //参数化输入/输出 ......