自定义类的使用
#include "Sales_item.h"
int main(void)
{
Sales_item total;
if (std::cin >> total) {
Sales_item trans;
while (std::cin >> trans)
{
if (total.isbn() == trans.isbn())
total += trans;
else {
std::cout << total << std::endl;
total = trans;
}
}
std::cout << total << std::endl;
}
else {
std::cerr << "No data?!" << std::endl;
return -1;
}
return 0;
}
来看第一句
Sales_item total;
mscv2015 32位反汇编
.text:004013BE xorps xmm0, xmm0
.text:004013C1 mov [ebp+var_50], 0
.text:004013C8 mov [ebp+var_4C], 0Fh
.text:004013CF mov byte ptr [ebp+var_60], 0
.text:004013D3 mov [ebp+var_48], 0
.text:004013DA movsd [ebp+var_40], xmm
clang+llvm 64位反汇编
这里调用了构造函数
.text:0000000000401422 lea rax, [rbp+total]
.text:0000000000401426 mov rdi, rax
.text:0000000000401429 mov [rbp+var_C8], rax
.text:0000000000401430 call Sales_item
构造函数内部大概如下
result = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string();
*(_DWORD *)(a1 + 0x20) = 0;
*(_QWORD *)(a1 + 0x28) = 0LL;
可以看到,类的实例本质上和结构体没有区别。Sales_Item成员定义如下
private:
std::string bookNo; // implicitly initialized to the empty string
#ifdef IN_CLASS_INITS
unsigned units_sold = 0; // explicitly initialized
double revenue = 0.0;
#else
unsigned units_sold;
double revenue;
再看下一句条件判断
if (std::cin >> total)
mscv2015 32位反汇编
.text:004013DF mov [ebp+var_4], 0
.text:004013E6 lea edx, [ebp+var60]
.text:004013E9 mov ecx, ds:?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A ; std::basic_istream<char,std::char_traits<char>> std::cin
.text:004013EF call input
.text:004013F4 mov ecx, [eax]
.text:004013F6 mov ecx, [ecx+4]
.text:004013F9 test byte ptr [ecx+eax+0Ch], 6
.text:004013FE jnz loc_40163E //跳转到else处
clang+llvm 64位反汇编
.text:0000000000401435 mov ecx, offset _ZSt3cin ; std::cin
.text:000000000040143A mov edi, ecx
.text:000000000040143C mov rsi, [rbp+var_C8]
.text:0000000000401443 call input
.text:0000000000401448 mov [rbp+var_D0], rax
.text:000000000040144F jmp $+5
.text:0000000000401454 loc_401454: ; CODE XREF: main+3F↑j
.text:0000000000401454 mov rax, [rbp+var_D0]
.text:000000000040145B mov rcx, [rax]
.text:000000000040145E mov rcx, [rcx-18h]
.text:0000000000401462 add rax, rcx
.text:0000000000401465 mov rdi, rax
.text:0000000000401468 call __ZNKSt9basic_iosIcSt11char_traitsIcEEcvbEv ; std::basic_ios<char,std::char_traits<char>>::operator bool(void)
.text:000000000040146D mov [rbp+var_D1], al
.text:0000000000401473 jmp $+5
.text:0000000000401478 loc_401478: ; CODE XREF: main+63↑j
.text:0000000000401478 mov al, [rbp+var_D1]
.text:000000000040147E test al, 1
.text:0000000000401480 jnz loc_40148B //跳转到else处
.text:0000000000401486 jmp loc_401687
这段代码信息很多,首先input函数(自己改的名)返回了一个指针的指针,它最终有一个指向的值与std::cin >> value的返回值有关,不过在mscv编译器中,最终的比较是
test byte ptr [ecx+eax+0Ch], 6
而在llvm中,最终的比较是
test al, 1
具体原因不是很懂。
接着来看对象的函数调用和重载运算符
if (total.isbn() == trans.isbn())
total += trans;
mscv2015 32位反汇编(这里代码非常混乱,很多代码不会执行,这里只给出关键代码)
if (total.isbn() == trans.isbn())
.text:00F61450 loc_F61450:
.text:00F61450 lea eax, [ebp+trans]
.text:00F61453 push eax ; Src
.text:00F61454 lea ecx, [ebp+trans_isbn]
.text:00F6145A call isbn
.text:00F6145F lea eax, [ebp+total]
.text:00F61462 mov byte ptr [ebp+var_4], 2
.text:00F61466 push eax ; Src
.text:00F61467 lea ecx, [ebp+total_isbn]
.text:00F6146A call isbn
······
.text:00F614B8 mov al, [edx]
.text:00F614BA cmp al, [ecx]
.text:00F614BC jnz short loc_F614E5
······
total += trans;
.text:00F61569 movsd xmm0, [ebp+var_18]
.text:00F6156E mov eax, [ebp+var_20]
.text:00F61571 add [ebp+var_48], eax
.text:00F61574 addsd xmm0, [ebp+var_40]
.text:00F61579 jmp loc_F615B8
clang+llvm 64位反汇编
.text:00000000004014F1 lea rdi, [rbp+var_98]
.text:00000000004014F8 lea rsi, [rbp+total]
.text:00000000004014FC call strcpy
.text:0000000000401501 jmp $+5
.text:0000000000401506 lea rdi, [rbp+var_B8]
.text:000000000040150D lea rsi, [rbp+trans]
.text:0000000000401511 call strcpy
.text:0000000000401516 jmp $+5
.text:000000000040151B lea rdi, [rbp+var_98]
.text:0000000000401522 lea rsi, [rbp+var_B8]
.text:0000000000401529 call string_equals
.text:000000000040152E mov [rbp+var_E2], al
.text:0000000000401534 jmp $+5
.text:0000000000401539 lea rdi, [rbp+var_B8]
.text:0000000000401540 call __ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev ; std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string()
.text:0000000000401545 lea rdi, [rbp+var_98]
.text:000000000040154C call __ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev ; std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string()
.text:0000000000401551 mov al, [rbp+var_E2]
.text:0000000000401557 test al, 1
.text:0000000000401559 jnz loc_401564
.text:000000000040155F jmp loc_4015D2
llvm的代码就比较清晰,但并未明显的调用成员函数。
到此结束了。