如果返回的是一个struct对象,return 语句会如何做呢?下面是测试代码
- #include <iostream>
- using namespace std;
- struct Big
- {
- char buf[100];
- int i;
- long d;
- }B,B2;
- Big bigfun(Big b)
- {
- b.i=100;
- return b;
- }
- int main()
- {
- B2=bigfun(B);
- return 0;
- }
在main开头和结尾设断点
- 8: int main()
- 19: {
- 004012A0 push ebp
- 004012A1 mov ebp,esp
- 004012A3 sub esp,118h
- //一开始对这迷惑不解,分析了好久
- //原来(118h-40h)剩下的内存块存放了两个Big的变量
- //低地址放Bigfun()函数返回值的临时变量
- //高地址放B2.operator=(Big &) 的参数
- 004012A9 push ebx
- 004012AA push esi
- 004012AB push edi
- 004012AC lea edi,[ebp-118h]
- 004012B2 mov ecx,46h
- 004012B7 mov eax,0CCCCCCCCh
- 004012BC rep stos dword ptr [edi]
- 20: B2=bigfun(B);
- 004012BE sub esp,6Ch//b参数入栈
- 004012C1 mov ecx,1Bh
- 004012C6 mov esi,offset B (00438490)//B的首地址
- 004012CB mov edi,esp
- 004012CD rep movs dword ptr [edi],dword ptr [esi]//上面这些指令完成对b的初始化工作
- 004012CF lea eax,[ebp-0D8h]//eax存放Big类型一个返回值临时变量的首地址
- 004012D5 push eax//注意一般栈调用没有这条指令
- 004012D6 call @ILT+0(bigfun) (00401005)
- /*
- 004012DB add esp,70h
- 004012DE mov esi,eax
- 004012E0 mov ecx,1Bh
- 004012E5 lea edi,[ebp-6Ch]
- 004012E8 rep movs dword ptr [edi],dword ptr [esi]
- 004012EA mov ecx,1Bh
- 004012EF lea esi,[ebp-6Ch]
- 004012F2 mov edi,offset B2 (00438500)
- 004012F7 rep movs dword ptr [edi],dword ptr [esi]
- 21:
- 22: return 0;
- 004012F9 xor eax,eax
- 23:
- 24: }
- 004012FB pop edi
- 004012FC pop esi
- 004012FD pop ebx
- 004012FE add esp,118h
- 00401304 cmp ebp,esp
- 00401306 call __chkesp (004081e0)
- 0040130B mov esp,ebp
- 0040130D pop ebp
- 0040130E ret
- */
- @ILT+0(?bigfun@@YA?AUBig@@U1 @@Z):
- 00401005 jmp bigfun (00401250)
- 11: Big bigfun(Big b)
- 12: {
- 00401250 push ebp
- 00401251 mov ebp,esp
- 00401253 sub esp,40h
- 00401256 push ebx
- 00401257 push esi
- 00401258 push edi
- 00401259 lea edi,[ebp-40h]
- 0040125C mov ecx,10h
- 00401261 mov eax,0CCCCCCCCh
- 00401266 rep stos dword ptr [edi]
- 13: b.i=100;
- 00401268 mov dword ptr [ebp+70h],64h
- /*
- 0012FE50 00 00 00 00 64 00 00 00 00 00 00 00
- */
- 14: return b;
- 0040126F mov ecx,1Bh
- 00401274 lea esi,[ebp+0Ch]//esi=b的首地址
- 00401277 mov edi,dword ptr [ebp+8]//edi=返回值临时变量的首地址
- 0040127A rep movs dword ptr [edi],dword ptr [esi]
- 0040127C mov eax,dword ptr [ebp+8]
- 15: }
- 0040127F pop edi
- 00401280 pop esi
- 00401281 pop ebx
- 00401282 mov esp,ebp
- 00401284 pop ebp
- 00401285 ret
- 返回到main函数
- 004012DB add esp,70h//销毁局部参数
- 004012DE mov esi,eax//bigfunction()返会值临时变量的首地址
- 004012E0 mov ecx,1Bh
- 004012E5 lea edi,[ebp-6Ch]//B2.operator=(Big &)参数的首地址
- 004012E8 rep movs dword ptr [edi],dword ptr [esi]
- 004012EA mov ecx,1Bh
- 004012EF lea esi,[ebp-6Ch]
- 004012F2 mov edi,offset B2 (00438500)//B2的首地址
- 004012F7 rep movs dword ptr [edi],dword ptr [esi]
- 21:
- 22: return 0;
- 004012F9 xor eax,eax
- 23:
- 24: }
- 004012FB pop edi
- 004012FC pop esi
- 004012FD pop ebx
- 004012FE add esp,118h
- 00401304 cmp ebp,esp
- 00401306 call __chkesp (004081e0)
- 0040130B mov esp,ebp
- 0040130D pop ebp
- 0040130E ret
总结:
1.一般function frame的结构是
函数内局部变量
ebp
eip
函数参数
如果返回值是一个struct对象function frame
函数内局部变量
ebp
eip
返回值临时变量的首地址//特别注意这个
函数参数
(由于寄存器太小,不可能放一块struct内存,所以保存了临时变量的首地址).
2.struct对象的临时变量是在栈上的,而不是在堆上.