|
學(xué)匯編是件很幸苦的事,那些匯編的教學(xué)書都是大磚頭,想學(xué)好匯編沒有一年半載是很難的。 但你不要害怕,事實(shí)上我們學(xué)這方面的技術(shù)純綷是為了分析遊戲,制作用,并非真的要你用匯編來編寫程序,所以不需要真的花那么多的時(shí)間去學(xué)的。本章所有內(nèi)容我要求大家用半個(gè)月來學(xué)習(xí)即可。很多東西不一定非得精通,夠用就行,未來用得多了,經(jīng)驗(yàn)自然會積累起來。 如果你有厭學(xué)癥,對這些沒興趣或不想學(xué),建議你早點(diǎn)退出這行吧,想做好一個(gè),匯編這塊不得不學(xué),不然你只能做些三流的輔助。想做高級點(diǎn)的功能,例如找怪,自動打怪,撿物,走路,加密解密等等,還有脫機(jī)程序,都得要求有一定的匯編基礎(chǔ)。
這幾節(jié)的匯編教材可能會讓你感覺很枯燥,沒事,你可以不用太認(rèn)真,只要反復(fù)的看幾次,看不懂也沒關(guān)系,只要在大腦里有個(gè)映像即可,為之后的教材打下基礎(chǔ)。
計(jì)算機(jī)的中央處理器 CPU 的架構(gòu)是非常復(fù)雜的.但我們只需要學(xué)習(xí)寄存器與匯編指令這兩方面即可.
用OD隨便打開一個(gè)EXE程序后,可以看到如下圖中顯示的那樣.可以看到各寄存器,標(biāo)志寄存器,段寄存器,棧等
![]() 調(diào)試工具OD的基本界面.
寄存器
寄存器 是 CPU 內(nèi)部的物理存儲單元,相對于CPU來說就是一些臨時(shí)變量而已,用于臨時(shí)存放數(shù)據(jù).因?yàn)榧拇嫫鞅葍?nèi)存更快,所以用匯編語言編寫程序時(shí),盡可能充分利用寄存器的存儲功能.
寄存器一般用來保存程序運(yùn)行的中間結(jié)果,為隨后的指令快速提供操作數(shù),從而避免中間結(jié)果存入內(nèi)存,再讀取內(nèi)存的操作。
另外,由于寄存器的個(gè)數(shù)和能存放數(shù)據(jù)的長度有限,不可能把所有中間結(jié)果都存儲在寄存器中.所以,要對寄存器進(jìn)行適當(dāng)?shù)氖褂谩?/div>
盡管現(xiàn)在的CPU太都已支持64位,但各種軟件還都停留在32位上,而且調(diào)試工具OD也不支持64位反匯編分析.所以這里主要介紹32位應(yīng)用.
32位寄存器組
4個(gè)數(shù)據(jù)寄存器 EAX,EBX,ECX,EDX
2個(gè)堆棧指針寄存器 ESP,EBP
2個(gè)數(shù)據(jù)指針寄存器 ESI,EDI
1個(gè)標(biāo)志寄存器 EFlags
1個(gè)指令指針寄存器 EIP
6個(gè)數(shù)據(jù)段寄存器 ES,CS,SS,DS,FS,GS
![]() 32位CPU 寄存器組的示意圖
同時(shí)一些32位寄存器里又包含著16位寄存器,16位寄存器里又包含著兩個(gè)8位寄存器
16位寄存器組
4個(gè)數(shù)據(jù)寄存器 AX,BX,CX,DX
2個(gè)堆棧指針寄存器 SP,BP
2個(gè)數(shù)據(jù)指針寄存器 SI,DI
1個(gè)標(biāo)志寄存器 Flags
1個(gè)指令指針寄存器 IP
6個(gè)數(shù)據(jù)段寄存器 ES,CS,SS,DS
事實(shí)上32位程序都是直接使用32位的內(nèi)存地址,所以上述的多個(gè)16位寄存器除AX,BX,CX,DX外基本上都用不到的,在32位的保護(hù)模式下段寄存器更是用不到了
8位寄存器組
8個(gè)數(shù)據(jù)寄存器 AH,AL,BH,BL,CH,CL,DH,DL
8位寄存器等于易語言里的字節(jié)型,能存放一個(gè)字節(jié)長的數(shù)值.
16位寄存器等于易語言里的短整數(shù)型,能存放兩個(gè)字節(jié)長的數(shù)值.
32位寄存器等于易語言里的整數(shù)型,能存放四個(gè)字節(jié)長的數(shù)值.
這些CPU中的寄存器被稱為通用寄存器
通用寄存器的作用
通用寄存器可用于傳送和暫存數(shù)據(jù),也可參與算術(shù)邏輯運(yùn)算,并保存運(yùn)算結(jié)果.除此之外,它們還各自具有一些特殊功能.大家應(yīng)熟悉每個(gè)寄存器的一般用途和特殊用途,只有這樣,才能在調(diào)試遊戲反匯編中看懂代碼.
1、數(shù)據(jù)寄存器
數(shù)據(jù)寄存器主要用來保存操作數(shù)和運(yùn)算結(jié)果等信息,從而節(jié)省讀取操作數(shù)所需占用總線和訪問存儲器的時(shí)間。
32位 CPU 有4個(gè)32位的通用寄存器 EAX , EBX , ECX , EDX .對低16位數(shù)據(jù)的存取,不會影響高16位的數(shù)據(jù).這些低16位寄存器分別命名為: AX , BX , CX , DX .它和先前的 CPU 中的寄存器相一致。
4個(gè)16位寄存器又可分割成8個(gè)獨(dú)立的8位寄存器( AX:AH - AL , BX:BH - BL , CX:CH - CL , DX:DH - DL ),每個(gè)寄存器都有自己的名稱,可獨(dú)立存取。程序員可利用數(shù)據(jù)寄存器的這種“可分可合”的特性,靈活地處理字/字節(jié)的信息。
寄存器 EAX,AX,AL 通常稱為累加器(Accumulator),用累加器進(jìn)行的操作可能需要更少時(shí)間.累加器可用于乘、除、輸入/輸出,匯編子程序返回值等操作,它們的使用頻率很高;
寄存器 EBX,BX 稱為基地址寄存器(Base Register)。它可作為存儲器指針來使用;
寄存器 ECX,CX 稱為計(jì)數(shù)寄存器(Count Register)。在循環(huán)和字符串操作時(shí),要用它來控制循環(huán)次數(shù);在位操作中,當(dāng)移多位時(shí),要用 CL 來指明移位的位數(shù);
寄存器 EDX,DX 稱為數(shù)據(jù)寄存器(Data Register)。在進(jìn)行乘、除運(yùn)算時(shí),它可作為默認(rèn)的操作數(shù)參與運(yùn)算,也可用于存放 I/O 的端口地址。
32位寄存器 EAX , EBX , ECX , EDX 不僅可傳送數(shù)據(jù)、暫存數(shù)據(jù)保存算術(shù)邏輯運(yùn)算結(jié)果,而且也可作為指針寄存器.
2 、變址寄存器
32位 CPU 有2個(gè)32位通用寄存器 ESI 和 EDI 。
寄存器 ESI , EDI 稱為變址寄存器(Index Register),它們主要用于存放某些內(nèi)存數(shù)據(jù)所在的內(nèi)存地址
作為通用寄存器,也可存儲算術(shù)邏輯運(yùn)算的操作數(shù)和運(yùn)算結(jié)果。
它們可作一般的存儲器指針使用。在字符串操作指令的執(zhí)行過程中,對它們有特定的要求,而且還具有特殊的功能。
3 、指針寄存器
32位 CPU 有2個(gè)32位通用寄存器 EBP 和 ESP 。
寄存器 EBP , ESP 稱為指針寄存器(Pointer Register),主要用于存放堆棧內(nèi)存儲單元的偏移量.用它們可實(shí)現(xiàn)多種存儲器操作數(shù)的尋址方式,為以不同的地址形式訪問存儲單元提供方便。
指針寄存器不可分割成8位寄存器。作為通用寄存器,也可存儲算術(shù)邏輯運(yùn)算的操作數(shù)和運(yùn)算結(jié)果。
它們主要用于訪問堆棧內(nèi)的存儲單元,并且規(guī)定:
ESP為堆棧指針(Stack Pointer)寄存器,用它只可訪問棧頂。
EBP為基指針(Base Pointer)寄存器,用它可直接存取堆棧中的數(shù)據(jù);
一般EBP指向的棧中數(shù)據(jù)是當(dāng)前匯編子程序執(zhí)行到返回時(shí),要跳向的指令地址.
標(biāo)準(zhǔn)的匯編子程序里常見的用[ebp+8]=子程序參數(shù)1 ,[ebp+c]=子程序參數(shù)2 ,[ebp-4]=局部整數(shù)型變量1,[ebp-8]=局部整數(shù)型變量2,以此類推.
4 、段寄存器
CS——代碼段寄存器(Code Segment Register),其值為代碼段的段值;
DS——數(shù)據(jù)段寄存器(Data Segment Register),其值為數(shù)據(jù)段的段值;
ES——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值;
SS——堆棧段寄存器(Stack Segment Register),其值為堆棧段的段值;
FS——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值;
GS——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值。
事實(shí)上我們的軟件都是運(yùn)行在CPU的保護(hù)模式下,這些段寄存器基本已經(jīng)用不到了,所以也無需去詳細(xì)了解它
5 、指令指針寄存器
指令指針 EIP (Instruction Pointer)是存放下次將要執(zhí)行的匯編指令所在的內(nèi)存地址。在具有預(yù)取指令功能的系統(tǒng)中,下次要執(zhí)行的指令通常已被預(yù)取到指令隊(duì)列中,除非發(fā)生代碼流程轉(zhuǎn)移情況。所以,在理解它們的功能時(shí),不考慮存在指令隊(duì)列的情況。
這個(gè)EIP指令指針寄存器,只需知道它是將要被執(zhí)行的下一條匯編指令的內(nèi)存地址即可.除非當(dāng)前在執(zhí)行的這條指令會跳到別處.而且我們也不能直接讀取或賦值EIP寄存器中的值.
標(biāo)志寄存器的作用
32 位 CPU 內(nèi)部有一個(gè) 32 位的標(biāo)志寄存器,它包含 13 個(gè)標(biāo)志位。這些標(biāo)志位主要用來反映處理器的狀態(tài)和運(yùn)算結(jié)果的某些特征。各標(biāo)志位在標(biāo)志寄存器內(nèi)的分布如下圖所示。
32位標(biāo)志寄存器的示意圖
上面13個(gè)標(biāo)志位可分為二組:運(yùn)算結(jié)果標(biāo)志位(有 背景色 的標(biāo)志位)和狀態(tài)控制標(biāo)志位。前者受 算術(shù)運(yùn)算 和 邏輯運(yùn)算 結(jié)果的影響,后者受一些控制指令執(zhí)行的影響。
有些指令的執(zhí)行會改變標(biāo)志位(如:算術(shù)運(yùn)算指令等),不同的指令會影響不同的標(biāo)志位,有些指令的執(zhí)行不改變?nèi)魏螛?biāo)志位(如: MOV 指令等),有些指令的執(zhí)行會受標(biāo)志位的影響(如:條件轉(zhuǎn)移指令等),也有指令的執(zhí)行不受其影響。
程序員要想熟練運(yùn)用這些標(biāo)志位,就必須掌握每個(gè)標(biāo)志位的含義,每條指令的執(zhí)行條件和執(zhí)行結(jié)果對標(biāo)志位的作用。
注意 :雖然知道每個(gè)標(biāo)志位在標(biāo)志寄存器內(nèi)的具體位置是有好處的,但通常情況下,沒有這個(gè)必要.在后面的“ 條件轉(zhuǎn)移指令 ”時(shí),系統(tǒng)會自動引用相應(yīng)標(biāo)志位的值來決定是否需要“轉(zhuǎn)移”的,所以不必過分強(qiáng)調(diào)標(biāo)志位在標(biāo)志寄存器內(nèi)的具體位置。
標(biāo)志寄存器一般配合條件轉(zhuǎn)移指令一起使用,來實(shí)現(xiàn)像易語言里的 如果真() 如果() 等功能.
運(yùn)算結(jié)果標(biāo)志位
1、進(jìn)位標(biāo)志CF(Carry Flag)
進(jìn)位標(biāo)志CF主要用來反映運(yùn)算是否產(chǎn)生進(jìn)位或借位.如果運(yùn)算結(jié)果的最高位產(chǎn)生了一個(gè)進(jìn)位或借位,那么其值為1,否則其值為0。
使用該標(biāo)志位的情況有:多字(字節(jié))數(shù)的加減運(yùn)算,無符號數(shù)的大小比較運(yùn)算,移位操作,字(字節(jié))之間移位,專門改變CF值的指令等。
2、 奇偶標(biāo)志PF(Parity Flag)
奇偶標(biāo)志PF用于反映運(yùn)算結(jié)果中“1”的個(gè)數(shù)的奇偶性。如果“1”的個(gè)數(shù)為偶數(shù),則PF的值為1,否則其值為0。
利用PF可進(jìn)行奇偶校驗(yàn)檢查,或產(chǎn)生奇偶校驗(yàn)位.在數(shù)據(jù)傳送過程中,為了提供傳送的可靠性,如果采用奇偶校驗(yàn)的方法,就可使用該標(biāo)志位。
3、 輔助進(jìn)位標(biāo)志AF(Auxiliary Carry Flag)
在發(fā)生下列情況時(shí),輔助進(jìn)位標(biāo)志AF的值被置為1,否則其值為0:
(1)、在字操作時(shí),發(fā)生低字節(jié)向高字節(jié)進(jìn)位或借位時(shí);
(2)、在字節(jié)操作時(shí),發(fā)生低4位向高4位進(jìn)位或借位時(shí)。
對以上6個(gè)運(yùn)算結(jié)果標(biāo)志位,在一般編程情況下,標(biāo)志位CF、ZF、SF和OF的使用頻率較高,而標(biāo)志位PF和AF的使用頻率較低。
4、 零標(biāo)志ZF(Zero Flag)
零標(biāo)志ZF用來反映運(yùn)算結(jié)果是否為0.如果運(yùn)算結(jié)果為0,則其值為1,否則其值為0.在判斷運(yùn)算結(jié)果是否為0時(shí),可使用此標(biāo)志位。
5、 符號標(biāo)志SF(Sign Flag)
符號標(biāo)志SF用來反映運(yùn)算結(jié)果的符號位,它與運(yùn)算結(jié)果的最高位相同.在微機(jī)系統(tǒng)中,有符號數(shù)采用補(bǔ)碼表示法,所以,SF也就反映運(yùn)算結(jié)果的正負(fù)號.運(yùn)算結(jié)果為正數(shù)時(shí),SF的值為0,否則其值為1.
6、 溢出標(biāo)志OF(Overflow Flag)
溢出標(biāo)志OF用于反映有符號數(shù)加減運(yùn)算所得結(jié)果是否溢出.如果運(yùn)算結(jié)果超過當(dāng)前運(yùn)算位數(shù)所能表示的范圍,則稱為溢出,OF的值被置為1,否則OF的值被清為0。
“溢出”和“進(jìn)位”是兩個(gè)不同含義的概念,不要混淆。
上面的這幾個(gè)狀態(tài)控制標(biāo)志基本上需要理解,因?yàn)檫@些位會被用來進(jìn)行條件轉(zhuǎn)移用.
下面的那些標(biāo)志位基本上都不必去管.非特殊情況下都是用不到的.
二、狀態(tài)控制標(biāo)志位
狀態(tài)控制標(biāo)志位是用來控制CPU操作的,它們要通過專門的指令才能使之發(fā)生改變。
1、追蹤標(biāo)志TF(Trap Flag)
當(dāng)追蹤標(biāo)志TF被置為1時(shí),CPU進(jìn)入單步執(zhí)行方式,即每執(zhí)行一條指令,產(chǎn)生一個(gè)單步中斷請求.這種方式主要用于程序的調(diào)試。
指令系統(tǒng)中沒有專門的指令來改變標(biāo)志位TF的值,但程序員可用其它辦法來改變其值。
2、 中斷允許標(biāo)志IF(Interrupt-enable Flag)
中斷允許標(biāo)志IF是用來決定CPU是否響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求.但不管該標(biāo)志為何值,CPU都必須響應(yīng)CPU外部的不可屏蔽中斷所發(fā)出的中斷請求,以及CPU內(nèi)部產(chǎn)生的中斷請求.具體規(guī)定如下:
(1)、當(dāng)IF=1時(shí),CPU可以響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求;
(2)、當(dāng)IF=0時(shí),CPU不響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求。
CPU的指令系統(tǒng)中也有專門的指令來改變標(biāo)志位IF的值。
3、 方向標(biāo)志DF(Direction Flag)
方向標(biāo)志DF用來決定在串操作指令執(zhí)行時(shí)有關(guān)指針寄存器發(fā)生調(diào)整的方向。具體規(guī)定在—字符串操作指令——中給出。在指令系統(tǒng)中,還提供了專門的指令來改變標(biāo)志位DF的值。
三 、32位標(biāo)志寄存器增加的標(biāo)志位
1、I/O特權(quán)標(biāo)志IOPL(I/O Privilege Level)
I/O特權(quán)標(biāo)志用兩位二進(jìn)制位來表示,也稱為I/O特權(quán)級字段。該字段指定了要求執(zhí)行I/O指令的特權(quán)級。如果當(dāng)前的特權(quán)級別在數(shù)值上小于等于IOPL的值,那么該I/O指令可執(zhí)行,否則將發(fā)生一個(gè)保護(hù)異常。
2、 嵌套任務(wù)標(biāo)志NT(Nested Task)
嵌套任務(wù)標(biāo)志NT用來控制中斷返回指令I(lǐng)RET的執(zhí)行。具體規(guī)定如下:
(1)、當(dāng)NT=0,用堆棧中保存的值恢復(fù)EFLAGS、CS和EIP,執(zhí)行常規(guī)的中斷返回操作;
(2)、當(dāng)NT=1,通過任務(wù)轉(zhuǎn)換實(shí)現(xiàn)中斷返回。
3、 重啟動標(biāo)志RF(Restart Flag)
重啟動標(biāo)志RF用來控制是否接受調(diào)試故障。規(guī)定:RF=0時(shí),表示“接受”調(diào)試故障,否則拒絕之。在成功執(zhí)行完一條指令后,處理機(jī)把RF置為0,當(dāng)接受到一個(gè)非調(diào)試故障時(shí),處理機(jī)就把它置為1。
4 、虛擬8086方式標(biāo)志VM(Virtual 8086 Mode)
如果該標(biāo)志的值為1,則表示處理機(jī)處于虛擬的8086方式下的工作狀態(tài),否則,處理機(jī)處于一般保護(hù)方式下的工作狀態(tài)。
注意:匯編方面的重點(diǎn)在于各寄存器的作用及下節(jié)的尋址方式,還有匯編指令。掌握了這些基本的就可以進(jìn)行調(diào)試分析遊戲,做更強(qiáng)的功能。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|