cpp逆向之旅3

自定义类的使用

#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的代码就比较清晰,但并未明显的调用成员函数。
到此结束了。

猜你喜欢

转载自blog.csdn.net/qq_35713009/article/details/85331482
今日推荐