【问题标题】:c++ class disassemblyc++类反汇编
【发布时间】:2011-06-22 08:08:23
【问题描述】:

我有以下代码:

class Base {
public:
int x,y;
Base() { x=10; y=20; }
virtual void myfunction() { }
};

int main() {
Base *b = new Base();
return 0;
}

反汇编给了我类似的东西:

push 0Ch                ; size of Base
call j_<some giberrish> ; IDA gives the comment "operator new(uint)"
add esp, 4              ; function epilogue
mov [ebp+var_E0], eax

几行之后,您将调用构造函数。

mov ecx, [ebp+var_E0]
call j_Base__Base
mov [ebp+var_F4], eax
  • 起初我以为var_E0 将包含指向实例的指针,但现在我很确定var_F4 确实如此,因为它包含构造函数的返回值。
  • 在那种情况下,var_E0 到底包含什么?为什么在调用构造函数之前将其移动到ecx

【问题讨论】:

  • 嗯,为什么要在调用构造函数之前将其加载到 ecx 中? ://
  • @uki 是this 指针

标签: c++ class assembly reverse-engineering


【解决方案1】:

这是编译器临时生成的一些内部变量。

当你写new Base时,编译器会生成一个对全局的调用 operator new 函数,然后调用返回的构造函数 地址。显然,您的编译器保存从返回的地址 operator new 在内存中,而不是将其保存在寄存器中。

【讨论】:

    【解决方案2】:

    Visual C++ 使用内部约定,构造函数返回指向对象实例的指针(根据 C++ 标准,构造函数没有返回值)。所以在你的情况下 var_E0 var_F4 都持有实例指针。

    查看my article 了解有关 Visual C++ 如何实现 C++ 的更多详细信息。

    【讨论】:

      【解决方案3】:

      这几乎可以肯定是您正在查看的调试版本,并且调试版本对其所做的事情非常保守。创建对象是一个两阶段的过程:分配内存,然后构造对象。您的编译器将分配的内存指针放入临时变量中。如果您构建优化版本,则不会存储此临时变量,因为这会引入不必要的开销(写入/读取 RAM)。

      【讨论】:

      • 澄清一下,第一次调用分配内存而不是调用 j_Base__Base,对吗?谢谢!
      • @eQuiNoX - 就像 Skizz 所说,编译器必须分步执行此操作,分配内存,然后构造对象。在最坏的情况下,当构造失败时,它还必须调用operator delete 来释放内存。这是保存指针的一个很好的理由。 :-)
      猜你喜欢
      • 1970-01-01
      • 2011-03-12
      • 2013-04-11
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      相关资源
      最近更新 更多