#include <iostream>
#include <stdio.h>
class Base
{
public:
void function_1()
{
printf("function_1...\n");
}
virtual void function_2()
{
printf("function_2...\n");
}
};
int main(int argc, char ** argv)
{
Base base;
base.function_1();
base.function_2();
}
[xiaozhi@linux virtual]$ gdb
GNU gdb (GDB) Fedora 7.7.1-21.fc20
Copyright (C) 2014 Free Software Foundation, Inc.
(gdb) file r-virtual-01
Reading symbols from r-virtual-01...done.
(gdb) b *main
Breakpoint 1 at 0x8048640: file r-virtual-01.cpp, line 19.
(gdb) r
Starting program: /home/share/work/ac-code/study-c++/virtual/r-virtual-01
Breakpoint 1, main (argc=1, argv=0xbffff194) at r-virtual-01.cpp:19
19 {
Missing separate debuginfos, use: debuginfo-install libgcc-4.8.3-7.fc20.i686 libstdc++-4.8.3-7.fc20.i686
(gdb) disassemble /mr main
Dump of assembler code for function main(int, char**):
19 {
=> 0x08048640 <+0>: 55 push %ebp
0x08048641 <+1>: 89 e5 mov %esp,%ebp
0x08048643 <+3>: 83 e4 f0 and $0xfffffff0,%esp
0x08048646 <+6>: 83 ec 20 sub $0x20,%esp
20 Base base;
0x08048649 <+9>: 8d 44 24 1c lea 0x1c(%esp),%eax
0x0804864d <+13>: 89 04 24 mov %eax,(%esp)
0x08048650 <+16>: e8 a3 00 00 00 call 0x80486f8 <Base::Base()>
21
22 base.function_1();
0x08048655 <+21>: 8d 44 24 1c lea 0x1c(%esp),%eax
0x08048659 <+25>: 89 04 24 mov %eax,(%esp)
0x0804865c <+28>: e8 6f 00 00 00 call 0x80486d0 <Base::function_1()>
23 base.function_2();
0x08048661 <+33>: 8d 44 24 1c lea 0x1c(%esp),%eax
0x08048665 <+37>: 89 04 24 mov %eax,(%esp)
0x08048668 <+40>: e8 77 00 00 00 call 0x80486e4 <Base::function_2()>
24 }
0x0804866d <+45>: b8 00 00 00 00 mov $0x0,%eax
0x08048672 <+50>: c9 leave
0x08048673 <+51>: c3 ret
End of assembler dump.
(gdb) n
20 Base base;
(gdb) n
22 base.function_1();
(gdb) n
function_1...
23 base.function_2();
(gdb) disassemble
Dump of assembler code for function main(int, char**):
0x08048640 <+0>: push %ebp
0x08048641 <+1>: mov %esp,%ebp
0x08048643 <+3>: and $0xfffffff0,%esp
0x08048646 <+6>: sub $0x20,%esp
0x08048649 <+9>: lea 0x1c(%esp),%eax
0x0804864d <+13>: mov %eax,(%esp)
0x08048650 <+16>: call 0x80486f8 <Base::Base()>
0x08048655 <+21>: lea 0x1c(%esp),%eax
0x08048659 <+25>: mov %eax,(%esp)
0x0804865c <+28>: call 0x80486d0 <Base::function_1()>
=> 0x08048661 <+33>: lea 0x1c(%esp),%eax
0x08048665 <+37>: mov %eax,(%esp)
0x08048668 <+40>: call 0x80486e4 <Base::function_2()>
0x0804866d <+45>: mov $0x0,%eax
0x08048672 <+50>: leave
0x08048673 <+51>: ret
End of assembler dump.
/* 找出虚函数地址方法一 */
(gdb) p $esp
$1 = (void *) 0xbffff0d0
(gdb) p $esp+0x1c
$2 = (void *) 0xbffff0ec
(gdb) p base
$3 = {_vptr.Base = 0x80487c8 <vtable for Base+8>}
(gdb) x /xw 0xbffff0ec
0xbffff0ec: 0x080487c8
(gdb) x /xw 0x080487c8
0x80487c8 <_ZTV4Base+8>: 0x080486e4 # 虚函数地址
/* 找出虚函数地址方法二 */
(gdb) p base
$4 = {_vptr.Base = 0x80487c8 <vtable for Base+8>}
(gdb) i r $esp
esp 0xbffff0d0 0xbffff0d0
(gdb) p /x 0xbffff0d0+0x1c
$5 = 0xbffff0ec
(gdb) p /x 0xbffff0ec
$6 = 0xbffff0ec
(gdb) p /x *0xbffff0ec
$7 = 0x80487c8
(gdb) p /x *0x80487c8
$8 = 0x80486e4 # 虚函数地址
(gdb) disassemble 0x80486e4 # 反汇编地址处代码
Dump of assembler code for function Base::function_2():
0x080486e4 <+0>: push %ebp
0x080486e5 <+1>: mov %esp,%ebp
0x080486e7 <+3>: sub $0x18,%esp
0x080486ea <+6>: movl $0x80487b2,(%esp)
0x080486f1 <+13>: call 0x8048520 <puts@plt>
0x080486f6 <+18>: leave
0x080486f7 <+19>: ret
End of assembler dump.
(gdb)