免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
VS2008查看匯編代碼
了解反匯編的一些小知識對于我們在開發(fā)軟件時進行編程與調試大有好處,下面以VS2008環(huán)境下的VC++簡單介紹一下反匯編的一些小東西!如果有些解釋有問題的地方,希望大家能夠指出。
1、新建簡單的VC控制臺應用程序(對此熟悉的同學可以略過)
A、打開Microsoft Visual Studio 2008,選擇主菜單“File”
B、選擇子菜單“New”下面的“Project”,打開“New Project”對話框。
C、左邊選擇Visual C++下的win32,右邊選擇Win32 Console Application,然后輸入一個工程名,點擊“OK”即可,在出現(xiàn)的向導中,一切默認,點擊Finish即可。
D、在出現(xiàn)的編輯區(qū)域內會出現(xiàn)以你設定的工程名命名的CPP文件。內容如下:
      #include "stdafx.h"
      int _tmain(int argc, _TCHAR* argv)
      {
            return 0;
      }
2、VS查看匯編代碼
A、VC處于調試狀態(tài)才能看到匯編指令窗口。因此,可以在 return 0 上設置一個斷點:把光標移到 return 0 那一行上,然后按下F9鍵設置一個斷點。
B、按下F5鍵進入調試狀態(tài),當程序停在 return 0 這一行上時,打開菜單“Debug”下的“Windows”子菜單,選擇“Disassembly”。這樣,出現(xiàn)一個反匯編的窗口,顯示下面的信息:
--- d:/my documents/visual studio 2008/projects/casmtest/casmtest/casmtest_main.cpp
// CAsmTest.cpp : 定義控制臺應用程序的入口點。
//
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv)
{
00411370  push        ebp  
00411371  mov         ebp,esp
00411373  sub         esp,0C0h
00411379  push        ebx  
0041137A  push        esi  
0041137B  push        edi  
0041137C  lea         edi,
00411382  mov         ecx,30h
00411387  mov         eax,0CCCCCCCCh
0041138C  rep stos    dword ptr es:
return 0;
0041138E  xor         eax,eax
}
00411390  pop         edi  
00411391  pop         esi  
00411392  pop         ebx  
00411393  mov         esp,ebp
00411395  pop         ebp  
00411396  ret   
上面就是系統(tǒng)生成的main函數(shù)原型,確切的說是_tmain()的反匯編的相關信息,相信學過匯編語言的肯定就能夠了解它所做的操作了。
3、簡單了解一下常見的匯編指令
為了照顧到沒學過匯編程序的同志們,這里簡單介紹一下常見的幾種匯編指令。
A、add:加法指令,第一個是目標操作數(shù),第二個是源操作數(shù),格式為:目標操作數(shù) = 目標操作數(shù) + 源操作數(shù)。
B、sub:減法指令,格式同 add。
C、call:調用函數(shù),一般函數(shù)的參數(shù)放在寄存器中。
D、ret:跳轉會調用函數(shù)的地方。對應于call,返回到對應的call調用的下一條指令,若有返回值,則放入eax中。
E、push:把一個32位的操作數(shù)壓入堆棧中,這個操作在32位機中會使得esp被減4(字節(jié)),esp通常是指向棧頂?shù)模ㄟ@里要指出的是:學過單片機的同學請注意單片機種的堆棧與Windows下的堆棧是不同的,請參考相應資料),這里頂部是地址小的區(qū)域,那么,壓入堆棧的數(shù)據(jù)越多,esp也就越來越小。
F、pop:與push相反,esp每次加4(字節(jié)),一個數(shù)據(jù)出棧。pop的參數(shù)一般是一個寄存器,棧頂?shù)臄?shù)據(jù)被彈出到這個寄存器中。
一般不會把sub、add這樣的算術指令,以及call、ret這樣的跳轉指令歸入堆棧相關指令中。但是實際上在函數(shù)參數(shù)傳遞過程中,sub和add最常用來操作堆棧;call和ret對堆棧也有影響。
G、mov:數(shù)據(jù)傳送。第一個參數(shù)是目的操作數(shù),第二個參數(shù)是源操作數(shù),就是把源操作數(shù)拷貝到目的一份。
H、xor:異或指令,這本身是一個邏輯運算指令,但在匯編指令中通常會見到它被用來實現(xiàn)清零功能。用 xor eax,eax這種操作來實現(xiàn) mov eax,0,可以使速度更快,占用字節(jié)數(shù)更少。
I、lea:取得第二個參數(shù)地址后放入到前面的寄存器(第一個參數(shù))中。
然而lea也同樣可以實現(xiàn)mov的操作,例如:
                                  lea edi,
