| 寄存器 |
名稱 |
常見用途(未完) |
| eax |
累加器(Accumulator) | 函數(shù)返回值
|
| ebx | 基址寄存器(Base) | 可作為存儲(chǔ)指針來使用
|
| ecx |
計(jì)數(shù)器(Counter) |
在循環(huán)和字符串操作時(shí),用來控制循環(huán)次數(shù) __thiscall中傳遞this指針 |
| edx |
數(shù)據(jù)寄存器(Data) |
|
| esp |
堆棧指針寄存器(Stack) |
|
| ebp |
基地址指針寄存器(Base) |
|
| esi |
源地址寄存器(Source Index) |
|
| edi |
目的地址寄存器(Destination) |
| push | 把一個(gè)32位的操作數(shù)壓入堆棧,這個(gè)操作會(huì)導(dǎo)致esp減4. |
| pop | 與push相反,esp加4,一個(gè)數(shù)據(jù)出棧 |
| call | 調(diào)用函數(shù)。將下一條指令的地址壓棧,然后跳轉(zhuǎn)到所調(diào)用函數(shù)的開始處,本質(zhì)相當(dāng)于push+jump |
| ret | 與call相對(duì)應(yīng),跳轉(zhuǎn)到棧頂數(shù)據(jù)所指的地址,本質(zhì)相當(dāng)于pop+jump。對(duì)于_cdecl 調(diào)用的函數(shù),通常會(huì)在ret之后進(jìn)行exp-[n],用于清理調(diào)用參數(shù)堆棧 |
| xor | 異或,常用于清零操作,例如: xor eax eax |
| lea | 取得地址(第二個(gè)參數(shù))后放入前面的寄存器中。 |
| stosw | 將eax中的數(shù)據(jù)傳送給edi,之后edi+4。常與rep一起使用,用于初始化內(nèi)存段 |
| rep | 當(dāng)eax>0時(shí),重復(fù)后面的指令 |
| jp,jl,jge | 根據(jù)eax中值與0的關(guān)系跳轉(zhuǎn) |
| cmp | 比較指令,將結(jié)果放入eax中,往往是jp,jl,jge之類跳轉(zhuǎn)指令的執(zhí)行條件 |
| 調(diào)用方式 |
簡(jiǎn)要說明 |
堆棧清理 | 參數(shù)傳遞規(guī)則 |
| _cdecl | C 編譯器的默認(rèn)調(diào)用規(guī)則 | Caller |
從右到左 |
| _stdcall | 又稱為WINAPI | Callee |
從右到左 |
| __thiscall | C++成員函數(shù)調(diào)用方式 |
Callee | this放入ecx,其他從右到左 |
| __fastcall |
Callee |
前兩個(gè)等于或者小于DWORD大小的參數(shù)放入ecx和edx,其他參數(shù)從右到左 |
;保存ebp,并把esp放入ebp中,此時(shí)ebp與esp都為這次函數(shù)調(diào)用的棧頂
push ebp
mov ebp,esp
3.在堆棧中預(yù)留一個(gè)區(qū)域用于保存局部變量。方法是將esp減少一個(gè)數(shù)值,這樣就等于壓入了一堆變量。要恢復(fù)的時(shí)候直接把esp回復(fù)成ebp保存的數(shù)據(jù)就可以了。
4.保存ebx、esi、edi到堆棧中,函數(shù)調(diào)用完成后恢復(fù)。
;把esp往下移動(dòng)一個(gè)范圍,等于在堆棧中預(yù)留一片新的空間來保存局部變量
sub esp,010h
push ebx
push esi
push edi
5.(debug版)把局部變量全部初始化為0xcccccccch.
;將保存局部變量的區(qū)域全部初始化為0xcccccccch
lea edi,[ebp-010h]
mov ecx,33h
mov eax,0xcccccccch
rep stos dword ptr [edi]
6.然后執(zhí)行函數(shù)的具體邏輯。傳入?yún)?shù)的獲取為:ebp+4為函數(shù)的返回地址;ebp+8為第一個(gè)參數(shù),ebp+12為第二個(gè)參數(shù),以此類推。
7.回復(fù)ebx、esi、edi、esp、ebp,最后返回。如果有返回值,在返回之前將保存在eax中,供調(diào)用方式用。
pop edi ;恢復(fù)edi、esi、ebx
pop esi
pop ebx
mov esp, ebp ;恢復(fù)原來的ebp和esp
pop ebp
ret
調(diào)用方:
mov eax,dword ptr [b]
push eax
move ecx,dword ptr [a]
push ecx
call myfunction
add esp,8 ;回復(fù)堆棧



