0x0000000000400759
0x000000000040075c
0x000000000040075d
//整个类由于没有成员对象和数据,只有一个虚表指针,因此类的大小为8
0x0000000000400761
0x0000000000400766
//rax为开辟的内存首地址,调用CChinese的首地址
0x000000000040076b
0x000000000040076f
0x0000000000400773
0x0000000000400778
0x000000000040077c
0x0000000000400780
0x0000000000400784
//根据(一)的分析,有两个析构函数,因此ShowSpeak在虚表中处于第三项,因此这里的偏移量就是0x10
0x0000000000400787
0x000000000040078b
0x000000000040078e
0x0000000000400792
0x0000000000400797
0x0000000000400799
0x000000000040079e
0x00000000004007a0
0x00000000004007a2
0x00000000004007a6
0x00000000004007aa
0x00000000004007ae
0x00000000004007b3
0x00000000004007b7
0x00000000004007bb
0x00000000004007c0
0x00000000004007c4
//调用第二个析构函数
0x00000000004007c7
0x00000000004007cb
0x00000000004007ce
0x00000000004007d2
0x00000000004007d4
0x00000000004007d9
0x00000000004007dd
0x00000000004007de
0x00000000004007df
O2版本:
0x0000000000400760
0x0000000000400765
0x000000000040076a
0x000000000040076f
0x0000000000400774
//前面这一串动作的目的是为了保存某些寄存器的值,唯一有意义的就是mov $0x8,%edi,表明需要开辟的空间大小为8个字节
0x0000000000400778
//%rax里面保存了这块内存的首地址,因此需要首先知道这个rbp到底是哪个函数的地址?
//0x464(%rip),这个在这里有点绕口,相当于将0x464+$rip的值作为内存地址,将该内存单元里面的值取出来,放到$rbp中
//注意这里的$rip的值是下一条指令的值,所以是0x400784+0x464=0x400be8
//%rbp的值是0x400820,该地址处的指令为
//0x400820 <_ZN7CPerson12GetClassNameEv>: mov $0x400b10,%eax
//0x400825 <_ZN7CPerson12GetClassNameEv+5>: retq
//其中,0x400b10里面的值是“CPerson”
//这个0x400bd0是CPerson的虚表指针,可以通过x/6xg 0x400bd0来查看表项内容,并通过反汇编每个表项所指地址处的汇编来判断每个虚函数的内容
//从这里可以看出,经过优化后,没有了明显的构造函数,相当于构造函数被打开了,在main段就将CPerson构造函数需要做的事情都做掉了;但首部的虚表指针,还是赋了一下
0x000000000040077d
0x0000000000400784
0x0000000000400787
0x000000000040078e
0x0000000000400791
//这里的rax是函数返回的内容,0x400b22的值是"%s::ShowSpeak()\r\n",因此猜测rax就是返回的GetClassName()返回的字符串
0x0000000000400793
0x0000000000400796
0x000000000040079b
0x000000000040079d
//目前的分析来看,0x400b50像是CChinese的虚表地址
0x00000000004007a2
0x00000000004007a9
//就是两行代码
//mov $0x400b18,%eax;retq;
//其中0x400b18的内容为“CChinese”
0x00000000004007ac
0x00000000004007b2
0x00000000004007b5
0x00000000004007ba
0x00000000004007bc
//下面这几行,就是开始调用ShowSpeak了
0x00000000004007c1
0x00000000004007c4
0x00000000004007c7
0x00000000004007c9
//这里开始调用析构函数了
0x00000000004007cc
0x00000000004007cf
0x00000000004007d2
0x00000000004007d5
0x00000000004007d9
//平衡堆栈,清理现场了
0x00000000004007de
0x00000000004007e0
0x00000000004007e5
0x00000000004007e9
//到这里main函数就结束了
0x00000000004007ea
0x00000000004007ed
0x00000000004007f0
0x00000000004007f5
0x00000000004007f8
0x00000000004007fd
0x0000000000400800
0x0000000000400803
0x000000000040080a
0x000000000040080c
0x0000000000400811
0x0000000000400814
0x0000000000400816
0x000000000040081b