方括號表示存儲單元,也就是提取方括號中的數(shù)據(jù)所指向的內容,然而lea提取內容的地址,這樣就實現(xiàn)了把(ebx-0ch)放入到了edi中,但是mov指令是不支持第二個操作數(shù)是一個寄存器減去一個數(shù)值的。
J、stos:串行存儲指令,它實現(xiàn)把eax中的數(shù)據(jù)放入到edi所指的地址中,同時edi后移4個字節(jié),這里的stos實際上對應的是stosd,其他的還有stosb,stosw分別對應1,2個字節(jié)。
K、jmp:無條件跳轉指令,對應于大量的條件跳轉指令。
L、jg:條件跳轉,大于時成立,進行跳轉,通常條件跳轉之前會有一條比較指令(用于設置標志位)。
M、jl:小于時跳轉。
N、jge:大于等于時跳轉。
O、cmp:比較大小指令,結果用來設置標志位。
4、函數(shù)參數(shù)傳遞方式
函數(shù)調用規(guī)則指的是調用者和被調用函數(shù)間傳遞參數(shù)及返回參數(shù)的方法,在Windows上,常用的有Pascal方式、WINAPI方式(_stdcall)、C方式(_cdecl)。
A、_cdecl C調用規(guī)則:
(a)參數(shù)從右到左進入堆棧;
(b)在函數(shù)返回后,調用者要負責清除堆棧,這種調用方式通常會生成較大的可執(zhí)行程序。
B、_stdcall又稱為WINAPI,調用規(guī)則如下:
(a)參數(shù)從右到左進入堆棧;
(b)被調用的函數(shù)在返回前自行清理堆棧,這種方式生成的代碼比cdecl小。
C、Pascal調用規(guī)則(主要用于Win16函數(shù)庫中,現(xiàn)在基本不用):
(a)參數(shù)從左到右進入堆棧;
(b)被調用的函數(shù)在返回前自行清理堆棧。
(c)不支持可變參數(shù)的函數(shù)調用。
5、VC中訪問無效變量出錯原因
我們看上面主函數(shù)反匯編后的其中一段代碼如下:
0041137C  lea         edi,
00411382  mov         ecx,30h
00411387  mov         eax,0CCCCCCCCh
0041138C  rep stos    dword ptr es:
從代碼的表面上看,它是實現(xiàn)把從ebp-0C0h開始的30h個字的空間寫入0CCCCCCCCh。其中eax為四位的數(shù)據(jù),這樣可以計算:
                      0C0h = 30h * 4