cmp <條件>
jle <下一個(gè)分支>
switch的特點(diǎn)是有多個(gè)判斷。因?yàn)閟witch顯然不會(huì)判斷大于小于,所以都是je,分別跳轉(zhuǎn)到每個(gè)case處,最有一個(gè)是無條件跳轉(zhuǎn),直接跳到default處。
對(duì)于break,會(huì)增加一個(gè)無條件跳轉(zhuǎn)語句,跳轉(zhuǎn)至結(jié)尾
int i = 0;
0040B93E mov dword ptr [i],0
int j = 0;
0040B945 mov dword ptr [j],0
switch (i)
0040B94C mov eax,dword ptr [i]
0040B94F mov dword ptr [ebp-0DCh],eax
0040B955 cmp dword ptr [ebp-0DCh],0
0040B95C je wmain+49h (40B969h) ;判斷case 1
0040B95E cmp dword ptr [ebp-0DCh],1
0040B965 je wmain+52h (40B972h) ;判斷case 2
0040B967 jmp wmain+59h (40B979h) ;跳轉(zhuǎn)到default
{
case 0:
j = 0;
0040B969 mov dword ptr [j],0
break; ;跳轉(zhuǎn)到結(jié)束
0040B970 jmp wmain+60h (40B980h)
case 1:
j = 1;
0040B972 mov dword ptr [j],1
default:
j = 3;
0040B979 mov dword ptr [j],3
}
return 0;
0040B980 xor eax,eax
cmp
je標(biāo)志著可能是swith語句
對(duì)于以下代碼:
struct A
{
int a;
int b;
int c;
};
int wmain(int argc, wchar_t* argv[])
{
A ar[3];
for (int i=0;i<3;++i)
{
ar[i].a = 0;
ar[i].b = 0;
ar[i].c = 0;
}
return 0;
}for循環(huán)中所對(duì)應(yīng)的匯編為
對(duì)于結(jié)構(gòu)體數(shù)組的訪問有個(gè)很明顯的特征:使用imul取得某個(gè)數(shù)組元素的地址偏移,然后在加上所要訪問結(jié)構(gòu)體成員的地址偏移。同時(shí),大多數(shù)情況下結(jié)構(gòu)的的大小都是在編譯期決定的,imul的最后一個(gè)參數(shù)會(huì)是個(gè)常量。
首先F(function)類指令:是函數(shù)調(diào)用相關(guān)代碼,這些代碼用于函數(shù)或者作為一個(gè)函數(shù)數(shù)被調(diào)用。幾乎凡是堆棧操作(備份集陳啟或者壓入?yún)?shù))可全部歸入此類。此外還有call指令、堆棧恢復(fù)。
然后C(control)類指令 :設(shè)計(jì)判斷和跳轉(zhuǎn)指令,以及對(duì)循環(huán)變量操作的指令。這些代碼用于循環(huán)、判斷語句。
剩余D(data)類指令:數(shù)據(jù)處理指令,應(yīng)該不包含函數(shù)調(diào)用,多半不含有堆操作,也不會(huì)含有跳轉(zhuǎn)。
2.翻譯D類指令。
3.表達(dá)式的合并與控制流程的結(jié)合。
Reference:
學(xué) Win32 匯編[29] - 串指令: MOVS*、CMPS*、SCAS*、LODS*、REP、REPE、REPNE 等
《天書夜讀-從匯編語言到Windows內(nèi)核編程》
1.下載并安裝最新的Debugging
Tools for Windows。
2.在系統(tǒng)Path環(huán)境變量中添加Debugging
Tools for Windows的安裝路徑。
3.在系統(tǒng)環(huán)境變量中創(chuàng)建_NT_SYMBOL_PATH項(xiàng)并設(shè)置為SRV*E:\SymbolServer
\OSSymbols*http://msdl.microsoft.com/download/symbols;E:\SymbolServer\MySymbols;C:\WINNT\Symbsols
其中,SRV是告訴調(diào)試器加載symsrv.dll并將后面的執(zhí)作為參數(shù),E:\SymbolServer\OSSymbols是我為操作系統(tǒng)符號(hào)設(shè)置的 目錄,http://msdl.microsoft.com/download/symbols告訴調(diào)試器如果沒有找到所需的符號(hào)就到這個(gè)地址去下 載,E:\SymbolServer\MySymbols是我自己程序的符號(hào)目錄,C:\WINNT\Symbsols中有net2005的C- RunTime
Library和MFC的PDB文件.
我是使用得本機(jī)作為符號(hào)服務(wù)器,當(dāng)然也可以使用專門架設(shè)一臺(tái)服務(wù)器作為符號(hào)服務(wù)器,只要將_NT_SYMBOL_PATH中的路徑設(shè)置為遠(yuǎn)程路徑就可以.注意你要對(duì)符號(hào)服務(wù)器有讀寫權(quán)限.
See also:
Debugging
Tools and Symbols: Getting Started
MSDN2001中關(guān)于symbol文件的相關(guān)介紹和MSDN中Matt
Pietrek的文章------最好還是下載DDK
使用
Minidumps 和
Visual Studio .NET 進(jìn)行崩潰后調(diào)試
Debug Tips at
codeproject
簡(jiǎn)單建立自己的符號(hào)服務(wù)器(symstore使用說明)
MS DLL Help Database