env:
g++-4.6.real (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Ubuntu/Linaro x86 32bit
看了
ptt [問題] 關於Class指標的觀念 系列的文章讓我想
知道 member function pointer 有什麼不一樣的地方。
c.cpp non-virtual member funcion
1 #include <cstdio>
2
3 using namespace std ;
4
5 struct A {
6 void func ( )
7 {
8 printf ( "i: %d\n " , i_ ) ;
9 }
10 void inc ( )
11 {
12 + + i_ ;
13 }
14 A ( )
15 {
16 i_ = 10 ;
17 }
18 private :
19 int i_ ;
20 } ;
21
22 typedef void ( A : : * MF ) ( ) ;
23
24 int main ( )
25 {
26
27 void ( A : : * p ) ( ) = & A : : func ;
28 A a ;
29 A aa ;
30 ( a .* p ) ( ) ;
31 a .inc ( ) ;
32
33 MF mf = & A : : func ;
34
35 unsigned int addr = * ( ( unsigned int * ) & p ) ;
36
37 ( * ( void ( * ) ( ) ) ( addr ) ) ( ) ;
38 ( * ( void ( * ) ( A * ) ) ( addr ) ) ( & aa ) ;
39 aa .func ( ) ;
40
41 ( MF ) addr ;
42
43
44
45
46
47 #if 1
48 printf ( "p: %p\n " , p ) ;
49 printf ( "addr: %x\n " , addr ) ;
50 #endif
51 return 0 ;
52 }
http://www.parashift.com/c++-faq-lite/cant-cvt-memfnptr-to-voidptr.html
看來無法將 void* 轉 member function pointer。
我用的方法其實是把 member function 當成 non member function, 再把 this 傳進去。
那麼為什麼不能轉?
void (A::*p)() = &A::func;
這個指標 assign 的動作原來有兩個部份, non-virtual function
剛好 可以這樣作。
non-virtual member function:
80486d1: c7 44 24 14 b4 86 04 movl $0x80486b4,0x14(%esp)
80486d8: 08
80486d9: c7 44 24 18 00 00 00 movl $0x0,0x18(%esp)
80486e0: 00
virtual member function:
804873f: c7 44 24 14 01 00 00 movl $0x1,0x14(%esp)
8048746: 00
8048747: c7 44 24 18 00 00 00 movl $0x0,0x18(%esp)
804874e: 0
ref 2 提到:
(&a)->func()
被 c++ 編譯器轉成
(*a->vptr[1])(&a)
只討論 virtual member function, 這個 member function pointer 只存了 1 和 0 這兩個值, 想靠著 1, 0 這兩個資料去找到 A::func() 是不可能的, 所以就算你想了很多辦法轉型成功, 還是得要拿到 virtual table 進而找到 A::func(), 找到 A::func() 的位址還怕不能執行嗎?
c.cpp virtual member funcion
1 #include <iostream>
2 #include <cstdio>
3
4 using namespace std ;
5
6 struct A
7 {
8 virtual void func ( )
9 {
10 printf ( "i: %d\n " , i_ ) ;
11 }
12 void inc ( )
13 {
14 + + i_ ;
15 }
16 A ( )
17 {
18 i_ = 10 ;
19 }
20 private :
21 int i_ ;
22 } ;
23
24
25 int main ( )
26 {
27 void ( A : : * p ) ( ) = & A : : func ;
28
29 //cout << "sizeof: " << sizeof(p) << endl;
30
31 //cout << "sizeof: " << sizeof(A) << endl;
32
33 //printf("addr: %p\n", p);
34 //cout << "p:" << p << endl;
35 //unsigned int addr = pp;
36 //printf("addr: %p\n", pp);
37
38
39 A a ;
40 ( a .* p ) ( ) ;
41
42 unsigned int vptr_addr = * ( unsigned int * ) & a ;
43 cout < < "vptr_addr:" < < hex < < vptr_addr < < endl ;
44
45 unsigned int func_addr = * ( unsigned int * ) vptr_addr ;
46 cout < < "func_addr:" < < hex < < func_addr < < endl ;
47 a .inc ( ) ;
48 ( * ( void ( * ) ( A * ) ) ( func_addr ) ) ( & a ) ;
49
50 A aa ;
51 ( * ( void ( * ) ( A * ) ) ( func_addr ) ) ( & aa ) ;
52
53 ( * ( void ( * ) ( A * ) ) ( func_addr ) ) ( & a ) ;
54
55 ( * ( void ( * ) ( A * ) ) ( func_addr ) ) ( & aa ) ;
56
57 return 0 ;
58 }
g++ -g -m32 c.cpp -o c
ideone 執行結果:
http://ideone.com/KLP0gG
objdump -Sd c
1
2 c: file format elf32-i386
3
4
5 Disassembly of section .init:
6
7 08048578 <_init>:
8 8048578: 53 push %ebx
9 8048579: 83 ec 08 sub $0x8,%esp
10 804857c: e8 00 00 00 00 call 8048581 <_init+0x9>
11 8048581: 5b pop %ebx
12 8048582: 81 c3 73 1a 00 00 add $0x1a73,%ebx
13 8048588: 8b 83 fc ff ff ff mov -0x4(%ebx),%eax
14 804858e: 85 c0 test %eax,%eax
15 8048590: 74 05 je 8048597 <_init+0x1f>
16 8048592: e8 39 00 00 00 call 80485d0 <__gmon_start__@plt>
17 8048597: e8 64 01 00 00 call 8048700 <frame_dummy>
18 804859c: e8 df 04 00 00 call 8048a80 <__do_global_ctors_aux>
19 80485a1: 83 c4 08 add $0x8,%esp
20 80485a4: 5b pop %ebx
21 80485a5: c3 ret
22
23 Disassembly of section .plt:
24
75
76 08048650 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@plt>:
77 8048650: ff 25 24 a0 04 08 jmp *0x804a024
78 8048656: 68 48 00 00 00 push $0x48
79 804865b: e9 50 ff ff ff jmp 80485b0 <_init+0x38>
80
81 08048660 <_ZNSolsEPFRSt8ios_baseS0_E@plt>:
82 8048660: ff 25 28 a0 04 08 jmp *0x804a028
83 8048666: 68 50 00 00 00 push $0x50
84 804866b: e9 40 ff ff ff jmp 80485b0 <_init+0x38>
85
86 Disassembly of section .text:
87
117
118 080486a0 <__do_global_dtors_aux>:
119 80486a0: 55 push %ebp
120 80486a1: 89 e5 mov %esp,%ebp
121 80486a3: 53 push %ebx
122 80486a4: 83 ec 04 sub $0x4,%esp
123 80486a7: 80 3d 0c a1 04 08 00 cmpb $0x0,0x804a10c
124 80486ae: 75 3f jne 80486ef <__do_global_dtors_aux+0x4f>
125 80486b0: a1 10 a1 04 08 mov 0x804a110,%eax
126 80486b5: bb 08 9f 04 08 mov $0x8049f08,%ebx
127 80486ba: 81 eb 04 9f 04 08 sub $0x8049f04,%ebx
128 80486c0: c1 fb 02 sar $0x2,%ebx
129 80486c3: 83 eb 01 sub $0x1,%ebx
130 80486c6: 39 d8 cmp %ebx,%eax
131 80486c8: 73 1e jae 80486e8 <__do_global_dtors_aux+0x48>
132 80486ca: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
133 80486d0: 83 c0 01 add $0x1,%eax
134 80486d3: a3 10 a1 04 08 mov %eax,0x804a110
135 80486d8: ff 14 85 04 9f 04 08 call *0x8049f04(,%eax,4)
136 80486df: a1 10 a1 04 08 mov 0x804a110,%eax
137 80486e4: 39 d8 cmp %ebx,%eax
138 80486e6: 72 e8 jb 80486d0 <__do_global_dtors_aux+0x30>
139 80486e8: c6 05 0c a1 04 08 01 movb $0x1,0x804a10c
140 80486ef: 83 c4 04 add $0x4,%esp
141 80486f2: 5b pop %ebx
142 80486f3: 5d pop %ebp
143 80486f4: c3 ret
144 80486f5: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
145 80486f9: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
146
147 08048700 <frame_dummy>:
148 8048700: 55 push %ebp
149 8048701: 89 e5 mov %esp,%ebp
150 8048703: 83 ec 18 sub $0x18,%esp
151 8048706: a1 0c 9f 04 08 mov 0x8049f0c,%eax
152 804870b: 85 c0 test %eax,%eax
153 804870d: 74 12 je 8048721 <frame_dummy+0x21>
154 804870f: b8 00 00 00 00 mov $0x0,%eax
155 8048714: 85 c0 test %eax,%eax
156 8048716: 74 09 je 8048721 <frame_dummy+0x21>
157 8048718: c7 04 24 0c 9f 04 08 movl $0x8049f0c,(%esp)
158 804871f: ff d0 call *%eax
159 8048721: c9 leave
160 8048722: c3 ret
161 8048723: 90 nop
162
163 08048724 <main>:
164 int i_;
165 };
166
167
168 int main()
169 {
170 8048724: 55 push %ebp
171 8048725: 89 e5 mov %esp,%ebp
172 8048727: 83 e4 f0 and $0xfffffff0,%esp
173 804872a: 83 ec 30 sub $0x30,%esp
174 void (A::*p)() = &A::func;
175 804872d: c7 44 24 10 01 00 00 movl $0x1,0x10(%esp)
176 8048734: 00
177 8048735: c7 44 24 14 00 00 00 movl $0x0,0x14(%esp)
178 804873c: 00
179 //cout << "p:" << p << endl;
180 //unsigned int addr = pp;
181 //printf("addr: %p\n", pp);
182
183
184 A a;
185 804873d: 8d 44 24 18 lea 0x18(%esp),%eax
186 8048741: 89 04 24 mov %eax,(%esp)
187 8048744: e8 9d 02 00 00 call 80489e6 <_ZN1AC1Ev>
188 (a.*p)();
189 8048749: 8b 44 24 10 mov 0x10(%esp),%eax
190 804874d: 83 e0 01 and $0x1,%eax
191 8048750: 84 c0 test %al,%al
192 8048752: 74 19 je 804876d <main+0x49>
193 8048754: 8b 44 24 14 mov 0x14(%esp),%eax
194 8048758: 8d 54 24 18 lea 0x18(%esp),%edx
195 804875c: 01 d0 add %edx,%eax
196 804875e: 8b 10 mov (%eax),%edx
197 8048760: 8b 44 24 10 mov 0x10(%esp),%eax
198 8048764: 83 e8 01 sub $0x1,%eax
199 8048767: 01 d0 add %edx,%eax
200 8048769: 8b 00 mov (%eax),%eax
201 804876b: eb 04 jmp 8048771 <main+0x4d>
202 804876d: 8b 44 24 10 mov 0x10(%esp),%eax
203 8048771: 8b 54 24 14 mov 0x14(%esp),%edx
204 8048775: 8d 4c 24 18 lea 0x18(%esp),%ecx
205 8048779: 01 ca add %ecx,%edx
206 804877b: 89 14 24 mov %edx,(%esp)
207 804877e: ff d0 call *%eax
208
209 unsigned int vptr_addr = *(unsigned int *)&a;
210 8048780: 8d 44 24 18 lea 0x18(%esp),%eax
211 8048784: 8b 00 mov (%eax),%eax
212 8048786: 89 44 24 28 mov %eax,0x28(%esp)
213 cout << "vptr_addr:" << hex << vptr_addr << endl;
214 804878a: c7 44 24 04 d7 8a 04 movl $0x8048ad7,0x4(%esp)
215 8048791: 08
216 8048792: c7 04 24 80 a0 04 08 movl $0x804a080,(%esp)
217 8048799: e8 72 fe ff ff call 8048610 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
218 804879e: c7 44 24 04 8d 89 04 movl $0x804898d,0x4(%esp)
219 80487a5: 08
220 80487a6: 89 04 24 mov %eax,(%esp)
221 80487a9: e8 b2 fe ff ff call 8048660 <_ZNSolsEPFRSt8ios_baseS0_E@plt>
222 80487ae: 8b 54 24 28 mov 0x28(%esp),%edx
223 80487b2: 89 54 24 04 mov %edx,0x4(%esp)
224 80487b6: 89 04 24 mov %eax,(%esp)
225 80487b9: e8 72 fe ff ff call 8048630 <_ZNSolsEj@plt>
226 80487be: c7 44 24 04 50 86 04 movl $0x8048650,0x4(%esp)
227 80487c5: 08
228 80487c6: 89 04 24 mov %eax,(%esp)
229 80487c9: e8 72 fe ff ff call 8048640 <_ZNSolsEPFRSoS_E@plt>
230
231 unsigned int func_addr = *(unsigned int *)vptr_addr;
232 80487ce: 8b 44 24 28 mov 0x28(%esp),%eax
233 80487d2: 8b 00 mov (%eax),%eax
234 80487d4: 89 44 24 2c mov %eax,0x2c(%esp)
235 cout << "func_addr:" << hex << func_addr << endl;
236 80487d8: c7 44 24 04 e2 8a 04 movl $0x8048ae2,0x4(%esp)
237 80487df: 08
238 80487e0: c7 04 24 80 a0 04 08 movl $0x804a080,(%esp)
239 80487e7: e8 24 fe ff ff call 8048610 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
240 80487ec: c7 44 24 04 8d 89 04 movl $0x804898d,0x4(%esp)
241 80487f3: 08
242 80487f4: 89 04 24 mov %eax,(%esp)
243 80487f7: e8 64 fe ff ff call 8048660 <_ZNSolsEPFRSt8ios_baseS0_E@plt>
244 80487fc: 8b 54 24 2c mov 0x2c(%esp),%edx
245 8048800: 89 54 24 04 mov %edx,0x4(%esp)
246 8048804: 89 04 24 mov %eax,(%esp)
247 8048807: e8 24 fe ff ff call 8048630 <_ZNSolsEj@plt>
248 804880c: c7 44 24 04 50 86 04 movl $0x8048650,0x4(%esp)
249 8048813: 08
250 8048814: 89 04 24 mov %eax,(%esp)
251 8048817: e8 24 fe ff ff call 8048640 <_ZNSolsEPFRSoS_E@plt>
252 a.inc();
253 804881c: 8d 44 24 18 lea 0x18(%esp),%eax
254 8048820: 89 04 24 mov %eax,(%esp)
255 8048823: e8 aa 01 00 00 call 80489d2 <_ZN1A3incEv>
256 (*(void(*)(A*))(func_addr) )(&a);
257 8048828: 8b 54 24 2c mov 0x2c(%esp),%edx
258 804882c: 8d 44 24 18 lea 0x18(%esp),%eax
259 8048830: 89 04 24 mov %eax,(%esp)
260 8048833: ff d2 call *%edx
261
262 A aa;
263 8048835: 8d 44 24 20 lea 0x20(%esp),%eax
264 8048839: 89 04 24 mov %eax,(%esp)
265 804883c: e8 a5 01 00 00 call 80489e6 <_ZN1AC1Ev>
266 (*(void(*)(A*))(func_addr) )(&aa);
267 8048841: 8b 54 24 2c mov 0x2c(%esp),%edx
268 8048845: 8d 44 24 20 lea 0x20(%esp),%eax
269 8048849: 89 04 24 mov %eax,(%esp)
270 804884c: ff d2 call *%edx
271
272 (*(void(*)(A*))(func_addr) )(&a);
273 804884e: 8b 54 24 2c mov 0x2c(%esp),%edx
274 8048852: 8d 44 24 18 lea 0x18(%esp),%eax
275 8048856: 89 04 24 mov %eax,(%esp)
276 8048859: ff d2 call *%edx
277
278 (*(void(*)(A*))(func_addr) )(&aa);
279 804885b: 8b 54 24 2c mov 0x2c(%esp),%edx
280 804885f: 8d 44 24 20 lea 0x20(%esp),%eax
281 8048863: 89 04 24 mov %eax,(%esp)
282 8048866: ff d2 call *%edx
283
284 return 0;
285 8048868: b8 00 00 00 00 mov $0x0,%eax
286 }
287 804886d: c9 leave
288 804886e: c3 ret
289
290 0804886f <_Z41__static_initialization_and_destruction_0ii>:
291 804886f: 55 push %ebp
292 8048870: 89 e5 mov %esp,%ebp
293 8048872: 83 ec 18 sub $0x18,%esp
294 8048875: 83 7d 08 01 cmpl $0x1,0x8(%ebp)
295 8048879: 75 32 jne 80488ad <_Z41__static_initialization_and_destruction_0ii+0x3e>
296 804887b: 81 7d 0c ff ff 00 00 cmpl $0xffff,0xc(%ebp)
297 8048882: 75 29 jne 80488ad <_Z41__static_initialization_and_destruction_0ii+0x3e>
298 extern wostream wclog; /// Linked to standard error (buffered)
299 #endif
300 //@}
301
302 // For construction of filebuffers for cout, cin, cerr, clog et. al.
303 static ios_base::Init __ioinit;
304 8048884: c7 04 24 14 a1 04 08 movl $0x804a114,(%esp)
305 804888b: e8 50 fd ff ff call 80485e0 <_ZNSt8ios_base4InitC1Ev@plt>
306 8048890: b8 00 86 04 08 mov $0x8048600,%eax
307 8048895: c7 44 24 08 30 a0 04 movl $0x804a030,0x8(%esp)
308 804889c: 08
309 804889d: c7 44 24 04 14 a1 04 movl $0x804a114,0x4(%esp)
310 80488a4: 08
311 80488a5: 89 04 24 mov %eax,(%esp)
312 80488a8: e8 13 fd ff ff call 80485c0 <__cxa_atexit@plt>
313 80488ad: c9 leave
314 80488ae: c3 ret
315
316 080488af <_GLOBAL__sub_I_main>:
317 80488af: 55 push %ebp
318 80488b0: 89 e5 mov %esp,%ebp
319 80488b2: 83 ec 18 sub $0x18,%esp
320 80488b5: c7 44 24 04 ff ff 00 movl $0xffff,0x4(%esp)
321 80488bc: 00
322 80488bd: c7 04 24 01 00 00 00 movl $0x1,(%esp)
323 80488c4: e8 a6 ff ff ff call 804886f <_Z41__static_initialization_and_destruction_0ii>
324 80488c9: c9 leave
325 80488ca: c3 ret
326
327 080488cb <_ZStanSt13_Ios_FmtflagsS_>:
328 _S_ios_fmtflags_end = 1L << 16
329 };
330
331 inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
332 operator&(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
333 { return _Ios_Fmtflags(static_cast<int>(__a) & static_cast<int>(__b)); }
334 80488cb: 55 push %ebp
335 80488cc: 89 e5 mov %esp,%ebp
336 80488ce: 8b 55 08 mov 0x8(%ebp),%edx
337 80488d1: 8b 45 0c mov 0xc(%ebp),%eax
338 80488d4: 21 d0 and %edx,%eax
339 80488d6: 5d pop %ebp
340 80488d7: c3 ret
341
342 080488d8 <_ZStorSt13_Ios_FmtflagsS_>:
343
344 inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
345 operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
346 { return _Ios_Fmtflags(static_cast<int>(__a) | static_cast<int>(__b)); }
347 80488d8: 55 push %ebp
348 80488d9: 89 e5 mov %esp,%ebp
349 80488db: 8b 55 08 mov 0x8(%ebp),%edx
350 80488de: 8b 45 0c mov 0xc(%ebp),%eax
351 80488e1: 09 d0 or %edx,%eax
352 80488e3: 5d pop %ebp
353 80488e4: c3 ret
354
355 080488e5 <_ZStcoSt13_Ios_Fmtflags>:
356 operator^(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
357 { return _Ios_Fmtflags(static_cast<int>(__a) ^ static_cast<int>(__b)); }
358
359 inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
360 operator~(_Ios_Fmtflags __a)
361 { return _Ios_Fmtflags(~static_cast<int>(__a)); }
362 80488e5: 55 push %ebp
363 80488e6: 89 e5 mov %esp,%ebp
364 80488e8: 8b 45 08 mov 0x8(%ebp),%eax
365 80488eb: f7 d0 not %eax
366 80488ed: 5d pop %ebp
367 80488ee: c3 ret
368
369 080488ef <_ZStoRRSt13_Ios_FmtflagsS_>:
370
371 inline const _Ios_Fmtflags&
372 operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
373 { return __a = __a | __b; }
374 80488ef: 55 push %ebp
375 80488f0: 89 e5 mov %esp,%ebp
376 80488f2: 83 ec 18 sub $0x18,%esp
377 80488f5: 8b 45 08 mov 0x8(%ebp),%eax
378 80488f8: 8b 00 mov (%eax),%eax
379 80488fa: 8b 55 0c mov 0xc(%ebp),%edx
380 80488fd: 89 54 24 04 mov %edx,0x4(%esp)
381 8048901: 89 04 24 mov %eax,(%esp)
382 8048904: e8 cf ff ff ff call 80488d8 <_ZStorSt13_Ios_FmtflagsS_>
383 8048909: 8b 55 08 mov 0x8(%ebp),%edx
384 804890c: 89 02 mov %eax,(%edx)
385 804890e: 8b 45 08 mov 0x8(%ebp),%eax
386 8048911: c9 leave
387 8048912: c3 ret
388
389 08048913 <_ZStaNRSt13_Ios_FmtflagsS_>:
390
391 inline const _Ios_Fmtflags&
392 operator&=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
393 { return __a = __a & __b; }
394 8048913: 55 push %ebp
395 8048914: 89 e5 mov %esp,%ebp
396 8048916: 83 ec 18 sub $0x18,%esp
397 8048919: 8b 45 08 mov 0x8(%ebp),%eax
398 804891c: 8b 00 mov (%eax),%eax
399 804891e: 8b 55 0c mov 0xc(%ebp),%edx
400 8048921: 89 54 24 04 mov %edx,0x4(%esp)
401 8048925: 89 04 24 mov %eax,(%esp)
402 8048928: e8 9e ff ff ff call 80488cb <_ZStanSt13_Ios_FmtflagsS_>
403 804892d: 8b 55 08 mov 0x8(%ebp),%edx
404 8048930: 89 02 mov %eax,(%edx)
405 8048932: 8b 45 08 mov 0x8(%ebp),%eax
406 8048935: c9 leave
407 8048936: c3 ret
408 8048937: 90 nop
409
410 08048938 <_ZNSt8ios_base4setfESt13_Ios_FmtflagsS0_>:
411 *
412 * This function clears @a mask in the format flags, then sets
413 * @a fmtfl @c & @a mask. An example mask is @c ios_base::adjustfield.
414 */
415 fmtflags
416 setf(fmtflags __fmtfl, fmtflags __mask)
417 8048938: 55 push %ebp
418 8048939: 89 e5 mov %esp,%ebp
419 804893b: 83 ec 28 sub $0x28,%esp
420 {
421 fmtflags __old = _M_flags;
422 804893e: 8b 45 08 mov 0x8(%ebp),%eax
423 8048941: 8b 40 0c mov 0xc(%eax),%eax
424 8048944: 89 45 f4 mov %eax,-0xc(%ebp)
425 _M_flags &= ~__mask;
426 8048947: 8b 45 10 mov 0x10(%ebp),%eax
427 804894a: 89 04 24 mov %eax,(%esp)
428 804894d: e8 93 ff ff ff call 80488e5 <_ZStcoSt13_Ios_Fmtflags>
429 8048952: 8b 55 08 mov 0x8(%ebp),%edx
430 8048955: 83 c2 0c add $0xc,%edx
431 8048958: 89 44 24 04 mov %eax,0x4(%esp)
432 804895c: 89 14 24 mov %edx,(%esp)
433 804895f: e8 af ff ff ff call 8048913 <_ZStaNRSt13_Ios_FmtflagsS_>
434 _M_flags |= (__fmtfl & __mask);
435 8048964: 8b 45 10 mov 0x10(%ebp),%eax
436 8048967: 89 44 24 04 mov %eax,0x4(%esp)
437 804896b: 8b 45 0c mov 0xc(%ebp),%eax
438 804896e: 89 04 24 mov %eax,(%esp)
439 8048971: e8 55 ff ff ff call 80488cb <_ZStanSt13_Ios_FmtflagsS_>
440 8048976: 8b 55 08 mov 0x8(%ebp),%edx
441 8048979: 83 c2 0c add $0xc,%edx
442 804897c: 89 44 24 04 mov %eax,0x4(%esp)
443 8048980: 89 14 24 mov %edx,(%esp)
444 8048983: e8 67 ff ff ff call 80488ef <_ZStoRRSt13_Ios_FmtflagsS_>
445 return __old;
446 8048988: 8b 45 f4 mov -0xc(%ebp),%eax
447 }
448 804898b: c9 leave
449 804898c: c3 ret
450
451 0804898d <_ZSt3hexRSt8ios_base>:
452 }
453
454 /// Calls base.setf(ios_base::hex, ios_base::basefield).
455 inline ios_base&
456 hex(ios_base& __base)
457 {
458 804898d: 55 push %ebp
459 804898e: 89 e5 mov %esp,%ebp
460 8048990: 83 ec 18 sub $0x18,%esp
461 __base.setf(ios_base::hex, ios_base::basefield);
462 8048993: c7 44 24 08 4a 00 00 movl $0x4a,0x8(%esp)
463 804899a: 00
464 804899b: c7 44 24 04 08 00 00 movl $0x8,0x4(%esp)
465 80489a2: 00
466 80489a3: 8b 45 08 mov 0x8(%ebp),%eax
467 80489a6: 89 04 24 mov %eax,(%esp)
468 80489a9: e8 8a ff ff ff call 8048938 <_ZNSt8ios_base4setfESt13_Ios_FmtflagsS0_>
469 return __base;
470 80489ae: 8b 45 08 mov 0x8(%ebp),%eax
471 }
472 80489b1: c9 leave
473 80489b2: c3 ret
474 80489b3: 90 nop
475
476 080489b4 <_ZN1A4funcEv>:
477
478 using namespace std;
479
480 struct A
481 {
482 virtual void func()
483 80489b4: 55 push %ebp
484 80489b5: 89 e5 mov %esp,%ebp
485 80489b7: 83 ec 18 sub $0x18,%esp
486 {
487 printf("i: %d\n", i_);
488 80489ba: 8b 45 08 mov 0x8(%ebp),%eax
489 80489bd: 8b 40 04 mov 0x4(%eax),%eax
490 80489c0: 89 44 24 04 mov %eax,0x4(%esp)
491 80489c4: c7 04 24 d0 8a 04 08 movl $0x8048ad0,(%esp)
492 80489cb: e8 50 fc ff ff call 8048620 <printf@plt>
493 }
494 80489d0: c9 leave
495 80489d1: c3 ret
496
497 080489d2 <_ZN1A3incEv>:
498 void inc()
499 80489d2: 55 push %ebp
500 80489d3: 89 e5 mov %esp,%ebp
501 {
502 ++i_;
503 80489d5: 8b 45 08 mov 0x8(%ebp),%eax
504 80489d8: 8b 40 04 mov 0x4(%eax),%eax
505 80489db: 8d 50 01 lea 0x1(%eax),%edx
506 80489de: 8b 45 08 mov 0x8(%ebp),%eax
507 80489e1: 89 50 04 mov %edx,0x4(%eax)
508 }
509 80489e4: 5d pop %ebp
510 80489e5: c3 ret
511
512 080489e6 <_ZN1AC1Ev>:
513 A()
514 80489e6: 55 push %ebp
515 80489e7: 89 e5 mov %esp,%ebp
516 {
517 80489e9: 8b 45 08 mov 0x8(%ebp),%eax
518 80489ec: c7 00 f8 8a 04 08 movl $0x8048af8,(%eax)
519 i_=10;
520 80489f2: 8b 45 08 mov 0x8(%ebp),%eax
521 80489f5: c7 40 04 0a 00 00 00 movl $0xa,0x4(%eax)
522 }
523 80489fc: 5d pop %ebp
524 80489fd: c3 ret
525 80489fe: 90 nop
526 80489ff: 90 nop
527
L185 0x18(%esp) 這是 object a 的位址, 為於 stack。
L185 ~ 187 在建構 a, L188 ~ 207 在使用那個 member function pointer。
L187 call A::A() 會設定 virtual table 的位址。
518 80489ec: c7 00 f8 8a 04 08 movl $0x8048af8,(%eax)
0x8048af8 這就是 vtable 的位址, 查這位址的內容就會看到 A::func() 的位址。
non-virtual member funtion 和 virtual member funtion 基本原理都一樣, 找到 A::func() address, 然後把 &aa 或是 &a 傳進去即可。
virtual member function:
void (A::*p)() = &A::func;
804873f: c7 44 24 14 01 00 00 movl $0x1,0x14(%esp)
8048746: 00
8048747: c7 44 24 18 00 00 00 movl $0x0,0x18(%esp)
804874e: 0
不過我沒搞懂這兩部份是用來幹嘛的?
Member Function Pointers and the Fastest Possible C++ Delegates 對於苦惱這文章的朋友來說可以參考 "深度探索 C++ 物件模型": Virtual member function 這節在介紹這個, 簡單兩頁的介紹就足以解除大部份的疑惑。
深度探索 C++ 物件模型 (繁體版本) p178 ~ p181 提供了更多的資訊。member function pointer 為了支援多重繼承和虛擬繼承, 才會需要這些欄位。
也需要一些手法來判斷這個 member function pointer 是位址還是 index value。
有了這些知識, 應該容易參閱各家編譯器實作的反組譯程式碼。
ptt Feis 的作法, 不過我看不懂
http://ideone.com/tXALVS
VC++ 的版本
env:
vc2010
winxp 32bit
vc 這個要 thiscall (ptt purpose 提供)
http://en.wikipedia.org/wiki/X86_calling_conventions#thiscall
c.cpp
1 #include <iostream>
2 #include <cstdio>
3
4 using namespace std ;
5
6 struct A
7 {
8 virtual void func ( )
9 {
10 printf ( "i: %d\n " , i_ ) ;
11 }
12 void inc ( )
13 {
14 + + i_ ;
15 }
16 A ( )
17 {
18 i_ = 10 ;
19 }
20 private :
21 int i_ ;
22 } ;
23
24
25 int main ( )
26 {
27 void ( A : : * p ) ( ) = & A : : func ;
28
29 //cout << "sizeof: " << sizeof(p) << endl;
30
31 //cout << "sizeof: " << sizeof(A) << endl;
32
33 //printf("addr: %p\n", p);
34 //cout << "p:" << p << endl;
35 //unsigned int addr = pp;
36 //printf("addr: %p\n", pp);
37
38
39 A a ;
40 ( a .* p ) ( ) ;
41
42 unsigned int vptr_addr = * ( unsigned int * ) & a ;
43 cout < < "vptr_addr:" < < hex < < vptr_addr < < endl ;
44
45 unsigned int func_addr = * ( unsigned int * ) vptr_addr ;
46 cout < < "func_addr:" < < hex < < func_addr < < endl ;
47 a .inc ( ) ;
48
49 __asm
50 {
51 lea ecx , a
52 }
53 #if 1
54 ( * ( void ( * ) ( ) ) ( func_addr ) ) ( ) ;
55
56 A aa ;
57 __asm
58 {
59 lea ecx , aa
60 }
61 ( * ( void ( * ) ( ) ) ( func_addr ) ) ( ) ;
62
63 __asm
64 {
65 lea ecx , a
66 }
67 ( * ( void ( * ) ( ) ) ( func_addr ) ) ( ) ;
68
69 __asm
70 {
71 lea ecx , aa
72 }
73 ( * ( void ( * ) ( ) ) ( func_addr ) ) ( ) ;
74 #endif
75 return 0 ;
76 }
C:\>cl c.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
c.cpp
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xlocale(323) : warning
C4530: 已使用 C++ 例外處理常式,但沒有啟用回溯語意 (Unwind Semantics)。請指定 /E
Hsc
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c.exe
c.obj
C:\>c
i: 10
vptr_addr:41a1bc
func_addr:4011a0
i: 11
i: 10
i: 11
i: 10
ref:
Member Function Pointers and the Fastest Possible C++ Delegates
深度探索 C++ 物件模型:virtual member function 這節
Pointers to member functions are very strange animals (ptt purpose)
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。