也就是把從ebp-0C0h 到ebp之間的空間初始化為0CCCCCCCCh。大家在學習反匯編的過程中會發(fā)現(xiàn),其實編譯器會根據(jù)情況把相應長度的這樣一段作為局部變量的空間,而這里把局部變量區(qū)域全都初始化成0CCCCCCCCh也是有其用意的,做VC編程的工作者,特別是初學者可能不會對0CCCCCCCCh這個常量陌生。0cch實際上是int 3指令的機器碼,這是一個斷點中斷指令(在反編譯出的信息中大家會看到int 3),因為局部變量不可被執(zhí)行,或者如果在沒有初始化的時候進行了訪問,則就會出現(xiàn)訪問失敗錯誤。這個在VC編譯Debug版本中才能看到提示這個錯誤,在Release版本中,會以另外一種錯誤形式體現(xiàn)。下面,我們修改主程序看下new與delete的反匯編的效果(注釋直接加到反匯編的代碼中了)。
VC生成工程,寫入源代碼如下:
(1)情況1
// ASM_Test.cpp : Defines the entry point for the console application.                    (  源代碼1 )
//
#include "stdafx.h"
#include "stdlib.h"
int _tmain(int argc, _TCHAR* argv)
{
    int *pTest = new int(3);                //定義一個整型指針,并初始化為 3
    printf( "*pTest = %d/r/n", *pTest );    //調用庫函數(shù)printf輸出數(shù)據(jù)
    delete pTest;                            //刪除這個指針
    return 0;
}
這里僅僅看下在new與delete進行空間管理時進行反匯編時可能出現(xiàn)的一些情況,我們把上面源代碼稱為源代碼(1),我們按照前面講解的查看VS下反匯編的方法可以看到對應于上面代碼的反匯編代碼如下:
--- f:/mysource/asm_test/asm_test/asm_test.cpp ---------------------------------                      ( 反匯編代碼 1)
// ASM_Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
int _tmain(int argc, _TCHAR* argv)
{
;(1)函數(shù)預處理部分
004113C0  push        ebp  
004113C1  mov         ebp,esp ;保存堆棧的棧頂位置
004113C3  sub         esp,0E8h ;要置為0CCCCCCCCh 保留變量空間長度
004113C9  push        ebx       ;保存寄存器ebx、esi、edi
004113CA  push        esi  
004113CB  push        edi  
004113CC  lea         edi,    ;提出要置為0CCCCCCCCh 的空間起始地址
004113D2  mov         ecx,3Ah      ;要置為0CCCCCCCCh 的個數(shù),每個占4個字節(jié)
004113D7  mov         eax,0CCCCCCCCh  ;于是3Ah * 4 = 0E8h
004113DC  rep stos    dword ptr es:  ;進行置為0CCCCCCCCh操作
;(2)定義一個int 型指針,分配空間后,并初始化為 3 ,
    int *pTest = new int(3);                //定義一個整型指針,并初始化為 3
004113DE  push        4    ;要分配的空間長度,會根據(jù)定義的數(shù)據(jù)類型而不同
004113E0  call        operator new (411186h)   ;分配空間,并把分配空間的起始地址放入eax中
004113E5  add         esp,4    ;由于new與delete函數(shù)本身沒有對棧進行彈出操作,所以,要編寫者自己處理
004113E8  mov         dword ptr ,eax  ;比較分配的空間是否為0,如果為0
004113EE  cmp         dword ptr ,0
004113F5  je          wmain+51h (411411h)
004113F7  mov         eax,dword ptr       ;對于分配的地址分配空間進行賦值為:3
004113FD  mov         dword ptr ,3
00411403  mov         ecx,dword ptr  
00411409  mov         dword ptr ,ecx   ;似乎用和作為了中間存儲單元
0041140F  jmp         wmain+5Bh (41141Bh)
00411411  mov         dword ptr ,0     ;上面分配空間失敗是的操作
0041141B  mov         edx,dword ptr  
00411421  mov         dword ptr ,edx           ;數(shù)據(jù)最后送入pTest變量中
;調用printf函數(shù)進行數(shù)據(jù)輸出
    printf( "*pTest = %d/r/n", *pTest );    //調用庫函數(shù)printf輸出數(shù)據(jù)
00411424  mov         esi,esp   ;用于調用printf后的Esp檢測,不明白編譯器為什么這樣做
00411426  mov         eax,dword ptr    ;提取要打印的數(shù)據(jù),先是地址,下面一條是提取具體數(shù)據(jù)
00411429  mov         ecx,dword ptr  
0041142B  push        ecx         ;兩個參數(shù)入棧
0041142C  push        offset string "*pTest = %d/r/n" (41573Ch)
00411431  call        dword ptr       ;調用函數(shù)
00411437  add         esp,8         ;由于庫函數(shù)無出棧管理操作,同new與delete,所以要加 8,進行堆棧處理
0041143A  cmp         esi,esp        ;對堆棧的棧頂進行測試
0041143C  call        @ILT+325(__RTC_CheckEsp) (41114Ah)
;進行指針變量的清理工作
    delete pTest;                            //刪除這個指針
00411441  mov         eax,dword ptr    ; 中放入的是分配的地址,下面幾條指令轉悠一圈
00411444  mov         dword ptr ,eax   ;就是要把要清理的地址送入堆棧,然后調用delete函數(shù)
0041144A  mov         ecx,dword ptr  
00411450  push        ecx  
00411451  call        operator delete (411091h)
00411456  add         esp,4     ;對堆棧進行處理,同new與printf函數(shù)
;函數(shù)結束后,進行最終的清理工作
    return 0;
00411459  xor         eax,eax   ;做相應的清理工作,堆棧中保存的變量送回原寄存器
}
0041145B  pop         edi  
0041145C  pop         esi  
0041145D  pop         ebx  
0041145E  add         esp,0E8h       ;進行堆棧的棧頂判斷
00411464  cmp         ebp,esp
00411466  call        @ILT+325(__RTC_CheckEsp) (41114Ah)
0041146B  mov         esp,ebp
0041146D  pop         ebp  
0041146E  ret  
--- No source file -------------------------------------------------------------;后面不再是源代碼
在列出反匯編程序時把反匯編代碼的上下的分解注釋也列了出來,親手去查看的朋友可能會發(fā)現(xiàn)在這段代碼的之外的其他部分會有大量的int 3匯編中的中斷指令,這個是與上面的所說的0CCCCCCCCh具有一致性,這些區(qū)域是無效區(qū)域,但代碼訪問這些區(qū)域時就會出現(xiàn)非法訪問提示。當然,你應該可以想到,那個提示是可以被屏蔽掉的,你可以把這部分區(qū)域填充上數(shù)據(jù)或者修改 iint 3 調用的中斷程序。
從以上反匯編程序,我們可以發(fā)現(xiàn)幾點:
A、一些內部的庫函數(shù)是不會對堆棧進行出棧管理的,所以若要對反匯編程序進行操作時,一點要注意這一點
B、編譯器會自動的加上一些對棧頂?shù)臋z查工作,這個是我們在做VC調試時經常遇到的一個問題,就是堆棧錯誤
當然以上只是對debug版本下的程序進行反匯編,如果為release 版本,代碼就會進行大量的優(yōu)化,在理解時會有一定的難度,有興趣朋友可以試著反匯編一下,推薦大家有IDA返回工具,感覺挺好用的。
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
獻給匯編初學者-函數(shù)調用堆棧變化分析
(轉)Visual C Inline ASM 內聯(lián)匯編
Win32匯編--使用MASM
x86、arm、mips架構函數(shù)調用實例分析
匯編語言的準備知識
數(shù)據(jù)傳送指令詳解
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服