上次我分析了一下,
debug
模式下反彙編後的演算法部分**,天才的您可能覺得不算糟,想再搞點花樣,那麼本文就能滿足你的需求。天書夜讀上其實還貼出來了
release
模式下的**,它經過
vc編譯器
o2的優化,我初次看到反彙編**時,還真汗了一把。不過定下心來細細品位還是可以看懂的,儘管正如原書所說,連語句的對應順序也已經不見了。。。
廢話不多說,先貼出**大夥「飽飽眼福」。。。
00401000 mov eax,dword ptr [esp+4]
00401004 mov edx,dword ptr [esp+0ch]
00401008 mov ecx,dword ptr [esp+8]
0040100c push ebx
0040100d push esi
0040100e add eax,4
00401011 push edi
00401012 add edx,8
00401015 mov esi,3
0040101a lea ebx,[ebx]
00401020 mov ebx,dword ptr [eax]
00401022 imul ebx,dword ptr [ecx+0ch]
00401026 mov edi,dword ptr [ecx+18h]
00401029 imul edi,dword ptr [eax+4]
0040102d add edi,ebx
0040102f mov ebx,dword ptr [eax-4]
00401032 imul ebx,dword ptr [ecx]
00401035 add edi,ebx
00401037 mov dword ptr [edx-8],edi
0040103a mov ebx,dword ptr [eax]
0040103c imul ebx,dword ptr [ecx+10h]
00401040 mov edi,dword ptr [ecx+1ch]
00401043 imul edi,dword ptr [eax+4]
00401047 add edi,ebx
00401049 mov ebx,dword ptr [eax-4]
0040104c imul ebx,dword ptr [ecx+4]
00401050 add edi,ebx
00401052 mov dword ptr [edx-4],edi
00401055 mov ebx,dword ptr [eax+4]
00401058 imul ebx,dword ptr [ecx+20h]
0040105c mov edi,dword ptr [ecx+14h]
0040105f imul edi,dword ptr [eax]
00401062 add edi,ebx
00401064 mov ebx,dword ptr [eax-4]
00401067 imul ebx,dword ptr [ecx+8]
0040106b add edi,ebx
0040106d mov dword ptr [edx],edi
0040106f add eax,0ch
00401072 add edx,0ch
00401075 dec esi
00401076 jne myfunction+20h (401020h)
00401078 pop edi
00401079 pop esi
0040107a xor eax,eax
0040107c pop ebx
**確實精簡了不少,也精簡地一點對應關係也找不到了。。。這份彙編**,比(二)中其實要完整,因為它把整個函式呼叫到返回的**都列出來了,儘管也早精簡得不是標準的函式彙編**了,由此可見
vc編譯器的優化能力之強令人嘆為觀止。。。
老規矩,對上述彙編**的部分內容先作一簡析。
第一.細心的讀者一定已經發現,(二)中的
(間接定址符)包含的都是活生生的變數名,而在
release
中已經變為暫存器的表示式,當然我們可以根據引數入棧的順序來推導出哪個是哪個,這會在後續有所說明。
第二.正常的函式呼叫過程開始都會先將
ebp入棧,而後將
ebp用作
esp的暫存暫存器,而在這裡,從頭至尾就沒有出現過
ebp,當然主要是因為
esp並沒有被函式用做特殊用途,再追溯根源一點,是因為迴圈變數
i被更高速的暫存器
esi所替代,而
j這個迴圈。。。很神奇的由於只有3次,居然被編譯器展開成三個等效計算過程給代替了。
第三.最後一點也不是很重要,就是暫存器壓棧的指令原本是放在最前的,現在又很神奇地被嵌在了資料計算語句之間。這點更加體現了經過優化的**比較不符合人的常識,但更契合高效能的需要。
現在我們從頭開始,一段段看: ;
隨著c, b, a
順序入棧,堆疊向位址減小的方向發展,故而可以容易推斷出
00401000 mov eax,dword ptr [esp+4]
; 對應a
00401004 mov edx,dword ptr [esp+0ch]
; 對應c
00401008 mov ecx,dword ptr [esp+8]
; 對應b
; 40100c, 40100d, 401011
三個指令是常規的暫存器儲存工作
0040100c push ebx
0040100d push esi ;
這裡給eax與edx分別加上乙個值的目的,後面會得知
0040100e add eax,4
00401011 push edi
00401012 add edx,8 ;
使用esi暫存器作為迴圈變數,提高執行速度
00401015 mov esi,3 ;
下面一行指令儘管看不出什麼用處,但我倒不是很贊同原書上的說法, ;
如果有哪位大俠知道,請告知下大家,謝謝
0040101a lea ebx,[ebx]
esi
迴圈體
; 可以看到,上面這個迴圈體每次處理的是a與c對應的一行資料,如上面的註解是針對第0 ;
行的情況,而下面兩個指令就是把a與c分別下移一行,即下次將處理a與c的第1行,只要 ;
把上面註解中c[0][x]改為c[1][x],a[0][y]改為a[1][y],依次類推……
0040106f add eax,0ch
00401072 add edx,0ch ;
迴圈變數esi減1,若還不為0,則迴圈未結束,跳轉後接著迴圈
00401075 dec esi
00401076 jne myfunction+20h (401020h) ;
函式結束時常規的暫存器恢復工作,依次恢復edi, esi, ebx,和儲存順序相反
00401078 pop edi
00401079 pop esi
0040107a xor eax,eax
; 返回值在
eax裡,異或運算,把
eax清零,即返回值是0
0040107c pop ebx
其實對c反彙編的技術還有很多,這裡只是舉個例子給大家起乙個拋磚引玉的作用,要完全領悟還得靠自己去學習去多多實踐。
本系列三篇文章就結束了,首先感謝《天書夜讀》的作者,另外如果由於我語文或技術水平有限導致理解有些困難的話,那我先說聲
sorry
C反彙編例項(詳細註解版)(三)
上次我分析了一下,debug 模式下反彙編後的演算法部分 天才的您可能覺得不算糟,想再搞點花樣,那麼本文就能滿足你的需求。天書夜讀上其實還貼出來了 release 模式下的 它經過 vc編譯器 o2的優化,我初次看到反彙編 時,還真汗了一把。不過定下心來細細品位還是可以看懂的,儘管正如原書所說,連語...
C反彙編例項(詳細註解版)(一)
呵,好久沒寫 csdn 文章了,來湊個熱鬧。最近我閱讀了楚狂人 wowocock 寫的 天書夜讀 試讀本,對 c反彙編感觸頗深,書中有一例演算法反彙編,其對彙編的閱讀確實富有挑戰,而該書中也未詳解,在此,我謹將此例詳細分析如下,幫助大家更好理解 c反彙編 若有任何錯誤,請大家批評指正!該例的要求是求...
C反彙編例項(詳細註解版)(二)
那麼有了上述三方面的基礎,我們就可以來逐一解讀那段 傳奇 的彙編 了。初始化i 00411a3e mov dword ptr i 0 跳轉至條件判斷 00411a45 jmp myfunction 30h 411a50h 迴圈表示式,對i每輪加1 00411a47 mov eax,dword ptr...