c++ 函数的工作原理
目录
- 函数传参
- 结构体作为函数的返回值
1:函数传参
1 int Add(int a,int b)
2 {
3 return a+b;
4 }
2 {
3 return a+b;
4 }
反汇编代码
30: int i = Add(5,6);
00401078 push 6 ; 参数入栈
0040107A push 5 ; 参数入栈
0040107C call @ILT+5(Add) (0040100a)
00401081 add esp,8 ;由于push2个参数,esp-8,所以这里esp+8,平衡栈。
00401084 mov dword ptr [ebp-4],eax ;eax为函数的返回值
00401078 push 6 ; 参数入栈
0040107A push 5 ; 参数入栈
0040107C call @ILT+5(Add) (0040100a)
00401081 add esp,8 ;由于push2个参数,esp-8,所以这里esp+8,平衡栈。
00401084 mov dword ptr [ebp-4],eax ;eax为函数的返回值
此时内存中栈的内容
0012FF24 81 10 40 00 ..@. ;Call的下一条指令的内存地址
0012FF28 05 00 00 00 .... ;参数5
0012FF2C 06 00 00 00 .... ;参数6
0012FF30 00 00 92 7C
0012FF28 05 00 00 00 .... ;参数5
0012FF2C 06 00 00 00 .... ;参数6
0012FF30 00 00 92 7C
Add函数
00401030 push ebp ; 保存ebp
00401031 mov ebp,esp ; 赋值 ebp=esp ,ebp作为栈底
00401033 sub esp,40h ; 抬高栈,开辟40h个空间
00401036 push ebx ;ebx 入栈
00401037 push esi ;esi 入栈
00401038 push edi ; edi 入栈
00401039 lea edi,[ebp-40h] ;初始化栈40h为C
0040103C mov ecx,10h
00401041 mov eax,0CCCCCCCCh
00401046 rep stos dword ptr [edi]
8: return a+b;
00401048 mov eax,dword ptr [ebp+8] ;取出参数5
0040104B add eax,dword ptr [ebp+0Ch]; 取出参数6,返回值放在eax中
00401031 mov ebp,esp ; 赋值 ebp=esp ,ebp作为栈底
00401033 sub esp,40h ; 抬高栈,开辟40h个空间
00401036 push ebx ;ebx 入栈
00401037 push esi ;esi 入栈
00401038 push edi ; edi 入栈
00401039 lea edi,[ebp-40h] ;初始化栈40h为C
0040103C mov ecx,10h
00401041 mov eax,0CCCCCCCCh
00401046 rep stos dword ptr [edi]
8: return a+b;
00401048 mov eax,dword ptr [ebp+8] ;取出参数5
0040104B add eax,dword ptr [ebp+0Ch]; 取出参数6,返回值放在eax中
0040104E pop edi
0040104F pop esi
00401050 pop ebx
00401051 mov esp,ebp
00401053 pop ebp
00401054 ret
0040104F pop esi
00401050 pop ebx
00401051 mov esp,ebp
00401053 pop ebp
00401054 ret
栈的内存
00401030 push ebp ; 保存ebp
00401031 mov ebp,esp ; 赋值 ebp=esp ,ebp作为栈底,ebp = 12ff20
00401031 mov ebp,esp ; 赋值 ebp=esp ,ebp作为栈底,ebp = 12ff20
0012FF20 80 FF 12 00 .... ;12ff80是ebp的值,(ebp)
0012FF24 81 10 40 00 ..@. +4
0012FF28 05 00 00 00 .... +8
0012FF2C 06 00 00 00 .... +12
0012FF30 00 00 92 7C
0012FF24 81 10 40 00 ..@. +4
0012FF28 05 00 00 00 .... +8
0012FF2C 06 00 00 00 .... +12
0012FF30 00 00 92 7C
00401048 mov eax,dword ptr [ebp+8] ;取出参数5
0040104B add eax,dword ptr [ebp+0Ch]; 取出参数6;
0040104B add eax,dword ptr [ebp+0Ch]; 取出参数6;
[ebp+8] = 05
[ebp+C] = 06
2. 结构体作为函数的返回值
测试代码:
struct tagTest{
int m_One ;
int m_Two;
int m_Three;
int m_Four;
};
tagTest RerStruct()
{
tagTest testRet;
testRet.m_One = 1;
testRet.m_Two = 2;
testRet.m_Three = 3;
testRet.m_Four = 4;
return testRet;
}
int m_One ;
int m_Two;
int m_Three;
int m_Four;
};
tagTest RerStruct()
{
tagTest testRet;
testRet.m_One = 1;
testRet.m_Two = 2;
testRet.m_Three = 3;
testRet.m_Four = 4;
return testRet;
}
反汇编代码:
30: tagTest test;
31: test = RerStruct();
00401078 lea eax,[ebp-30h] ;把ebp-30h的地址压入栈,函数的结构体赋值时候用
0040107B push eax
0040107C call @ILT+0(RerStruct) (00401005) ;执行完函数,此时ebp-30h上就完成了结构体返回值的拷贝
00401081 add esp,4 ;平衡堆栈
00401084 mov ecx,dword ptr [eax]
00401086 mov dword ptr [ebp-20h],ecx ;这里创建一个临时的结构体
00401089 mov edx,dword ptr [eax+4] ; 位对位的copy
0040108C mov dword ptr [ebp-1Ch],edx
0040108F mov ecx,dword ptr [eax+8]
00401092 mov dword ptr [ebp-18h],ecx
00401095 mov edx,dword ptr [eax+0Ch]
00401098 mov dword ptr [ebp-14h],edx
0040109B mov eax,dword ptr [ebp-20h]
0040109E mov dword ptr [ebp-10h],eax ;赋值给test
004010A1 mov ecx,dword ptr [ebp-1Ch]
004010A4 mov dword ptr [ebp-0Ch],ecx
004010A7 mov edx,dword ptr [ebp-18h]
004010AA mov dword ptr [ebp-8],edx
004010AD mov eax,dword ptr [ebp-14h]
004010B0 mov dword ptr [ebp-4],eax
31: test = RerStruct();
00401078 lea eax,[ebp-30h] ;把ebp-30h的地址压入栈,函数的结构体赋值时候用
0040107B push eax
0040107C call @ILT+0(RerStruct) (00401005) ;执行完函数,此时ebp-30h上就完成了结构体返回值的拷贝
00401081 add esp,4 ;平衡堆栈
00401084 mov ecx,dword ptr [eax]
00401086 mov dword ptr [ebp-20h],ecx ;这里创建一个临时的结构体
00401089 mov edx,dword ptr [eax+4] ; 位对位的copy
0040108C mov dword ptr [ebp-1Ch],edx
0040108F mov ecx,dword ptr [eax+8]
00401092 mov dword ptr [ebp-18h],ecx
00401095 mov edx,dword ptr [eax+0Ch]
00401098 mov dword ptr [ebp-14h],edx
0040109B mov eax,dword ptr [ebp-20h]
0040109E mov dword ptr [ebp-10h],eax ;赋值给test
004010A1 mov ecx,dword ptr [ebp-1Ch]
004010A4 mov dword ptr [ebp-0Ch],ecx
004010A7 mov edx,dword ptr [ebp-18h]
004010AA mov dword ptr [ebp-8],edx
004010AD mov eax,dword ptr [ebp-14h]
004010B0 mov dword ptr [ebp-4],eax
call @ILT+0(RerStruct)
20: tagTest testRet;
21: testRet.m_One = 1;
0040D7C8 mov dword ptr [ebp-10h],1
22: testRet.m_Two = 2;
0040D7CF mov dword ptr [ebp-0Ch],2
23: testRet.m_Three = 3;
0040D7D6 mov dword ptr [ebp-8],3
24: testRet.m_Four = 4;
0040D7DD mov dword ptr [ebp-4],4
25: return testRet;
0040D7E4 mov eax,dword ptr [ebp+8] ; 取出前面压入栈的eax
0040D7E7 mov ecx,dword ptr [ebp-10h] ;位对位的copy
0040D7EA mov dword ptr [eax],ecx
0040D7EC mov edx,dword ptr [ebp-0Ch]
0040D7EF mov dword ptr [eax+4],edx
0040D7F2 mov ecx,dword ptr [ebp-8]
0040D7F5 mov dword ptr [eax+8],ecx
0040D7F8 mov edx,dword ptr [ebp-4]
0040D7FB mov dword ptr [eax+0Ch],edx
0040D7FE mov eax,dword ptr [ebp+8]
21: testRet.m_One = 1;
0040D7C8 mov dword ptr [ebp-10h],1
22: testRet.m_Two = 2;
0040D7CF mov dword ptr [ebp-0Ch],2
23: testRet.m_Three = 3;
0040D7D6 mov dword ptr [ebp-8],3
24: testRet.m_Four = 4;
0040D7DD mov dword ptr [ebp-4],4
25: return testRet;
0040D7E4 mov eax,dword ptr [ebp+8] ; 取出前面压入栈的eax
0040D7E7 mov ecx,dword ptr [ebp-10h] ;位对位的copy
0040D7EA mov dword ptr [eax],ecx
0040D7EC mov edx,dword ptr [ebp-0Ch]
0040D7EF mov dword ptr [eax+4],edx
0040D7F2 mov ecx,dword ptr [ebp-8]
0040D7F5 mov dword ptr [eax+8],ecx
0040D7F8 mov edx,dword ptr [ebp-4]
0040D7FB mov dword ptr [eax+0Ch],edx
0040D7FE mov eax,dword ptr [ebp+8]
这里有个疑问,为什么还要多创建一个临时的结构体?
此时栈中有3个结构体 ebp-30 ebp-20 ebp-10
0012FF50 01 00 00 00 ....
0012FF54 02 00 00 00 ....
0012FF58 03 00 00 00 ....
0012FF5C 04 00 00 00 ....
0012FF60 01 00 00 00 ....
0012FF64 02 00 00 00 ....
0012FF68 03 00 00 00 ....
0012FF6C 04 00 00 00 ....
0012FF70 01 00 00 00 ....
0012FF74 02 00 00 00 ....
0012FF78 03 00 00 00 ....
0012FF7C 04 00 00 00
0012FF54 02 00 00 00 ....
0012FF58 03 00 00 00 ....
0012FF5C 04 00 00 00 ....
0012FF60 01 00 00 00 ....
0012FF64 02 00 00 00 ....
0012FF68 03 00 00 00 ....
0012FF6C 04 00 00 00 ....
0012FF70 01 00 00 00 ....
0012FF74 02 00 00 00 ....
0012FF78 03 00 00 00 ....
0012FF7C 04 00 00 00
学习,积累中......