结构体传参,传递的是副本
结构体里面写函数,结构体的大小不变
函数的地址不在结构体里面。
类里面的函数都要传一个this指针,即
lea ecx,[s]
普通的函数结构体传参
this指针的特点
1、你用或者不用,它就在那里
2、参数个数确定的时候,用ecx来传递
3、参数个数不确定的时候,最后一个传递(参见不定长参数)
4、this指针不能做++ -- 等运算,不能重新被赋值.
5、this指针不占用结构体的宽度.
类的函数传参与普通函数的传参
struct st
{int x;int y;st(int x, int y){this->x = x;this->y = y;}int Add(){return this->x + this->y;}int Sub(){return this->x - this->y;}int Mul(){return this->x * this->y;}int Div(){return this->x / this->y;}
};
s.Add();
008F460B 8D 4D F0 lea ecx,[s]
008F460E E8 D0 CD FF FF call st::Add (08F13E3h)008F2F40 55 push ebp
008F2F41 8B EC mov ebp,esp
008F2F43 81 EC CC 00 00 00 sub esp,0CCh
008F2F49 53 push ebx
008F2F4A 56 push esi
008F2F4B 57 push edi
008F2F4C 51 push ecx
008F2F4D 8D 7D F4 lea edi,[ebp-0Ch]
008F2F50 B9 03 00 00 00 mov ecx,3
008F2F55 B8 CC CC CC CC mov eax,0CCCCCCCCh
008F2F5A F3 AB rep stos dword ptr es:[edi]
008F2F5C 59 pop ecx
008F2F5D 89 4D F8 mov dword ptr [this],ecx
008F2F60 B9 66 C0 8F 00 mov ecx,offset _570D0804_main@cpp (08FC066h)
008F2F65 E8 B6 E3 FF FF call @__CheckForDebuggerJustMyCode@4 (08F1320h)
return this->x + this->y;
008F2F6A 8B 45 F8 mov eax,dword ptr [this]
008F2F6D 8B 00 mov eax,dword ptr [eax]
008F2F6F 8B 4D F8 mov ecx,dword ptr [this]
008F2F72 03 41 04 add eax,dword ptr [ecx+4]
//ecx就是this指针,指向结构体第一个成员
普通函数
Add(&s);
005052CB 8D 45 F0 lea eax,[s]
005052CE 50 push eax
005052CF E8 05 C1 FF FF call Add (05013D9h)
005052D4 83 C4 04 add esp,4 005017D0 55 push ebp
005017D1 8B EC mov ebp,esp
005017D3 81 EC C0 00 00 00 sub esp,0C0h
005017D9 53 push ebx
005017DA 56 push esi
005017DB 57 push edi
005017DC 8B FD mov edi,ebp
005017DE 33 C9 xor ecx,ecx
005017E0 B8 CC CC CC CC mov eax,0CCCCCCCCh
005017E5 F3 AB rep stos dword ptr es:[edi]
005017E7 B9 66 C0 50 00 mov ecx,offset _570D0804_main@cpp (050C066h)
005017EC E8 2F FB FF FF call @__CheckForDebuggerJustMyCode@4 (0501320h) 35: return s->x + s->y;
005017F1 8B 45 08 mov eax,dword ptr [s]
005017F4 8B 00 mov eax,dword ptr [eax]
005017F6 8B 4D 08 mov ecx,dword ptr [s]
005017F9 03 41 04 add eax,dword ptr [ecx+4] 36: }
005017FC 5F pop edi
005017FD 5E pop esi
005017FE 5B pop ebx
005017FF 81 C4 C0 00 00 00 add esp,0C0h
00501805 3B EC cmp ebp,esp
00501807 E8 38 FA FF FF call __RTC_CheckEsp (0501244h)
0050180C 8B E5 mov esp,ebp
0050180E 5D pop ebp
0050180F C3 ret
普通函数外平栈,即调用约定为cdcall
类的函数内平栈,即调用约定为stdcall
空结构体的大小
为一
作业
1、设计一个结构体,有两个Int类型的成员X,Y 在结构体内部定义4个函数 分别实现对X Y的加法、减法、乘法与除法的功能. 2、观察这些函数调用的时候,与其他的函数调用有哪些不同? 从参数传递、压栈顺序、堆栈平衡来总结. 3、空结构体的大小是多少?为什么? 4、下面代码能否执行? struct Person
{ void Fn_1() { printf("Person:Fn_1()\n"); } void Fn_2() { printf("Person:Fn_2()%x\n"); }
}; int main(int argc, char* argv[])
{ Person* p = NULL; p->Fn_1(); p->Fn_2(); return 0;
} 4、下面代码能否执行? struct Person
{ int x ; void Fn_1() { printf("Person:Fn_1()\n"); } void Fn_2() { x = 10; printf("Person:Fn_2()%x\n"); }
}; int main(int argc, char* argv[])
{ Person* p = NULL; p->Fn_1(); p->Fn_2(); return 0;
}
调用成员函数add反汇编
39: t.add();
00401084 8D 4D F8 lea ecx,[ebp-8] *
00401087 E8 79 FF FF FF call @ILT+0(St::add) (00401005)00401100 55 push ebp
00401101 8B EC mov ebp,esp
00401103 83 EC 44 sub esp,44h
00401106 53 push ebx
00401107 56 push esi
00401108 57 push edi
00401109 51 push ecx *
0040110A 8D 7D BC lea edi,[ebp-44h]
0040110D B9 11 00 00 00 mov ecx,11h
00401112 B8 CC CC CC CC mov eax,0CCCCCCCCh
00401117 F3 AB rep stos dword ptr [edi]
00401119 59 pop ecx *
0040111A 89 4D FC mov dword ptr [ebp-4],ecx *这里将结构体的指针传入函数栈帧中
14: return this->X+this->Y;
0040111D 8B 45 FC mov eax,dword ptr [ebp-4]
00401120 8B 00 mov eax,dword ptr [eax]
00401122 8B 4D FC mov ecx,dword ptr [ebp-4]
00401125 03 41 04 add eax,dword ptr [ecx+4]
15: }
00401128 5F pop edi
00401129 5E pop esi
0040112A 5B pop ebx
0040112B 8B E5 mov esp,ebp
0040112D 5D pop ebp
0040112E C3 ret