2.17 JCC指令(jcn指令)
2.17 JCC指令
通過JCC指令可以實(shí)現(xiàn)有條件跳轉(zhuǎn),而標(biāo)志寄存器是決定JCC指令是否實(shí)現(xiàn)跳轉(zhuǎn)的必要條件。所以JCC指令與標(biāo)志寄存器是溝通計(jì)算機(jī)的橋梁。
本節(jié)必須掌握的知識(shí)點(diǎn):
JCC指令的概念
標(biāo)識(shí)寄存器
JCC指令的運(yùn)用
2.17.1【什么是JCC指令】
JCC指令是什么?JCC指令表示以”J”開頭的一組指令,是JMP的衍生指令,JMP表示無條件跳轉(zhuǎn)執(zhí)行指令,而JCC指令是一組有條件跳轉(zhuǎn)執(zhí)行指令,稱為”條件執(zhí)行指令”。
為什么需要這些條件執(zhí)行指令呢?在我們一個(gè)普通的程序中,充斥著很多邏輯判斷。如一個(gè)賣票的程序,首先要判斷是否有票,然后再詢問買幾張……當(dāng)我們看到票數(shù)為0時(shí),就知道票已經(jīng)售罄,而計(jì)算機(jī)并不知道數(shù)字背后的意義,這個(gè)意義是我們?nèi)ピO(shè)定的。
計(jì)算機(jī)發(fā)展到現(xiàn)在可謂神通廣大,但它其實(shí)是很笨的,你讓它減1,它就減1,然后把結(jié)果告訴你,至于這個(gè)結(jié)果有什么意義,你不告訴它,它是沒有任何的反應(yīng)的。每賣一張票,我們需要知道還有沒有票了,如果已經(jīng)售罄,我們需要告訴買票人,已經(jīng)沒有票了;如果有票,就可以進(jìn)行下一步操作。所以我們讓計(jì)算機(jī)做這樣的事情:每賣出一張票,剩余的票數(shù)如果是0,就讓它執(zhí)行打印”票已售罄”;如果不是0,讓它執(zhí)行另一段代碼。這里邏輯判斷就需要用到”條件執(zhí)行指令”。
當(dāng)我們做運(yùn)算時(shí),結(jié)果會(huì)影響標(biāo)志寄存器的值,JCC指令就是通過標(biāo)志寄存器里的值來進(jìn)行條件判斷是否跳轉(zhuǎn)的。接下來先介紹標(biāo)志寄存器。
2.17.2【標(biāo)志寄存器】
標(biāo)志寄存器:標(biāo)志寄存器又稱為程序狀態(tài)和控制寄存器(Program Status and Control Register),主要用于記錄當(dāng)前的程序狀態(tài)。
標(biāo)志寄存器就是一個(gè)4字節(jié)的內(nèi)存,而這個(gè)4字節(jié)的內(nèi)存是在處理器(CPU)中,4字節(jié)包含32位,這32位中的每一位都有自己特定的意義,下面我們來看圖2-17-1:
圖2-17-1
標(biāo)志寄存器:EFLAGS
在本節(jié)中我們介紹CF位:進(jìn)位標(biāo)志,PF位:奇偶標(biāo)志,AF位:輔助進(jìn)位標(biāo)志,ZF位:零標(biāo)志位,SF位:符號(hào)標(biāo)志,TF位:?jiǎn)尾綐?biāo)志,DF位:方向標(biāo)志,至于剩下幾位在Windows內(nèi)核的相關(guān)課程
中會(huì)有介紹。
我們借用DTDebug.exe軟件來看一下標(biāo)志寄存器在軟件中是怎么顯示的。
在DTDebug.exe軟件中打開飛鴿軟件,如圖2-17-1所示。
圖2-17-1中,EFL代表標(biāo)志寄存器,它后面存儲(chǔ)的數(shù)據(jù)是00000202,轉(zhuǎn)換為二進(jìn)制為0000 0000 0000 0000 0000 0010 0000 0010,這些位通過結(jié)合JCC指令會(huì)有特定的意義,如果沒有JCC指令,那標(biāo)志寄存器存在就沒有什么意義了。標(biāo)志寄存器是運(yùn)算指令和JCC指令的橋梁,為什么這么說呢?因?yàn)檫\(yùn)算指令是修改標(biāo)志寄存器,而JCC指令是根據(jù)標(biāo)志寄存器來跳轉(zhuǎn)的,標(biāo)識(shí)寄存器讓運(yùn)算指令間接的控制JCC指令。下面詳細(xì)介紹標(biāo)志寄存器。
1.(第0位)進(jìn)位標(biāo)志CF(Carry Flag):如果運(yùn)算結(jié)果的最高位產(chǎn)生了一個(gè)進(jìn)位或借位,那么其值為1,否則其值為0。
在使用CF位時(shí),首先要先確定數(shù)據(jù)寬度。
第一步:輸入以下匯編指令輸入到DTDebug.exe軟件中實(shí)驗(yàn),如圖2-17-2所示:
(1) MOV AL,0xEF
ADD AL,2
(2) MOV AL,0xFE
ADD AL,2
第二步:按F8兩次,觀察CF位的變化,如圖2-17-3所示。
按兩次F8執(zhí)行完后,EAX寄存器存儲(chǔ)的數(shù)據(jù)發(fā)生了變化,變?yōu)榱?x000000F1,但CF位并沒有發(fā)生變化依然是0,因?yàn)槲覀兊牟僮鲾?shù)是存在了低8位AL寄存器中,若想改變CF位,我們需要使AL存儲(chǔ)的數(shù)據(jù)最高位產(chǎn)生進(jìn)位。
第三步:為了更直觀的體現(xiàn)出實(shí)驗(yàn)結(jié)果,我們手動(dòng)修改EAX存儲(chǔ)的數(shù)據(jù),修改為0x00000000,如圖2-17-4所示。
第四步:按F8兩次,執(zhí)行并觀察AL存儲(chǔ)的數(shù)據(jù)是否發(fā)生了進(jìn)位及CF位是否有發(fā)生變化,如圖2-17-5所示。
圖2-17-5中,按兩次F8執(zhí)行完后,發(fā)現(xiàn)EAX寄存器變?yōu)榱?,因?yàn)閿?shù)據(jù)最高位發(fā)生了進(jìn)位,CF位由0變成了1,發(fā)生了進(jìn)位。
介紹幾個(gè)與進(jìn)位相關(guān)的其他指令:
ADC指令:帶進(jìn)位加法,如果CF位為1,將相加的結(jié)果再加1。
格式:ADC r/m,r/m/imm 兩邊寬度一致,且不能同時(shí)為內(nèi)存。
例:
如果CF位為1,ADC AL,CL 的結(jié)果 = (ADD AL,CL 1),如圖2-17-6輸入指令,當(dāng)前AL寄存器存儲(chǔ)的數(shù)據(jù)為0x00,CL寄存器存儲(chǔ)的數(shù)據(jù)為0x01;
單步按F8觀察CF位和AL寄存器的變化,如圖2-17-7。
F8執(zhí)行完后發(fā)現(xiàn),CF位變成了0,AL CL應(yīng)該為0x1,但AL的值卻變成了0x2,說明CF位為1時(shí),在AL CL的基礎(chǔ)上再加1。
我們實(shí)驗(yàn)觀察當(dāng)CF位為0時(shí)會(huì)出現(xiàn)什么結(jié)果,當(dāng)前AL為0x2,CL為0x1,按F8執(zhí)行,如圖2-17-8所示。
按F8執(zhí)行完后,CF位為0時(shí),結(jié)果為AL CL=0x03。下面的SBB指令請(qǐng)大家自己動(dòng)手實(shí)驗(yàn),并自己總結(jié)得出結(jié)論。
SBB指令:帶借位減法,如果CF位為1,將相減的結(jié)果再減1。
格式:ADC r/m,r/m/imm 兩邊寬度一致,且不能同時(shí)為內(nèi)存。
例:
如果CF位為1,SBB AL,CL 的結(jié)果 = (SUB AL,CL -1);
如果CF位為0,SBB AL,CL 的結(jié)果 = (SUB AL,CL)。
2. (第2位)奇偶標(biāo)志PF(Parity Flag):如果結(jié)果的最低有效字節(jié)(least-significant byte)包含偶數(shù)個(gè)1位則該位置為1,否則置0。
【注:最低有效字節(jié):低8位】
【注:包含偶數(shù)個(gè)1位則該位置為1:指如果在低8位中1的個(gè)數(shù)為偶數(shù)則PF位則PF位變成1】
例:
MOV AL,0x02
ADD AL,0x01
第一步:輸入以上指令,當(dāng)前PF位為0,如圖2-17-9所示。
第二步:按F8兩次,如圖2-17-10所示。
看圖2-17-10,執(zhí)行F8兩次,第一次執(zhí)行指令MOV AL,0x02,F8執(zhí)行后AL存儲(chǔ)的數(shù)據(jù)變?yōu)榱?x02;第二次執(zhí)行指令A(yù)DD AL,0x1執(zhí)行后AL存儲(chǔ)的數(shù)據(jù)變?yōu)榱?x03,而此時(shí)PF位發(fā)生了變化,從0變成了1.為什么PF位會(huì)變成1哪?因?yàn)?x03轉(zhuǎn)化成二進(jìn)制位0011,1的個(gè)數(shù)為偶數(shù),PF位時(shí)奇偶校驗(yàn),當(dāng)1的個(gè)數(shù)為偶數(shù)時(shí)則PF位為1,當(dāng)1的個(gè)數(shù)為奇數(shù)時(shí)PF位為0.
了解:
利用PF位可進(jìn)行奇偶校驗(yàn)檢查:
【需要傳輸”11001110″,數(shù)據(jù)中含5個(gè)”1″,所以其奇校驗(yàn)位為”0″,同時(shí)把”11001110″傳輸給接收方,接收方收到數(shù)據(jù)后再一次計(jì)算奇偶性,”11001110″中仍然含有5個(gè)”1″,所以接收方計(jì)算出的奇校驗(yàn)位還是”0″,與發(fā)送方一致,表示在此次傳輸過程中未發(fā)送錯(cuò)誤?!?/p>
3.(第4位)輔助進(jìn)位標(biāo)志AF[Auxiliary Carry Flag],如果算術(shù)操作在結(jié)果的第3位發(fā)生進(jìn)位或借位則將該標(biāo)志置1,否則清零。這個(gè)標(biāo)志在BCD(binary-code decimal)算術(shù)運(yùn)算中被使用。【注:平時(shí)較少用到,不在深入講解。】
這里第3位是從0開始的,也就是說AF位只看第3位是否進(jìn)位。例如:
第3位 第0位
(1)MOV AL,0x08
ADD AL,0x08
第一步:輸入以上指令,如圖2-17-11所示。
第二步:按F8兩次,并觀察AF位變化,如圖2-17-12所示。
圖2-17-12中,AF位發(fā)生了變化,變成了1,說明第三位發(fā)生進(jìn)位,致使AF位發(fā)生變化。請(qǐng)大家動(dòng)手實(shí)驗(yàn)下面的2組指令,并總結(jié)出AF位變化的結(jié)果
(2)MOV AX,0x80
ADD AX,0x80
(3)MOV EAX,0X8000
ADD AX,0X8000
3. (第6位)零標(biāo)志ZF(Zero Flag),零標(biāo)志ZF用來反映運(yùn)算結(jié)果是否為0。如果運(yùn)算結(jié)果為0,則ZF位的值為1,若運(yùn)算結(jié)果不為0,則ZF位的值為0。
例:
(1) XOR EAX,EAX
第一步:輸入指令,如圖2-17-13所示。
第二步:按F8執(zhí)行,并觀察CF位變化,如圖2-17-14。
圖2-17-14中,指令XOR EAX,EAX是清零的操作,因?yàn)榘l(fā)生了清零操作導(dǎo)致ZF位發(fā)生變化。
下面一組指令自己動(dòng)手實(shí)驗(yàn)并觀察ZF位變化。
(2) MOV EAX,2
SUB EAX,2 //運(yùn)算結(jié)果為0,所以ZF標(biāo)志為1。
5、(第7位)符號(hào)標(biāo)志位SF(Sign Flag),SF符號(hào)標(biāo)志位用來反映運(yùn)算結(jié)果的符號(hào)位,與運(yùn)算結(jié)果的最高位相同?!局饕醋罡呶唬?還是1。如果最高位為0,則SF位為0;如果最高位為1,則SF位為1;】
第7位 第0位
如果數(shù)據(jù)寬度為8位,SF的值與第7位相同;
如果數(shù)據(jù)寬度為16位,SF的值與第15位相同;
如果數(shù)據(jù)寬度為32位,SF的值與第31位相同。
例:
MOV AL,7F
ADD AL,2
第一步:輸入指令,如圖2-17-15所示。
圖2-17-15中,SF位為0,我們匯編指令中設(shè)定的寄存器寬度大小為低8位。我們知道
0x7F轉(zhuǎn)化為二進(jìn)制為01111111,0x02轉(zhuǎn)化成二進(jìn)制為00000010。
我們算出來的最高位為1,那么SF位應(yīng)該變?yōu)?,我們單步走看下結(jié)果。
第二步:按F8兩次,執(zhí)行并觀察SF位變化。
看圖2-17-16中,AL存儲(chǔ)的數(shù)據(jù)為0x81轉(zhuǎn)化為二進(jìn)制10000001,最高位為1,看SF位也變?yōu)榱?,和我們得到的結(jié)果一致。以上例題只驗(yàn)證了8位,而16位、32位希望大家動(dòng)手實(shí)驗(yàn)驗(yàn)證SF位與運(yùn)算結(jié)果的最高位有關(guān)系,并總結(jié)出結(jié)論。
6、 (第11位)溢出標(biāo)志OF(Overflow Flag),OF溢出標(biāo)志用于反映有符號(hào)數(shù)加減運(yùn)算所得的結(jié)果是否溢出。如果運(yùn)算結(jié)果超過當(dāng)前運(yùn)算位數(shù)所能表示的范圍,則稱為溢出,OF的值被置為1,否則,OF的值置0。
最高位進(jìn)位CF與溢出OF的區(qū)別:
(1)CF進(jìn)位標(biāo)志表示無符號(hào)數(shù)運(yùn)算結(jié)果是否超出范圍;【可以解釋為CF位為寬度溢出位,如果所用相應(yīng)寬度的容器放不下,則CF位置為1,否則為0】
(2)OF溢出標(biāo)志表示有符號(hào)數(shù)運(yùn)算結(jié)果是否超出范圍;
溢出主要是給有符號(hào)運(yùn)算使用的,在有符號(hào)的運(yùn)算中,有如下規(guī)律:
正 正 = 正 如果結(jié)果是負(fù)數(shù),說明有溢出
負(fù) 負(fù) = 負(fù) 如果結(jié)果為正數(shù),說明有溢出
正 負(fù) 永遠(yuǎn)都不會(huì)溢出。
總結(jié):符號(hào)位相同的兩個(gè)數(shù)相加,最終結(jié)果符號(hào)位與運(yùn)算前不同,OF置1,否則置0;符號(hào)位不同不會(huì)溢出,OF置0。
前面我們學(xué)了有符號(hào)數(shù)和無符號(hào)數(shù),它們存儲(chǔ)在計(jì)算機(jī)上是沒有區(qū)別的,關(guān)鍵看使用者怎么使用。在使用無符號(hào)數(shù)時(shí),我們不用考慮它的符號(hào)位,也就不用去管符號(hào)標(biāo)志位SF位的值,但是SF位的值不管我們用不用它,都會(huì)默默地工作。
當(dāng)我們把那個(gè)數(shù)當(dāng)成有符號(hào)數(shù)時(shí),由于它的最高位為符號(hào)位,所以判斷它是否進(jìn)位,由它的次高位決定。
例:
MOV AL,7f
ADD AL,2
第一步:輸入指令,如圖2-17-17所示。
圖2-17-17中,AL為0x00,OF位為0,我們輸入的匯編指令中,0x7F轉(zhuǎn)化為二進(jìn)制為01111111設(shè)定它是正數(shù),0x02轉(zhuǎn)化成二進(jìn)制為00000010設(shè)定它是正數(shù)。
那麼根據(jù)我們之前總結(jié)出來的正 正 = 正 如果結(jié)果是負(fù)數(shù),說明有溢出。我們單步執(zhí)行看一下OF位是否有變化。
第二步:按F8兩次,執(zhí)行并觀察OF位的變化,如圖2-17-18所示。
圖2-17-18中,AL的數(shù)據(jù)為0x81,0x81轉(zhuǎn)化成二進(jìn)制為10000001,OF位變?yōu)榱?。
有時(shí)候OF位和CF位都會(huì)發(fā)生改變,自已動(dòng)手做以下例題。
例:MOV AL,0xFE
ADD AL,80
由于我們?cè)O(shè)定的是正數(shù),我們看次高位也就是第6位,如果次高位向最高位進(jìn)1則OF位為1,如果次高位向最高位進(jìn)0則OF位為0。
如果是有符號(hào)數(shù),我們看次高位也就是第6位,如果次高位向最高位進(jìn)1則OF位為0,如果次高位向最高位進(jìn)0則OF位為1。
總結(jié):由于計(jì)算機(jī)不知道什么是有符號(hào)什么是無符號(hào),所以計(jì)算機(jī)不會(huì)通過符號(hào)來判斷,所以計(jì)算機(jī)判斷的是通過,最高位,我們總結(jié)了三點(diǎn):
1、 最高位相同的兩個(gè)數(shù)作運(yùn)算,是不會(huì)改變OF位;
2、 最高位均為0的兩個(gè)數(shù)做運(yùn)算,次高位進(jìn)1則OF位為1,次高位進(jìn)0則OF位為0;
3、 最高位均為1的兩個(gè)數(shù)做運(yùn)算,次高位進(jìn)1則OF位為0,次高位進(jìn)0則OF位為1;
7、 (第10位)方向標(biāo)志DF(Direction Flag):DF位在我們介紹MOVS指令、STOS指令中介紹了用法,這里我們總結(jié)一下。
在串處理指令中,控制每次操作后ESI,EDI的增減。
如果DF位為1時(shí),字符串指令(MOVS、STOS)處理字符串從高地址到低地址,ESI、EDI的數(shù)據(jù)自減。
如果DF位為0時(shí),字符串指令(MOVS、STOS)處理字符串從低地址到高地址,ESI、EDI的數(shù)據(jù)自增。
STD(Set Director)指令用來設(shè)置DF(方向標(biāo)志位)置為1,CLD(Clear Director)指令用來設(shè)置DF(方向標(biāo)志位)置為0。
常用的標(biāo)志寄存器我們已經(jīng)介紹完了,為了驗(yàn)證”運(yùn)算指令是修改標(biāo)志寄存器,而JCC指令是根據(jù)標(biāo)志寄存器來跳轉(zhuǎn)的,標(biāo)識(shí)寄存器讓運(yùn)算指令間接的控制JCC指令。”我們接下來結(jié)合運(yùn)算指令介紹JCC指令的運(yùn)用。
說到JCC指令我們不得不提CMP指令和TEST指令。為什么要介紹這兩個(gè)指令哪?因?yàn)镃MP指令、TEST指令執(zhí)行后的結(jié)果需要JCC指令來表現(xiàn)出來。
首先介紹CMP指令,CMP指令進(jìn)行比較兩個(gè)操作數(shù)大小的指令,CMP指令的功能相當(dāng)于減法指令,只是不保存結(jié)果;
CMP指令的格式:CMP 操作對(duì)象1,操作對(duì)象2 ;詳細(xì)說明操作對(duì)象1減去操作對(duì)象2,但相減的結(jié)果不影響操作對(duì)象,它影響EFL(標(biāo)志寄存器)的CF位,ZF位,OF位,AF位,PF位。
例:
MOV EAX, 10
MOV EBX, 10
CMP EAX, EBX ;相減求出結(jié)果,為0,將1存入ZF
TEST指令在每對(duì)操作對(duì)象的對(duì)應(yīng)數(shù)據(jù)位之間進(jìn)行隱含的”與”操作,并設(shè)置標(biāo)志位,但不修改操作對(duì)象。
TEST指令的格式:TEST 操作對(duì)象1,操作對(duì)象2 ;詳細(xì)說明操作對(duì)象1與操作對(duì)象2之間的進(jìn)行按位與運(yùn)算,并設(shè)置標(biāo)志位,但不修改操作對(duì)象,它影響EFL(標(biāo)志寄存器)的CF位,ZF位,OF位,PF位。
TEST ECX,ECX (檢測(cè)ECX是否是0)
我們今天要介紹的JCC指令如下圖2-17-19所示。
首先介紹第一條,JE指令它的英文全稱為Jump if equal,中文意思為如果相等則跳轉(zhuǎn);JZ指令它的英文全稱為Jump if zero,中文意思為如果為0則跳轉(zhuǎn);緊跟著ZF=1,這條是滿足條件。當(dāng)滿足ZF=1時(shí),則JE或JZ指令跳轉(zhuǎn)。
格式:
1. JZ/JE R32/M32/IMM32 。
第一步:借用DTDebug.exe軟件打開飛鴿軟件,并輸入以下指令,如圖2-17-20所示。
MOV EAX,0x10
MOV EBX,0x10
CMP EAX,EBX
JE 0x772301E0
看圖2-17-20中,JE 0x772301E0這行指令的前面,有一個(gè)向下的箭頭,一直指到內(nèi)存地址0x772301E0這一行。如果我們執(zhí)行JE指令,若是滿足JE指令則直接跳到內(nèi)存地址0x772301E0這一行,若是不滿足JE指令則不會(huì)執(zhí)行到內(nèi)存地址0x772301E0。使JE指令跳轉(zhuǎn)滿足條件是ZF=1。
第二步:按F8兩次,如圖2-17-21所示。
第三步:按F8,執(zhí)行CMP指令,觀察寄存器EAX、EBX有沒有變化和標(biāo)識(shí)寄存器變化。
執(zhí)行完CMP指令,影響了PF位、ZF位使他們變成了1,但EAX 、EBX并沒有發(fā)生變化,只是EAX、EBX里存儲(chǔ)的數(shù)據(jù)相減后為0,滿足JE相等。所以執(zhí)行JE指令會(huì)跳轉(zhuǎn)到內(nèi)存地址0x772301E0。
第四步:按F8執(zhí)行JE指令,看是否會(huì)跳轉(zhuǎn)到內(nèi)存地址0x772301E0嗎?還會(huì)不會(huì)改變ZF位哪?如圖2-17-23所示。
看圖2-17-23所示,當(dāng)ZF位等于1時(shí)則JE指令則跳轉(zhuǎn),當(dāng)執(zhí)行CMP指令時(shí)修改了ZF位所以,滿足JE指令跳轉(zhuǎn)。
動(dòng)手實(shí)驗(yàn)一下例題,并觀察標(biāo)志位的變化。
1、
MOV EAX,0x10
MOV EBX,0x10
CMP EAX,EBX
JZ 0x772301E0(0x772301E0這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
2、
MOV EAX,0x10
MOV EBX,0x20
CMP EAX,EBX
JZ 0x772301E0(0x772301E0這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
第二條指令,JNZ指令它的英文全稱為Jump if not zero,中文意思為如果不為0則跳轉(zhuǎn);JNE指令它的英文全稱為Jump if not equal,中文意思為如果不相等則跳轉(zhuǎn);緊跟著ZF=0,這條是滿足條件。當(dāng)滿足ZF=0時(shí),則JNZ或JNE指令跳轉(zhuǎn)。
格式:
JNZ/JNE R32/M32/IMM32 。
第一步:借用DTDebug.exe軟件打開飛鴿軟件,并輸入以下指令,如圖2-17-24所示。
MOV EAX,0x10
MOV EBX,0x20
CMP EAX,EBX
JNZ 0x772301E0
看圖2-17-24中,JNZ 0x772301E0這行指令的前面,有一個(gè)向下的箭頭,一直指到內(nèi)存地址0x772301E0這一行。如果我們執(zhí)行JNZ指令,若是滿足JNZ指令則直接跳到內(nèi)存地址0x772301E0這一行,若是不滿足JNZ則不會(huì)執(zhí)行到內(nèi)存地址0x772301E0。使JNZ指令跳轉(zhuǎn)滿足條件是ZF=0。
第二步:按F8兩次,如圖2-17-25所示。
第三步:按F8,執(zhí)行CMP指令,觀察寄存器EAX、EBX有沒有變化和標(biāo)識(shí)寄存器變化,如圖2-17-26所示。
執(zhí)行完CMP指令,影響了PF位、CF位、SF位使他們變成了1,但EAX 、EBX并沒有發(fā)生變化,只是EAX、EBX里存儲(chǔ)的數(shù)據(jù)相減后不為0,ZF=0滿足JNZ指令跳轉(zhuǎn)。所以執(zhí)行JNZ指令會(huì)跳轉(zhuǎn)到內(nèi)存地址0x772301E0。
第四步:按F8執(zhí)行JNZ指令,看是否會(huì)跳轉(zhuǎn)到內(nèi)存地址0x772301E0嗎?還會(huì)不會(huì)改變ZF位哪?如圖2-17-27所示。
看圖2-17-27所示,當(dāng)ZF位等于0時(shí)則JNZ指令則跳轉(zhuǎn),當(dāng)執(zhí)行CMP指令時(shí)并沒有修改了ZF位所以,ZF位為0滿足JNZ指令跳轉(zhuǎn)。
動(dòng)手實(shí)驗(yàn)一下例題,并觀察標(biāo)志位的變化。
1、
MOV EAX,0x10
MOV EBX,0x20
CMP EAX,EBX
JNE 0x772301E0(0x772301E0這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
圖2-17-19中剩余14條的JCC指令與我們介紹的第一條JZ/JE指令和第二條JNZ/JNE指令是一樣的,只要滿足相應(yīng)指令的條件,則對(duì)應(yīng)的指令會(huì)做相應(yīng)的跳轉(zhuǎn)功能。熟練掌握?qǐng)D2-17-19,自己多動(dòng)手實(shí)驗(yàn)。
例題:
1、
MOV EAX,0x10
MOV ECX,0x09
CMP EAX,EBX
JS 0x12345678(0x12345678這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
2、
MOV EAX,0x10
MOV ECX,0x09
CMP EAX,EBX
JNS 0x12345678(0x12345678這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
3、
MOV EAX,0x10
TEST EAX,EAX
JP 0x12345678(0x12345678這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
4、
MOV AL,0x10
ADD AL,0xFF
JO 0x12345678(0x12345678這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
5、
MOV EAX,0x10
MOV ECX,0x09
CMP EAX,EBX
JNL 0x12345678(0x12345678這個(gè)跳轉(zhuǎn)地址根據(jù)實(shí)驗(yàn)情況而定)
……
以上是部分JCC相關(guān)的練習(xí),希望大家能自己多練習(xí),總結(jié)出自己對(duì)圖2-17-19中JCC指令的認(rèn)識(shí)。
練習(xí):
1、 執(zhí)行0x80-0x81后,CF位是0還是1哪?
2、 說出TEST指令和CMP指令有什么區(qū)別?
3、 TEST EAX,EBX 與 AND EAX,EBX 這兩條指令是運(yùn)行的原理是一樣的嗎?哪里不一樣?為什么?
4、 自己多找資料多做練習(xí),達(dá)到能熟練運(yùn)用JCC指令。