C++虚函数调用过程深度理解(二)

前言

在上文C++虚函数调用过程深度理解中,笔者探讨验证了关于虚函数调用过程的一些理解。

但回顾后却发现仍然略过了一些细节,这部分细节是关于虚函数调用时this指针如何转换得到目标虚函数地址。上文有所涉及,但没有深入。接下来,笔者将继续验证这部分细节。

  • 依然使用前文示例代码中的菱形继承类模型来验证。

验证

对main函数中的语句略微修改,如下:

int main(int argc, char* argv[]) {
   
    DiamondDerived diamond;

    DerivedB *tmp = ⋄

    Base* base = static_cast<Base*>(tmp);

    base->VirtualFunc("called_from_main");

    return 0;
}

该部分反汇编,笔者注释后如下:

  • 先看DiamondDerived diamond;对应的汇编代码
DiamondDerived diamond;

;; 将edx寄存器设置1,入参
;; ecx edx 一般为函数入参寄存器
00007FF76566AE8C  mov         edx,1  

;; 取diamond的内存地址赋值给rcx寄存器
00007FF76566AE91  lea         rcx,[diamond]  

;; 调用构造函数
00007FF76566AE95  call        DiamondDerived::DiamondDerived (07FF765661249h)  

;; 占位,内存对齐。这里是指令对齐,指令加载在内存中。
00007FF76566AE9A  nop  

DerivedB *tmp = ⋄对应汇编:

;; 取diamond的内存地址赋值给rax寄存器
00007FF76566AE9B  lea         rax,[diamond]  

;; 检查rax寄存器的值是否等于0
00007FF76566AE9F  test        rax,rax  

;;上一句判断中若相等,则跳转到目标内存07FF76566AEB5h,可以在下面语句中找到。
00007FF76566AEA2  je          __$EncStackInitStart+5Eh (07FF76566AEB5h)  

;; 取diamond的内存地址到rax寄存器
00007FF76566AEA4  lea         rax,[diamond]  

;; rax寄存器加载的地址加8,即diamond内存地址向高偏移8字节
;; 这是编译器的设置,将diamond的内存地址偏移8字节,这里应该是diamond对象中DerivedB的虚函数表指针。
00007FF76566AEA8  add         rax,8  

;; 将rax加载的地址赋值给栈上临时变量
00007FF76566AEAC  mov         qword ptr 

你可能感兴趣的:(学习分享,C++,c++,开发语言,后端)