我无法理解如何用汇编语言实现类。我检查了使用类的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
答案 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)您只能看到类的数据结构。但是在这里你必须考虑填充和其他事情。
有时候查看生成的汇编程序代码是个好主意,以便了解哪种类型的编程会导致哪种可执行文件。但是今天大多数编译器都做得非常完美,几乎不可能看到代码是如何以高级语言呈现的。但是,是的,它有利于学习: - )