【开坑】一个 C++ 程序的反汇编分析—— C++ 模板的威力
题目和讨论见这里https://bbs.bccn.net/thread-433453-1-1.html
程序代码:
//g++ -Wall -march=corei7-avx -Ofast -msse4.2 -mavx -std=c++1y a.cpp -lm -o a #include <iostream> #include <vector> #include <algorithm> #include <boost/iterator/counting_iterator.hpp> using std::cout; using std::endl; int main(void) { const int max_num = 100; std::vector<int> vec( boost::counting_iterator<int>(1), boost::counting_iterator<int>(max_num)); for_each (vec.begin(), vec.end(), [] (auto i) { if (i % 5 == 0 || i % 7 == 0) cout << i << endl; }); return 0; }
程序代码:
<+0>: push r15 <+2>: push r14 <+4>: push r13 <+6>: push r12 <+8>: push rbp <+9>: push rdi <+10>: push rsi <+11>: push rbx <+12>: sub rsp,0x28 // 上面的都是初始化 <+16>: call 0x4021d0 <__main> //------------------------------------------------------------------- // 下面的一段就是__main的内容 也是初始化 // 要点有两个 一个是用rip寻址 再一个是用到了repz ret // 关于这个指令有专门的文章讲 我不说了 搜一下就有 <+0>: mov eax,DWORD PTR [rip+0x516a] # 0x407340 <initialized> <+6>: test eax,eax <+8>: je 0x4021e0 <__main+16> <+10>: repz ret <+12>: nop DWORD PTR [rax+0x0] <+16>: mov DWORD PTR [rip+0x5156],0x1 # 0x407340 <initialized> <+26>: jmp 0x402170 <__do_global_ctors> //------------------------------------------------------------------- <+21>: mov ecx,0x18c <+26>: call 0x401550 <_Znwy> // 上面两句是分配空间 <+31>: mov r13,rax <+34>: mov rdx,rax <+37>: mov eax,0x1 <+42>: nop WORD PTR [rax+rax*1+0x0] // 变长空指令 <+48>: test rdx,rdx <+51>: je 0x402d77 <main()+55> <+53>: mov DWORD PTR [rdx],eax <+55>: add eax,0x1 <+58>: add rdx,0x4 <+62>: cmp eax,0x64 <+65>: jne 0x402d70 <main()+48> // boost库编译出来了上面这一段 还是比较聪明的 <+67>: lea rsi,[r13+0x18c] <+74>: mov rbx,r13 <+77>: mov rdi,QWORD PTR [rip+0x151c] # 0x4042b0 <__fu1__ZSt4cout> <+84>: mov ebp,0x92492493 <+89>: lea r12,[rip+0xffffffffffffff90] # 0x402d30 <std::ctype<char>::do_widen(char) const> <+96>: jmp 0x402dc4 <main()+132> <+98>: movsx edx,BYTE PTR [r14+0x43] <+103>: mov rcx,r15 <+106>: call 0x401558 <_ZNSo3putEc> <+111>: mov rcx,rax <+114>: call 0x401560 <_ZNSo5flushEv> <+119>: add rbx,0x4 <+123>: cmp rsi,rbx <+126>: je 0x402e60 <main()+288> <+132>: mov ecx,DWORD PTR [rbx] // 下面这个好复杂啊 总之是避免了除法。。 <+134>: mov r8d,0x66666667 <+140>: mov eax,ecx <+142>: mov r9d,ecx <+145>: imul r8d <+148>: sar r9d,0x1f <+152>: sar edx,1 <+154>: mov r8d,edx <+157>: sub r8d,r9d <+160>: lea eax,[r8+r8*4] <+164>: cmp ecx,eax <+166>: je 0x402e01 <main()+193> <+168>: mov eax,ecx <+170>: imul ebp <+172>: add edx,ecx <+174>: sar edx,0x2 <+177>: sub edx,r9d <+180>: lea eax,[rdx*8+0x0] <+187>: sub eax,edx <+189>: cmp ecx,eax <+191>: jne 0x402db7 <main()+119> <+193>: mov edx,ecx <+195>: mov rcx,rdi <+198>: call 0x401568 <_ZNSolsEi> <+203>: mov r15,rax <+206>: mov rax,QWORD PTR [rax] <+209>: mov rax,QWORD PTR [rax-0x18] <+213>: mov r14,QWORD PTR [r15+rax*1+0xf0] <+221>: test r14,r14 <+224>: je 0x402e7b <main()+315> <+226>: cmp BYTE PTR [r14+0x38],0x0 <+231>: jne 0x402da2 <main()+98> <+237>: mov rcx,r14 <+240>: call 0x401570 <_ZNKSt5ctypeIcE13_M_widen_initEv> <+245>: mov rax,QWORD PTR [r14] <+248>: mov edx,0xa <+253>: mov rax,QWORD PTR [rax+0x30] <+257>: cmp rax,r12 <+260>: je 0x402da7 <main()+103> <+266>: mov rcx,r14 <+269>: call rax <+271>: movsx edx,al <+274>: jmp 0x402da7 <main()+103> <+279>: nop WORD PTR [rax+rax*1+0x0] <+288>: mov rcx,r13 <+291>: call 0x401578 <_ZdlPv> <+296>: xor eax,eax <+298>: add rsp,0x28 <+302>: pop rbx <+303>: pop rsi <+304>: pop rdi <+305>: pop rbp <+306>: pop r12 <+308>: pop r13 <+310>: pop r14 <+312>: pop r15 <+314>: ret <+315>: call 0x401580 <_ZSt16__throw_bad_castv> <+320>: mov rbx,rax <+323>: mov rcx,r13 <+326>: vzeroupper <+329>: call 0x401578 <_ZdlPv> <+334>: mov rcx,rbx <+337>: call 0x402b30 <_Unwind_Resume>
开帖省得忘了 以后慢慢写。。
改了一下形式 直接用反汇编的罢 剩下的改天写
[ 本帖最后由 zklhp 于 2014-7-5 16:55 编辑 ]