1 . 函数参数传递
| 调用约定 | _cdecl | _stdcall | _fastcall | 
| 传参顺序 | 左->右 | 右->左 | 寄存器和堆栈传参 | 
| 平衡堆栈者 | 调用者 | 子程序 | 子程序 | 
int _cdecl Add(char a, long b, int c, int d)
{
return (a + b + c + d);
}
push 4 
push        3    
push        2    
push        1    
call        Add (1161A60h) 
add         esp,10h //调用者平衡堆栈
int _stdcall Add(char a, long b, int c, int d) { return (a + b + c + d); }
push 4 
push 3 
push 2 
push 1 
call Add (1161A60h) //子程序Add里面平衡堆栈
int _fastcall Add(char a, long b, int c, int d)
{
return (a + b + c + d);
}
push 4 
push        3    
mov         edx,2  //寄存器传参
mov         cl,1   //寄存器传参
call        Add (11F1A60h)  //子程序Add里面 平衡堆栈
_fastcall调用约定不同编译器传参不同:
1. MS VC: 最左边2个参数依次 ecx, edx
2. borland delphi/C++:最左边2个参数 eax, edx,ecx
3. watcom C: 最左边2个参数 eax, edx,ebx,ecx
4. 剩下的参数的全部esp传参
thiscall 也是寄存器传递参数, C++非静态成员函数的默认调用约定,
对象的每个成员函数隐含接受this指针。通过ecx传递this指针
class CSum
{
public:
int Add(int a, int b)
{
return (a + b);
}
};
void ClllDlg::OnBnClickedOk2()
{
CSum sum;
sum.Add(1, 2);
}
push 2 
push        1    
lea         ecx,[sum] 
call        CSum::Add (1221B10h) 
2. 函数返回值:
2.1函数返回值一般在eax中,如果返回值超过了eax容量,高32位存放在edx中
2.2.通过参数按传引用的方式返回值
以下代码就是通过参数按传引用的方式返回值
void max(int *a, int *b);
int main( )
{
	int a=5,b=6;
	max(&a, &b); 
	printf("a、b中较大的数是%d",a); //将最大的数显示出来
	return 0;
}
void max( int *a, int *b) 
{ 
	if(*a < *b)
		*a=*b; 		//经比较后,将较大的数放到a变量之中
}
3. 局部变量
3.1.利用堆栈存放局部变量,分配局部变量空间
| 形式1: | 形式2: | 形式3: | 
| sub esp, n add esp, n | add esp,-n sub esp, -n | push reg 
 | 
参数相对于 ebp是正的
局部变量相对于 esp是负的
3.2.利用寄存器存放局部变量
除了堆栈存放 局部变量外,6个通用寄存器也可以存放局部变量。
4. 全局变量
1. 全局变量一般存放在.data区块, 它是一个固定值,采用硬编码方式
mov         dword ptr [4944A0h],7     //4944A0h就是全部变量的地址
mov         eax,dword ptr [b] 
5. 数组
5.1. 数组是连续数据的集合,汇编下访问数组是基址+变量的形式访问
#include <stdio.h> int main(void) { static int a[3]={0x11,0x22,0x33}; int i,s=0,b[3]; for(i=0;i<3;i++) { s=s+a[i]; b[i]=s; } for(i=0;i<3;i++) { printf("%d\n",b[i]); } return 0; }
mov eax,dword ptr [i] 
mov         ecx,dword ptr [s] 
add         ecx,dword ptr a (493078h)[eax*4]//493078h数组基址
6.虚函数
虚函数是在程序运行时刻定义的函数, 虚函数的地址不能在编译时刻确定,所以虚函数引用
通常放在一个专有数组里-虚函数表(VTBL), 每一个虚函数对象都具有虚函数表指针(VPTR),
虚函数通过指向虚函数表的指针间接调用。
#include <stdio.h>
class CSum
{
public:
	virtual int Add(int a, int b) 
	{
		return(a + b);
	}
	virtual	int	Sub(int a, int b )
	{
		return(a - b);
	}
};
void main()
{   
	CSum*	pCSum = new CSum ;  
	pCSum->Add(1,2);
	pCSum->Sub(1,2);
} 
.text:00401000 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00401000 _main           proc near               ; CODE XREF: start+AFp
.text:00401000
.text:00401000 argc            = dword ptr  4
.text:00401000 argv            = dword ptr  8
.text:00401000 envp            = dword ptr  0Ch
.text:00401000
.text:00401000                 push    esi
.text:00401001                 push    4               
.text:00401003                 call    ??2@YAPAXI@Z    ;new为创建对象分配4个字节
.text:00401008                 add     esp, 4
.text:0040100B                 test    eax, eax
.text:0040100D                 jz      short loc_401019
.text:0040100F                 mov     dword ptr [eax], offset off_4050A0 ;将4050A0写入创建对象的实例中,4050A0是虚函数表的指针。
.text:00401015                 mov     esi, eax
.text:00401017                 jmp     short loc_40101B
.text:00401019 ; ---------------------------------------------------------------------------
.text:00401019
.text:00401019 loc_401019:                             ; CODE XREF: _main+Dj
.text:00401019                 xor     esi, esi
.text:0040101B
.text:0040101B loc_40101B:                             ; CODE XREF: _main+17j
.text:0040101B                 mov     eax, [esi]
.text:0040101D                 push    2
.text:0040101F                 push    1
.text:00401021                 mov     ecx, esi
.text:00401023                 call    dword ptr [eax]
.text:00401025                 mov     edx, [esi]
.text:00401027                 push    2
.text:00401029                 push    1
.text:0040102B                 mov     ecx, esi
.text:0040102D                 call    dword ptr [edx+4]
.text:00401030                 pop     esi
.text:00401031                 retn
.text:00401031 _main           endp
查看虚函数表 4050A0的数据 
004050A0  40 10 40 00 50 10 40 00  FF FF FF FF 2E 11 40 00  @.@.P.@.......@.
004050B0  42 11 40 00 5F 5F 47 4C  4F 42 41 4C 5F 48 45 41  B.@.__GLOBAL_HEA
VTBL的2组数据
[VTBL] = 401040h
[VTBL+4] = 401050h
进一步看看这2个指针的内容
sub_401040 proc near
arg_0= dword ptr  4
arg_4= dword ptr  8
mov     eax, [esp+arg_4]
mov     ecx, [esp+arg_0]
add     eax, ecx
retn    8
sub_401040 endp
sub_401050 proc near
arg_0= dword ptr  4
arg_4= dword ptr  8
mov     eax, [esp+arg_0]
mov     ecx, [esp+arg_4]
sub     eax, ecx
retn    8
sub_401050 endp
原来 虚函数是通过虚函数表的指针 间接调用
原文:http://www.cnblogs.com/mayingkun/p/6060410.html