从c ++到汇编语言的类

时间:2014-07-11 07:55:16

标签: c++ assembly

我无法理解如何用汇编语言实现类。我检查了使用类的c ++应用程序(visual studio的编译器)的源代码,但它看起来像没有特殊功能的普通代码或其他东西。这个类的构造函数在哪里,它是如何工作的?我猜构造函数的参数是通过堆栈传递的,但是函数unknown_libname_1做了什么?

.text:00261050
.text:00261050 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:00261050 _main           proc near               ; CODE XREF: ___tmainCRTStartup+10Ap
.text:00261050
.text:00261050 var_10          = byte ptr -10h
.text:00261050 var_8           = byte ptr -8
.text:00261050 argc            = dword ptr  8
.text:00261050 argv            = dword ptr  0Ch
.text:00261050 envp            = dword ptr  10h
.text:00261050
.text:00261050                 push    ebp
.text:00261051                 mov     ebp, esp
.text:00261053                 sub     esp, 10h
.text:00261056                 push    4
.text:00261058                 push    3
.text:0026105A                 lea     ecx, [ebp+var_8]
.text:0026105D                 call    unknown_libname_1 ; Microsoft VisualC 2-10/net runtime
.text:00261062                 push    6
.text:00261064                 push    5
.text:00261066                 lea     ecx, [ebp+var_10]
.text:00261069                 call    unknown_libname_1 ; Microsoft VisualC 2-10/net runtime
.text:0026106E                 mov     eax, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:00261073                 push    eax
.text:00261074                 lea     ecx, [ebp+var_8]
.text:00261077                 call    sub_261000
.text:0026107C                 push    eax
.text:0026107D                 push    offset aRectArea ; "rect area: "
.text:00261082                 mov     ecx, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:00261088                 push    ecx
.text:00261089                 call    sub_2612D0
.text:0026108E                 add     esp, 8
.text:00261091                 mov     ecx, eax
.text:00261093                 call    ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(int)
.text:00261099                 mov     ecx, eax
.text:0026109B                 call    ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:002610A1                 mov     edx, ds:?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z ; std::endl(std::basic_ostream<char,std::char_traits<char>> &)
.text:002610A7                 push    edx
.text:002610A8                 lea     ecx, [ebp+var_10]
.text:002610AB                 call    sub_261000
.text:002610B0                 push    eax
.text:002610B1                 push    offset aRectbArea ; "rectb area: "
.text:002610B6                 mov     eax, ds:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::basic_ostream<char,std::char_traits<char>> std::cout
.text:002610BB                 push    eax
.text:002610BC                 call    sub_2612D0
.text:002610C1                 add     esp, 8
.text:002610C4                 mov     ecx, eax
.text:002610C6                 call    ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(int)
.text:002610CC                 mov     ecx, eax
.text:002610CE                 call    ds:??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<(std::basic_ostream<char,std::char_traits<char>> & (*)(std::basic_ostream<char,std::char_traits<char>> &))
.text:002610D4                 xor     eax, eax
.text:002610D6                 mov     esp, ebp
.text:002610D8                 pop     ebp
.text:002610D9                 retn
.text:0026

功能sub_261000:

sub_261000 proc near

var_4= dword ptr -4

push    ebp
mov     ebp, esp
push    ecx
mov     [ebp+var_4], ecx
mov     eax, [ebp+var_4]
mov     ecx, [ebp+var_4]
mov     eax, [eax]
imul    eax, [ecx+4]
mov     esp, ebp
pop     ebp
retn
sub_261000 endp

2 个答案:

答案 0 :(得分:5)

汇编没有任何类概念。在堆栈上创建类类型的对象时,它只为其所有成员对象腾出空间。成员函数就像普通函数一样,但它也传递一个指向这些成员对象开头的指针,即this指针。已编译的函数只访问相对于此指针的成员。构造函数只是另一个初始化这些成员对象的函数。

你可以想到这个:

class A {
  private:
    int x;
    short y;
  public:
    A(int arg) : x(arg), y(6) { }
    void print() {
      std::cout << x << ',' << y << std::endl;
    }
};

int main() {
  A a(5);
  a.print()
}

正在变成像这样的无效C ++:

void A_construct(A* this, int arg) {
  this->x = arg;
  this->y = 6;
}

void A_print(A* this) {
  std::cout << this->x << ',' << this->y << std::endl;
}

int main() {
  int x;
  short y;
  A_construct(this_cast<A*>(&x), 5);
  A_print(this_cast<A*>(&x));
}

组成this_cast的唯一原因是允许A*,因此我可以继续使用this->x表示&#34;访问x A&#34;的对象。只是为了方便说明。

除了这些运行时细节之外,类的唯一其他影响是它们对代码设置了一些编译时限制。例如,您无法编写从其外部访问类的private成员的代码。这在组装中没有以任何方式强制执行。

答案 1 :(得分:0)

我真的不知道你在寻找什么: - )

但首先你要记住:

1)编译器将尝试优化您的所有代码,与您的语言无关。为此,您通常会看不到任何内联函数。

2)来自常量值的所有计算将在编译时完成,作为优化的一部分。因此,如果它们不是编译时间常量,那么您可能只处理值!

3)全局对象的初始化将通过在main之前运行的程序开始时的简单复制循环来完成。代码本身没什么可看的。

4)您只能看到类的数据结构。但是在这里你必须考虑填充和其他事情。

有时候查看生成的汇编程序代码是个好主意,以便了解哪种类型的编程会导致哪种可执行文件。但是今天大多数编译器都做得非常完美,几乎不可能看到代码是如何以高级语言呈现的。但是,是的,它有利于学习: - )