1,大致分为传值和传地址,不过总体说来都是传值,地址也是一种数值。
传递参数都是拷贝数据进行传递的。这是编译器以及函数调用约定决定的。
首先了解一下主要的函数调用约定
__stdcall,__cdecl,__fastcall,__thiscall,__nakedcall,__pascal
1.从右到左依次入栈:__stdcall,__cdecl,__thiscall
2.从左到右依次入栈:__pascal,__fastcall
(1)__cdecl调用约定
1、参数是从右向左传递的,也是放在 堆栈 中。 2、堆栈平衡是由调用函数来执行的(在call B,之后会有add esp x,x表示参数的字节数)。 3、函数的前面会加一个前缀_(_sumExample) 下面来看看具体的反汇编代码,这是从VC反汇编的代码截取的一部分代码。10: int c = 0;
00401088 C7 45 FC 00 00 00 00 mov dword ptr [ebp-4],0 11: c = sumExample(2, 3); 0040108F 6A 03 push 3 00401091 6A 02 push 2 从上面的两个push操作我们就可以知道参数是从右向左传递的了。另外这里也回答前面的问题为什么参数会被扩展为4个字节,因为堆栈的操作都是对一个字进行操作的,所以参数都是4个字节的。 00401093 E8 7C FF FF FF call @ILT+15(_Max) (00401014) 这里就是调用函数操作了。在进行call操作之后,会自动将call的下一条语句作为函数的返回地址保存在栈中,也就是下面的(00401098)。在地址00401014处我们可以看到这样的一小段代码 @ILT+0(_Max): 00401005 E9 26 00 00 00 jmp _sumExample (00401030) 这里就可以知道程序在编译之后会在函数前面加上前缀_ 00401098 83 C4 08 add esp,8 这里就是平衡堆栈操作了。可以看出是在调用者进行的。 0040109B 89 45 FC mov dword ptr [ebp-4],eax 保存值是由eax寄存器返回的,从这里就可以看出了。 12: 13: return 0; 0040109E 33 C0 xor eax,eax 14: } 3: int __cdecl sumExample(int a, int b) 4: { <