【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
相关文档:
Boss说,要看OpenGL,看了快一个月,总算出了个像样的东西,用C写了个3D迷宫,
虽然只有350行
代码,不过边学边写,足足写了一周时间,还是小有成就感的,活活活!
&n ......
随机生成整数,然后算出正负零
void getrand(int *a, int m)
{
int i;
srand(time(NULL));
for (i=0; i<m; i++)
{
a = rand()-rand();
}
}
int main(int argc, char* argv[])
{
  ......
原文:http://blog.csdn.net/jackyvan/archive/2010/01/15/5193693.aspx
其实VIM也能把编译 调试集成在一起,像是一个IDE一样。
首先现在VIM的源码,因为要集成调试环境的话需要重新编译VIM才行,所以我们不如重新安装一个。
VIM的现在地址:
http://www.vim.org/sources.php
然后下载VIMGDB,这是vim的集成调试环境的 ......
字符输入输出:
aa = getchar();
putchar(a);
格式输出:
printf(格式控制, 输出表列);
%d 十进制数 %md m为指定的宽度 若数据位数小于m,则左端补以空格;若大于m,则按实际位数输出
%ld 长整型数据 %mld 指定字段宽度
%o 八进制整数形式 %mo
%x 十六进制整数形式 %m ......
C及传统C++
#include <assert.h> //设定插入点
#include <ctype.h> //字符处理
#include <errno.h> //定义错误码
#include <float.h> //浮点数处理
#include <fstream.h> //文件输入/输出
#include <iomanip.h> //参数化输入/输出 ......