我有三门课:
class Base { virtual foo() {...} }
class A : Base { virtual foo() override {...} }
class B : A { virtual bar() {...} /* introduce bar, but no foo override */ }
我想了解这个虚函数调用是如何工作的。
如果我调用A a; a.foo()
-编译器会生成Call
指令FF 10
,它会导致E9 01 02 03 04
的近跳转指令。最后4个字节-从vtable-record到真实的函数的相对偏移量。这是非常明显和清楚的。但是如果我调用B b; b.foo()
-Call
指令会导致另一种跳转FF 25
。Visual Studio反汇编器将其显示为:
00007FFA2CAB1C85 FF 25 AD 76 21 01 jmp qword ptr [A::foo (07FFA2DCC9338h)]
我希望跳转到07FFA2DCC9338h
地址,但实际上,它跳转到07FFA4AD05885h
(我认为VS与预测地址有关):
00007FFA4AD05885 E9 96 5D 01 00 jmp A::foo (07FFA4AD1B620h)
这个跳转指令(E9
)把我转到了真实的函数。
但是我不明白FF 25
是如何工作的,不幸的是,我的组装知识很差,我读了some documentation,它说的是一些“门”,我不明白。
是否可以通过当前指令地址(RIP
)与跳转参数来预测远跳转(FF
)得跳转位置?
1条答案
按热度按时间ig9co6j11#
谢谢@杰斯特,看来你是对的。
E9
-跳转到特定的相对代码指令。FF 25
-计算某个特定的相对位置,从那里读取存储器,并将该存储器用作指向下一个代码指令的指针。我刚刚发现
**qword ptr[...]**表示我应该解引用该值!