动态调度是如何在程序集中发生的
How does dynamic dispatch happen in assembly?
我在某个地方找到了一些代码,并决定在汇编中把它们吐出来,试图找出区别。
#include <iostream>
class A {
public:
void f() const { std::cout << "A::f()" << std::endl; }
};
class B {
public:
void f() const { std::cout << "B::f()" << std::endl; }
};
int main()
{
A a ;
B b ;
a.f() ;
b.f() ;
}
-
#include <iostream>
class base {
public:
virtual void f() const = 0 ;
virtual ~base() {}
};
class A : public base {
public:
virtual void f() const { std::cout << "A::f()" << std::endl; }
};
class B : public base {
public:
virtual void f() const { std::cout << "B::f()" << std::endl; }
};
void dispatch(const base & x) {
x.f();
}
int main() {
A a ;
B b ;
dispatch(a) ;
dispatch(b) ;
}
我在研究这个类似的问题(如何通过查看程序集来判断程序是否使用动态调度),并试图在程序集中找到它,但我不清楚
这是两个程序的diff文件(http://www.diffchecker.com/b9y0v3ps)。有人能指出动态调度发生在哪里吗?也许可以解释一下发生了什么以及两者之间的区别?
从链接到的程序集,非虚拟调度如下所示:
53 call _ZNK1A1fEv
直接调用函数。
虚拟调度类似于:
53 mov EAX, DWORD PTR [EBP - 4]
54 mov ECX, DWORD PTR [EAX]
56 call DWORD PTR [ECX]
从对象加载vtable的地址,然后从vtable加载函数地址,然后间接调用函数。
动态调度是通过一个虚拟函数表实现的,该表具有完整对象的最终覆盖者的地址。对象本身包含一个指向相应vtable的指针。
在汇编中,您应该能够认识到,对于动态调度,要调用的函数是通过vptr加载的,而在静态调度的情况下,调用直接解析到函数的地址。
相关文章:
- 内联程序集printf将整数解释为地址
- 正在解码MSVC 32位版本的程序集(作业).没有手术做什么
- 具有外部"c"和程序集的未定义函数
- 用于将C++代码转换为 Web 程序集的脚本未终止
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- CoreCLR 中的检测探查器 - 将帮助程序程序集加载到 dotnet 进程的方法
- 不同于按值传递和常量引用传递的程序集
- 为什么在堆栈和堆上创建变量会产生相同的程序集代码?
- C++变量在调用 x64 程序集函数后重置为 0
- 如何将C++子例程链接到 x86 程序集程序?
- Qt 网页程序集缓存
- 测试操作系统时执行程序集"sti"时虚拟框崩溃
- 为什么从 constexpr 引用生成的程序集代码与从 constexpr 指针生成的程序集代码不同?
- 将内联程序集尾调用函数尾声替换为用于x86/x64 msvc的Intrinsics
- 解析 C# 中的C++程序集
- 64 位进程中的 AnyCPU C# DLL 无法引用 64 位C++ DLL(给出错误:无法加载文件或程序集)
- 使用CLANG内联程序集创建C++预增量操作
- 是否可以在C++中基于程序集输出(.dll或.exe)定义变量
- 用于比较基元类型的std::可选的有趣程序集
- 在.NET Core 3.1中运行托管C++/CLI程序集时,映像格式错误