OD汇编指令集(不断更新)
一、快捷鍵
F7 執(zhí)行一行代碼,遇到 CALL 等子程序時會進入其中,進入后首先會停留在子程序的第一條指令上。
F8 執(zhí)行一行代碼,遇到 CALL 等子程序不進入其代碼。
F2 在顯著行設(shè)置斷點,再次按 F2 刪除斷點。
F9 F9運行調(diào)試程序,直到遇到斷點停止運行,Debug->Run。
F12 臨時暫停程序,Debug-> Pause。
二、寄存器
ESP 指向堆棧最頂端的地址。
EIP 指向當(dāng)前將要執(zhí)行的指令的地址。
EAX ECX EDX EBX ESP EBP ESI EDI EIP——32位寄存器
EAX=0x12345678 AX=0x5678——16位寄存器 AH=0x56,AL=0x78
O/歐 溢出標(biāo)志
A 輔助進位標(biāo)志/不關(guān)心
P 奇偶標(biāo)志,指令的結(jié)果用二進制表示,該二進制數(shù)中1的總個數(shù)為偶數(shù)時,P標(biāo)志被設(shè)置。
Z 零標(biāo)志,當(dāng)運算產(chǎn)生的結(jié)果為 0 時被設(shè)置。
S 符號標(biāo)志,這個標(biāo)志在運算結(jié)果為負時設(shè)置為 1。
C 進位/借位標(biāo)志,(無符號運算的結(jié)果)在超過最大數(shù)值時設(shè)置為 1 ,可能是寄存器的值。
T,D 標(biāo)志和其它
三、匯編指令
指令
1.? 寄存器或數(shù)值——查看寄存器內(nèi)容,顯示數(shù)值的十進制以及ASCII碼
NOP指令
2.替換指令:右鍵->Assemble 或 Space
3.在數(shù)據(jù)窗口查看指定內(nèi)存數(shù)據(jù):右鍵->“Go to”->“Expression”->輸入地址
4.撤銷修改的指令:選擇被替換的幾行->右鍵->“Undo Selection”
PUSH指令
5.push 401008
push [401008];內(nèi)存的倒序存儲 = push DWORD PTR DS:[401008]
不明確規(guī)定,OD認為都是4個字節(jié)內(nèi)存,DWORD
POP指令
6.POP EAX——從棧頂中取出第一個值存放到EAX中,隨后的一個值隨即變成棧頂。
PUSHAD指令
7.PUSHAD指令把所有通用寄存器的內(nèi)容按一定順序壓入到堆棧中
=push eax, push ecx, push edx, push ebx, push esp, push ebp, push esi, push edi
POPAD指令
8.POPAD指令與PUSHAD正好相反,它從堆棧中取值,并將它們放到相應(yīng)的寄存器中
=pop edi, pop esi, pop esp, pop ebx, pop edx, pop ecx, pop eax
MOV指令
9.該指令將第二個操作數(shù)賦值給第一個操作數(shù),例如:
MOV EAX, EBX;EBX值賦值給EAX。
mov [405000],eax——報錯,不能直接寫入內(nèi)存
MOVSX(帶符號擴展的傳送指令)
10.第二個操作數(shù)可能一個寄存器也可能是內(nèi)存單元,第一個操作數(shù)的位數(shù)比第二個操作數(shù)多,第二個操作數(shù)的符號位填充第一個操作數(shù)剩余部分
eax=00401008,bx=e000
movsx eax,bx
eax=ffffe000,bx=e000
16位范圍,0000-7fff 正數(shù) 8000-ffff 負數(shù)
MOVZX(帶0擴展的傳送指令)
11.MOVZX類似于前面的語句,但是這種情況下,剩余的部分不根據(jù)第二個操作數(shù)的正負來進行填充。我們這里不提供范例,因為和上面是相似的,剩余的部分總是被填充為0。
LEA(取地址指令)
12.第一個操作數(shù)是一個通用寄存器,并且第二個操作數(shù)是一個內(nèi)存單元。
lea eax,dword ptr ds:[ecx+38]
ecx=12ffb0
實質(zhì)是 eax=ecx+38
eax=12ffe8
XCHG(交換 寄存器/內(nèi)存單元 和 寄存器)
13.該指令交換兩個操作數(shù)的值;也可以使用這個指令來交換寄存器和內(nèi)存單元的值
XGHG EAX,ECX
四、數(shù)學(xué)指令
INC 和 DEC指令
14.INC EAX ; 使EAX+1
DEC EAX ; 使EAX-1
INC DWORD PTR DS:[405000]
INC WORD PTR DS:[405000]
ADD指令
ADD指令有兩個操作數(shù),相加后的結(jié)果存放到第一個操作數(shù)中。ADD EAX,1等價于INC EAX。
ADC指令(帶進位的加法)
15.兩個操作數(shù)的和加上進位標(biāo)志的值,結(jié)果存放到第一個操作數(shù)中。
SUB指令
16.這個指令與ADD剛好相反-它將第一個操作數(shù)減去第二個操作數(shù)的值存放到第一個操作數(shù)中。
SBB指令
17.該指令跟ADC正好相反,它計算兩個操作數(shù)的差值,并且還要減去進位標(biāo)志,結(jié)果存放到第一個操作數(shù)中。
MUL(無符號數(shù)的乘法)
18.有兩種乘法,第一個種是MUL,這種是無符號數(shù)乘法,只有一個操作數(shù),另一個操作數(shù)是EAX,結(jié)果存放到EDX:EAX中
MUL ECX ; EDX:EAX=EAX*ECX
IMUL(有符號數(shù)的乘法)
19.IMUL指令用法類似于MUL。操作數(shù)可以有1個 2個 或 3個
IMUL ECX; 該指令將有有符號數(shù)ECX乘以EAX,結(jié)果存放到EDX:EAX中。
IMUL EDX, DWORD PTR [EBP-18]; EDX x [EBP-18] -> EDX
IMUL EBP, DWORD PTR [ESI+74],FF800002; [ESI+74] x FF800002 -> EBP
DIV/IDIV指令
20.這兩個指令反別與MUL和IMUL相反。
DIV只有一個操作數(shù),該操作數(shù)必須是無符號數(shù),結(jié)果存放到EDX:EAX中。
IDIV指令經(jīng)常被使用。
如果是一個操作數(shù)的話,那么它和DIV類似,只不過操作數(shù)是有符號的,結(jié)果依然保存在EDX:EAX中。
兩個操作數(shù)的情況,第一個操作數(shù)除以第二個操作數(shù),結(jié)果存放到第一個操作數(shù)中。
三個操作數(shù)的情況,第二個操作數(shù)除以第三個操作數(shù),結(jié)果存放到第一個操作數(shù)中。
1- div除法指令
(1) 除數(shù): 有8位和16位兩種,在一個寄存器或內(nèi)存單元中.
(2) 被除數(shù): 默認放在AX和DX或AX中
除數(shù)為8位, 被除數(shù)為16位, 默認在AX中存放.
除數(shù)為16位, 被除數(shù)為32位, 在DX或AX中存放. AX存放低16位,DX存放高16位.
(3) 結(jié)果
除數(shù)為8位, 則AL存儲除法操作的商, AH存放余數(shù)
除數(shù)為16為, 則AX存儲除法操作的商, DX存放余數(shù)
XADD指令(交換并相加)
21.這個指令其實就是XCHG和ADD兩個簡單指令的組合,相加的結(jié)果放到第1個操作數(shù)中。
NEG指令
22.取補指令,負數(shù)的補碼是取反再加1,正數(shù)的補碼是它本身;
邏輯指令
邏輯指令有兩個操作數(shù),兩操作數(shù)按位運算,并將結(jié)果存放到第一個操作數(shù)中。
AND OR XOR(同為零,異為一) NOT(按位取反)
ebx=38 neg ffffffc8
neg != not
五、比較和條件跳轉(zhuǎn)指令
CMP指令(判斷2個操作數(shù)是否相等)
23.該指令是比較兩個操作數(shù),實際上,它相當(dāng)于SUB指令,但是相減的結(jié)構(gòu)并不保存到第一個操作數(shù)中。
只是根據(jù)相減的結(jié)果來改變零標(biāo)志位的,當(dāng)兩個操作數(shù)相等的時候,零標(biāo)志位 Z 置1。
符號標(biāo)志位 S 是比較第一個操作數(shù)是否大于第二個操作數(shù)。
CMP EAX,ECX; 若EAX > ECX,則Z=0,S=0
若EAX < ECX,則Z=0,S=1
CMP AX,WORD PTR DS:[405000]
CMP AL,BYTE PTR DS:[405000]
TEST(邏輯比較)
24.該指令在一定程序上和CMP指令時類似的,兩個數(shù)值進行與操作,結(jié)果不保存,但是會改變相應(yīng)標(biāo)志位(比如說,SF,ZF,PF標(biāo)志位),程序可以根據(jù)結(jié)果來決定是否跳轉(zhuǎn)到相應(yīng)的分支。
TEST EAX,EAX; 用這個指令,可以確定EAX是否等于0。
邏輯指令
JMP - 跳轉(zhuǎn)
JE, JE - 結(jié)果為零則跳轉(zhuǎn) Z=1
JNE, JNZ - 結(jié)果不為零則跳轉(zhuǎn)
JS - 結(jié)果為負則跳轉(zhuǎn) S=1
JNS - 結(jié)果不為負則跳轉(zhuǎn)
JP, JPE - 結(jié)果中1的個數(shù)為偶數(shù)則跳轉(zhuǎn) P=1
JNP, JNPE – 結(jié)果為1的個數(shù)為奇數(shù)則跳轉(zhuǎn)
JO - 結(jié)果溢出了則跳轉(zhuǎn) O=1
JNO – 結(jié)果沒有溢出則跳轉(zhuǎn)
JB, JNAE – 小于則跳轉(zhuǎn)(無符號數(shù)) 進位/借位標(biāo)志位 C=1
JNB, JAE – 大于等于則跳轉(zhuǎn)(無符號數(shù)) C=0
JBE, JNA – 小于等于則跳轉(zhuǎn)(無符號數(shù)) C=1 或 Z=1
JNBE, JA – 大于則跳轉(zhuǎn)(無符號數(shù)) C=0 且 Z=0
JL, JNGE – 小于則跳轉(zhuǎn)(有符號數(shù)) S = 1
JNL, JGE – 大于等于則跳轉(zhuǎn)(有符號數(shù))
JLE, JNG – 小于等于則跳轉(zhuǎn)(有符號數(shù)) Z=1 或者 S!=OF
JNLE, JG – 大于則跳轉(zhuǎn)(有符號數(shù)) Z=0 或者 S=OF
SHR - 邏輯右移指令
SAR - 算術(shù)右移指令
六、循環(huán) 字符串指令和尋址方式
LOOP指令(循環(huán)指令)
25.通常循環(huán)執(zhí)行的次數(shù)放在ECX中,LOOP指令執(zhí)行時:
a.ECX = ECX-1
b.判斷ECX中的值,不為零則轉(zhuǎn)移到標(biāo)號處執(zhí)行程序,如果為零,則向下執(zhí)行。
LOOPZ,LOOPE 重復(fù)循環(huán),直到零標(biāo)志位Z置1
LOOPNZ,LOOPNE 重復(fù)循環(huán),直到零標(biāo)志位Z清0
串操作
MOVS指令(另一種形式MOVSD)
26.該指令是從一個地址向另一個地址復(fù)制數(shù)據(jù)。源地址保存在ESI寄存器中,目的地址保存在EDI寄存器中。
MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
MOVSW——拷貝兩個字節(jié)
MOVSB——拷貝一個字節(jié)
拷貝的方向取決于方向標(biāo)志位D,D=0時從后往前拷貝。
REP指令(從一個地址單元拷貝任意數(shù)目的字節(jié)內(nèi)容到另一個地址單元)
27.該指令可做為前面介紹的一些指令的前綴,尤其是MOVS指令,該前綴表示當(dāng)前指令需要執(zhí)行的次數(shù)ECX,每次循環(huán)計數(shù)器ECX的值遞減1,和前面介紹的循環(huán)一樣。
REP MOVS不一定拷貝是4個字節(jié),它拷貝的大小為【每次拷貝的大小 * ECX】,源指針ESI和目的指針EDI每次遞增4或者遞減4(遞增或遞減取決于方向標(biāo)志位D)。
REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
注:MOVS指令不能將數(shù)據(jù)拷貝到?jīng)]有寫入權(quán)限的內(nèi)存單元中,強制寫入的話會引發(fā)異常。
類似指令:REPE/REPZ/REPNZ/REPNE
SCASB,SCASW, SCASD。這三個指令把al ax eax中的值同edi尋址到的目標(biāo)內(nèi)存中的字節(jié)或字或雙字相比較。(即al,ax,eax與edi尋址后的內(nèi)存值進行比較)這些指令在一個長字符串或數(shù)組中查找一個值的時候特別有用。如果使用REPE(或REP 前綴),REP前綴是當(dāng)ecx寄存器>0時,重復(fù)。 而REPE前綴是零標(biāo)志位(zf=1), 并且ecx>0時重復(fù)。
REPNE,這個前綴剛好和REPE是反的。 也就是它是如果我們的ZF=0且ECX>0進行重復(fù),只要滿足這兩個條件它就進行重復(fù),如果不滿足則不進行重復(fù),所以REPNE一般我們用來掃描字符串。
(1) lodsb、lodsw:把DS:SI指向的存儲單元中的數(shù)據(jù)裝入AL或AX,然后根據(jù)DF標(biāo)志增減SI
(2) stosb、stosw:把AL或AX中的數(shù)據(jù)裝入ES:DI指向的存儲單元,然后根據(jù)DF標(biāo)志增減DI
(3) movsb、movsw:把DS:SI指向的存儲單元中的數(shù)據(jù)裝入ES:DI指向的存儲單元中,然后根據(jù)DF標(biāo)志分別增減SI和DI
(4) scasb、scasw:把AL或AX中的數(shù)據(jù)與ES:DI指向的存儲單元中的數(shù)據(jù)相減,影響標(biāo)志位,然后根據(jù)DF標(biāo)志分別增減SI和DI
(5) cmpsb、cmpsw:把DS:SI指向的存儲單元中的數(shù)據(jù)與ES:DI指向的存儲單元中的數(shù)據(jù)相減,影響標(biāo)志位,然后根據(jù)DF標(biāo)志分別增減SI和DI
(6) rep:重復(fù)其后的串操作指令。重復(fù)前先判斷CX是否為0,為0就結(jié)束重復(fù),否則CX減1,重復(fù)其后的串操作指令。主要用在MOVS和STOS前。一般不用在LODS前。
上述指令涉及的寄存器:段寄存器DS和ES、變址寄存器SI和DI、累加器AX、計數(shù)器CX
涉及的標(biāo)志位:DF、AF、CF、OF、PF、SF、ZF
LOOP指令
REP前綴也可以與LOOPS指令配合使用,他們會重復(fù)執(zhí)行直到計數(shù)器ECX的值為0.
LODS 指令 :取字符串?dāng)?shù)據(jù)指令(Load String Instruction)
從源地址DS:SI所指向的內(nèi)存單元開始,LODSB LODSW LODSD 取一個字節(jié)、字或雙字,送入AL、AX或EAX中,并根據(jù)標(biāo)志位DF對寄存器SI作相應(yīng)增減。該指令的執(zhí)行不影響任何標(biāo)志位。
當(dāng)方向標(biāo)志位DF=0時,則SI自動增加1、2或4;DF=1時,SI自動減小1、2或4。
STOS指令 : 置字符串?dāng)?shù)據(jù)指令(Store String Instruction)
該指令是把寄存器AL、AX或EAX中的值存于以指針ES:[DI]所指向內(nèi)存單元為起始的一片存儲單元里,并根據(jù)標(biāo)志位DF對寄存器DI作相應(yīng)增減。該指令不影響任何標(biāo)志位。
MOVS指令:字符串傳送指令(Move String Instruction)
該指令是把指針DS:SI所指向的字節(jié)、字或雙字傳送給指針ES:DI所指向內(nèi)存單元,并根據(jù)標(biāo)志位DF對寄存器DI和SI作相應(yīng)增減。該指令的執(zhí)行不影響任何標(biāo)志位。
CMPS指令
30.該指令比較ESI和EDI指向內(nèi)存單元的內(nèi)容,該指令執(zhí)行的是算數(shù)減法運算。
CMPS DWORD PTR [ESI],DWORD PTR [EDI]
該指令影響零標(biāo)志位Z,所以可以配合REPE/REPZ前綴指令使用,直到計數(shù)器ECX的值為0或者零標(biāo)志位清0.
sete cl - 設(shè)置指令,根據(jù)ZF標(biāo)志位來設(shè)置cl的值,如果ZF=1,則cl=1,否則cl=0;
七、斷點
普通斷點【B】——斷點窗口
31.當(dāng)我們設(shè)置斷點后,OD會將對應(yīng)指令處第一個字節(jié)指令替換成CC。但是為了不影響界面顯示效果,OD會將CC顯示為原字節(jié)。但是,我們可以在內(nèi)存單元中讀取出其真實的內(nèi)容,并且可以在反調(diào)試中用此方法來檢測斷點。所以,我們設(shè)置的斷點有時候莫名其妙的消失了不要感到奇怪,或許說這是調(diào)試器的本身的弱點吧。
內(nèi)存斷點
32.不能設(shè)置多個;不會出現(xiàn)【B】斷點列表和其他的地址。
33.當(dāng)我們對指定內(nèi)存單元沒有寫權(quán)限,嘗試寫入的時候會觸發(fā)異常,OD會攔截到這個異常,并中斷下來,我們看到斷下來的時候,OD已經(jīng)將內(nèi)存頁的訪問屬性設(shè)置正常了。
34.對區(qū)段設(shè)置內(nèi)存斷點【M】,嘗試執(zhí)行當(dāng)前代碼段的任何一條指令都會觸發(fā)內(nèi)存訪問斷點。
比如對Kernel32.dll設(shè)置斷點,則調(diào)用該dll中的函數(shù)GetModuleHandleA會觸發(fā)斷點,并且執(zhí)行GetModuleHandleA的每一條指令都會觸發(fā)。
35.返回主程序模塊:-Debug-Execute till user code,或者在函數(shù)返回指令處設(shè)置斷點,中斷下來后再按F7或F8單步到主程序代碼中。
硬件斷點(簡稱HBP)
36.硬件斷點分為硬件執(zhí)行斷點(ON EXECUTION),硬件寫入斷點(ON WRITE),硬件訪問斷點(ON ACCESS)3種,OD中最多設(shè)置4個硬件斷點。
硬件執(zhí)行斷點和普通的CC斷點作用一樣,但硬件執(zhí)行斷點并不會將指令首字節(jié)修改為CC,所以更難檢測。
右鍵-Breakpoint-Hardware,on execution
HE 401013
單個硬件寫入斷點或者硬件訪問斷點可以設(shè)置1,2或者4個字節(jié)的長度,不論我們選擇的數(shù)據(jù)范圍有多大,只有前4個字節(jié)會起作用。
硬件訪問/斷點斷在了觸發(fā)硬件斷點的下一條指令處。
條件斷點
EAX==400000
37.條件斷點實際上就是普通的CC斷點,只不過該斷點的觸發(fā)需要滿足設(shè)置的條件,如果滿足設(shè)置的條件,那么程序就會中斷下來,如果不滿足條件的話,就和沒有設(shè)置CC斷點差不多。
條件記錄斷點【L】——日志窗口
38.通過設(shè)置該斷點來記錄下設(shè)置的條件的精確值。
我們給一個API函數(shù)設(shè)置條件記錄斷點,程序中有很多地方調(diào)用了這個API函數(shù),通過該條件記錄斷點我們可以精確的記錄程序中每處調(diào)用該API函數(shù)傳遞給它的內(nèi)容。
如果程序中有大約100處調(diào)用了該API函數(shù),你可以指定相應(yīng)的條件,比如說返回地址。設(shè)置條件為[ESP] == 40137D,那么這100個函數(shù)調(diào)用中只有返回地址為40137D的會被記錄下來。
總結(jié)
以上是生活随笔為你收集整理的OD汇编指令集(不断更新)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 识货app如何关注好友
- 下一篇: 微机原理实验1:字符串匹配程序实验