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