Author:bakari Date:2012.11.2
1、参数传递问题:
< 1 >、堆栈传参
< 2 >、寄存器传参(利用通用寄存器进行函数参数传递的方法)
< 3 >、全局变量或静态变量传参
2、 Call Convention(函数调用约定)
< 1 >、_cdecl
a、 参数从右向左压入堆栈
b、 函数被调用者修改堆栈
c、 在win32应用程序里,宏APIENTRY,WINAPI,都表示_stdcall,非常常见.
d、 C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。
< 2 >、_stdcall
a、 压栈方式与_cdecl一样,与之不一样的是堆栈的平衡不是由函数调用者完成,而是自身完成,在退出时自己清空堆栈。
b、 此种方式在函数返回是以 ret 8 指令来平衡堆栈,此处:ret 8 = add esp , 8。
< 3 >、上两种方式最为常用,此外还有fastcall ,thiscall, naked call,_pascal等 _pascal 入栈方式是从左到右。
下面通过一些例子来深入理解。
3、 跟踪汇编代码看函数参数的调用机制 我们看这样一个简单的函数,
编译器翻译的汇编指令如下:
< 1 >、void Test1(){}
据此画出内存布局图为:
< 2 >、有参数的情况
内存布布局如下:
4、 编写裸函数(不让系统加汇编的代码,而是人为的加上去)
比如:
在main函数调用的结果printf("%d\n", MyFunc());
练习:
< 1 >、无参数的情况(不在堆栈上展开)
< 2 >、有参数的情况(在堆栈上展开)