5.2 匯編語言:標(biāo)志位測試指令
匯編語言是一種面向機(jī)器的低級(jí)語言,用于編寫計(jì)算機(jī)程序。匯編語言與計(jì)算機(jī)機(jī)器語言非常接近,匯編語言程序可以使用符號(hào)、助記符等來代替機(jī)器語言的二進(jìn)制碼,但最終會(huì)被匯編器編譯成計(jì)算機(jī)可執(zhí)行的機(jī)器碼。
標(biāo)志位測試指令是匯編語言中用于測試處理器標(biāo)志位狀態(tài)的指令。標(biāo)志位是位于處理器狀態(tài)寄存器中的一組特殊標(biāo)志,用于指示上一個(gè)運(yùn)算的結(jié)果是否為零、是否進(jìn)位/借位、是否溢出等等。可以使用標(biāo)志位測試指令來檢查標(biāo)志位的狀態(tài),并在需要時(shí)根據(jù)標(biāo)志位狀態(tài)進(jìn)行操作。
常見的標(biāo)志位測試指令包括:
??test 指令:測試指定寄存器中的值與另一個(gè)值(常數(shù)或寄存器)的按位與操作結(jié)果,而不改變寄存器的值。如果結(jié)果為零,將設(shè)置零標(biāo)志位ZF。
??cmp 指令:比較兩個(gè)操作數(shù)并確定它們是否相等;如果兩個(gè)操作數(shù)相等,則設(shè)置ZF標(biāo)志位。使用此指令時(shí),通常將第一個(gè)操作數(shù)減去第二個(gè)操作數(shù),并且不需要保存差值。
??and 指令:對兩個(gè)操作數(shù)進(jìn)行逐位與操作,并將結(jié)果寫入目標(biāo)操作數(shù)。如果結(jié)果為零,將設(shè)置ZF標(biāo)志位。
??or 指令:對兩個(gè)操作數(shù)進(jìn)行逐位或操作,并將結(jié)果寫入目標(biāo)操作數(shù)。如果結(jié)果為零,將清除ZF標(biāo)志位。
??xor 指令:對兩個(gè)操作數(shù)進(jìn)行逐位異或操作,并將結(jié)果寫入目標(biāo)操作數(shù)。如果結(jié)果為零,將設(shè)置ZF標(biāo)志位。
2.1 PSR
標(biāo)志寄存器又稱程序狀態(tài)寄存器(Program Status Register,PSR),是CPU中存放處理器標(biāo)志位的寄存器。它記錄了上一個(gè)操作的結(jié)果,這些結(jié)果可以用于下一條指令的條件轉(zhuǎn)移或其他操作。標(biāo)志寄存器通常包含一些二進(jìn)制位(標(biāo)志位),每個(gè)標(biāo)志位用于表示不同的條件或狀態(tài)。不同的架構(gòu)和體系結(jié)構(gòu)會(huì)有不同的標(biāo)志位設(shè)置。
常見的標(biāo)志位包括:
??零標(biāo)志位(Zero Flag,ZF):當(dāng)上一個(gè)操作的結(jié)果為零時(shí),將設(shè)置該標(biāo)志位。
??進(jìn)位標(biāo)志位(Carry Flag,CF):當(dāng)上一個(gè)操作的結(jié)果產(chǎn)生了進(jìn)位或借位時(shí),將設(shè)置該標(biāo)志位。
??溢出標(biāo)志位(Overflow Flag,OF):當(dāng)上一個(gè)操作的結(jié)果產(chǎn)生了溢出時(shí),將設(shè)置該標(biāo)志位。
??符號(hào)標(biāo)志位(Sign Flag,SF):當(dāng)上一個(gè)操作的結(jié)果為負(fù)數(shù)時(shí)(最高位為1),將設(shè)置該標(biāo)志位。
??奇偶校驗(yàn)標(biāo)志位(Parity Flag,PF):當(dāng)上一個(gè)操作的結(jié)果具有偶數(shù)個(gè)二進(jìn)制位為1時(shí),將設(shè)置該標(biāo)志位。
這些標(biāo)志位通常用于指令的條件分支操作,例如 jz(零標(biāo)志位為真時(shí)跳轉(zhuǎn))、jnz(零標(biāo)志位為假時(shí)跳轉(zhuǎn))等。直接操作這些標(biāo)志位可能會(huì)對系統(tǒng)的運(yùn)行產(chǎn)生影響,因此在編程時(shí)應(yīng)該使用相應(yīng)的指令來讀寫標(biāo)志寄存器狀態(tài)。
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
??;?CF?進(jìn)位標(biāo)志位:?當(dāng)執(zhí)行一個(gè)加法(或減法)運(yùn)算,使最高位產(chǎn)生進(jìn)位(或借位)時(shí),CF為1;否則為0
????mov?ax,0ffffh
????add?ax,1????;?cf?=?1?af?=?1
??;?PF?奇偶標(biāo)志位:?當(dāng)運(yùn)算結(jié)果中,所有bit位(例:1001010)中1的個(gè)數(shù)為偶數(shù)時(shí),則PF=1;為基數(shù)PF=0
????mov?eax,00000000b
????add?eax,00000111b??;?pf?=?0
????
????mov?eax,00000000b
????add?eax,00000011b??;?pf?=?1
??;?ZF?零標(biāo)志位:?若當(dāng)前的運(yùn)算結(jié)果為零,則ZF=1;?否則ZF=0
????mov?eax,2
????sub?eax,2???;?zf?=?1?cf?=?0?af?=?0
??
??;?SF?符號(hào)標(biāo)志位:?若運(yùn)算結(jié)果為負(fù)數(shù),則SF=1;若為非負(fù)數(shù)則SF=0
????mov?eax,3e8h
????sub?eax,3e9h??;?sf?=?1?cf?=?1?af?=?1?zf?=?0
??
??;?DF?方向標(biāo)志位:?當(dāng)DF=0時(shí)為正向傳送數(shù)據(jù)(cld),否則為逆向傳送數(shù)據(jù)(std)
????cld
????mov?eax,1??????;?df?=?0
????std
????mov?eax,1??????;?df?=?1
??;?OF?溢出標(biāo)志位:?記錄是否產(chǎn)生了溢出,當(dāng)補(bǔ)碼運(yùn)算有溢出時(shí)OF=1;否則OF=0
????mov?al,64h
????add?al,64h?????;?of?=?1?cf?=?0?pf?=?0?af?=?0
??
????invoke?ExitProcess,0
??main?ENDP
END?main
2.2 TEST
TEST 指令是一種邏輯操作指令,用于執(zhí)行兩個(gè)操作數(shù)的逐位AND
運(yùn)算,不改變目標(biāo)操作數(shù)的值,只設(shè)置相應(yīng)的標(biāo)志位,常用于測試某些位是否被設(shè)置。
該指令的語法為:
TEST?dest,?src
其中,dest
是目標(biāo)操作數(shù),src
是源操作數(shù),兩個(gè)操作數(shù)可以是寄存器或內(nèi)存地址。
執(zhí)行TEST
指令時(shí),CPU將目標(biāo)操作數(shù)和源操作數(shù)直接逐位AND
運(yùn)算,結(jié)果并不保存到任何位置。但同時(shí),CPU會(huì)設(shè)置目標(biāo)操作數(shù)的條件碼標(biāo)志位,以反映運(yùn)算的結(jié)果。具體地,CPU會(huì)根據(jù)運(yùn)算結(jié)果將零標(biāo)志位(ZF)和進(jìn)位標(biāo)志位(CF)設(shè)置或清空,符號(hào)標(biāo)志位(SF)和溢出標(biāo)志位(OF)未定義。
TEST 指令通常用于測試某些位是否被設(shè)置,可以通過與一個(gè)掩碼進(jìn)行TEST
和來測試某一位(或一組位)是否被置位。例如,要測試寄存器eax
?是否為偶數(shù),可以使用以下代碼:
test?eax,?1
jz?even_number
在這個(gè)代碼中,使用TEST
指令將eax
和常數(shù)1逐位AND
運(yùn)算,并將結(jié)果保存到條件碼標(biāo)志位中。如果eax
的最低位為0,則ZF
處于設(shè)置狀態(tài),執(zhí)行jz
指令跳轉(zhuǎn)到even_number
標(biāo)號(hào)處,否則繼續(xù)執(zhí)行后續(xù)指令。
TEST指令可以同時(shí)檢測設(shè)置多個(gè)標(biāo)志位的值,該指令執(zhí)行時(shí)總是清除溢出標(biāo)志和進(jìn)位標(biāo)志,它修改符號(hào)標(biāo)志,基偶標(biāo)志,零標(biāo)志的方式與AND指令相同。
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
????mov?al,00001111b
????test?al,2????????????;?zf=0?pf=0
????mov?al,00100101b
????test?al,00001001b????;?zf=0?pf=0
????
????mov?al,00100100b
????test?al,00001001b????;?zf=1?pf=1
????
????mov?eax,0100h
????test?eax,eax?????????;?zf=0
????
????mov?eax,0
????test?eax,eax?????????;?zf=0
????
????or?al,80h????????????;?設(shè)置符號(hào)標(biāo)志?zf=0?pf=0?sf=1
????and?al,7fh???????????;?清除符號(hào)標(biāo)志?zf=1?pf=1?sf=0
????
????mov?al,0
????or?al,1??????????????;?清除符號(hào)標(biāo)志?zf=0?pf=0
????stc??????????????????;?設(shè)置進(jìn)位標(biāo)志?cf?=?1
????clc??????????????????;?清除進(jìn)位標(biāo)志?cf?=?0
????
????mov?al,07fh??????????;?AL?=?+127
????inc?al???????????????;?設(shè)置溢出標(biāo)志?AL?=?80h?(-128)?of=1?af=1?sf=1
????or?eax,0?????????????;?清除溢出標(biāo)志
????invoke?ExitProcess,0
??main?ENDP
END?main
2.3 CMP
CMP 指令是一種比較指令,通常用于比較兩個(gè)操作數(shù)的大小關(guān)系,并根據(jù)比較結(jié)果設(shè)置相應(yīng)的條件碼標(biāo)志位。
該指令的語法與SUB
指令相同,但是CMP
指令不會(huì)改變目標(biāo)操作數(shù)的值,只對源操作數(shù)和目標(biāo)操作數(shù)進(jìn)行逐位減法運(yùn)算,并根據(jù)運(yùn)算結(jié)果設(shè)置標(biāo)志位。具體地,CMP
指令執(zhí)行DEST - SRC
的減法運(yùn)算,但不保存結(jié)果,只把運(yùn)算結(jié)果的條件碼標(biāo)志位設(shè)置為反映運(yùn)算結(jié)果的值。
根據(jù)CMP
指令所設(shè)置的標(biāo)志位,可以通過條件跳轉(zhuǎn)指令來實(shí)現(xiàn)跳轉(zhuǎn)。例如,要判斷eax
是否為0并跳轉(zhuǎn)到標(biāo)號(hào)END
,可以使用以下代碼:
cmp?eax,?0
je?END
在這個(gè)代碼中,CMP
指令將eax
和0
相減,不保存結(jié)果,而是設(shè)置相應(yīng)的條件碼標(biāo)志位。如果eax
等于0,則ZF
處于設(shè)置狀態(tài),條件跳轉(zhuǎn)指令je
跳轉(zhuǎn)到END
標(biāo)號(hào)處。如果eax
不等于0,則ZF
處于未設(shè)置狀態(tài),不會(huì)執(zhí)行跳轉(zhuǎn)指令,而是繼續(xù)執(zhí)行后續(xù)指令。
如下代碼片段則是CMD指令的更多使用方法,讀者可自行編寫代碼進(jìn)行測試,根據(jù)注釋信息相信很容易理解。
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
????;?比較5和10
????mov?ax,5
????cmp?ax,10??????;?5-10?>?zf=0?cf=1?pf=0?af=1?sf=1
????
????;?比較兩個(gè)相同數(shù)
????mov?ax,1000
????mov?cx,1000
????cmp?cx,ax??????;?1000-1000?>?zf=1?cf=0?pf=1?sf=0
????
????;?比較100和0
????mov?ax,100
????cmp?ax,0???????;?100-0?>?zf=0?cf=0?pf=0
????
????;?比較100和50
????mov?eax,100
????mov?ebx,50
????cmp?eax,ebx????;?100-50?>?zf=0?cf=0?pf=0
????
????;?比較-100和50
????mov?eax,-100
????mov?ebx,50
????cmp?eax,ebx????;?-100-50?>?sf=1?pf=1
????
????;?比較-100和-50
????mov?eax,-100
????mov?ebx,-50
????cmp?eax,ebx????;?-100--50?>?cf=1?af=1?pf=0
??
????invoke?ExitProcess,0
??main?ENDP
END?main
2.4 JX/JNX/JSX/JPX
匯編語言中的跳轉(zhuǎn)指令可以根據(jù)條件碼標(biāo)志位來判斷條件是否成立,并根據(jù)判斷結(jié)果來跳轉(zhuǎn)到指定的地址。以下是基于特定 CPU 標(biāo)志寄存器來實(shí)現(xiàn)跳轉(zhuǎn)的常見指令及其含義:
??JZ / JE:當(dāng)零標(biāo)志位 (ZF) 為 1 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果為零。
??JNZ / JNE:當(dāng)零標(biāo)志位 (ZF) 為 0 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果不為零。
??JC / JB / JNAE:當(dāng)進(jìn)位標(biāo)志位 (CF) 為 1 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果產(chǎn)生了進(jìn)位或借位。
??JNC / JNB / JAE:當(dāng)進(jìn)位標(biāo)志位 (CF) 為 0 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果沒有產(chǎn)生進(jìn)位或借位。
??JO:當(dāng)溢出標(biāo)志位 (OF) 為 1 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果產(chǎn)生了溢出。
??JNO:當(dāng)溢出標(biāo)志位 (OF) 為 0 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果沒有產(chǎn)生溢出。
??JS:當(dāng)符號(hào)標(biāo)志位 (SF) 為 1 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果為負(fù)數(shù)。
??JNS:當(dāng)符號(hào)標(biāo)志位 (SF) 為 0 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果為非負(fù)數(shù)。
??JP / JPE:當(dāng)奇偶校驗(yàn)標(biāo)志位 (PF) 為 1 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果具有偶數(shù)個(gè)二進(jìn)制位為 1。
??JNP / JPO:當(dāng)奇偶校驗(yàn)標(biāo)志位 (PF) 為 0 時(shí)跳轉(zhuǎn),即前一個(gè)操作執(zhí)行結(jié)果不具有偶數(shù)個(gè)二進(jìn)制位為 1。
以上這些跳轉(zhuǎn)指令中,條件判斷所依賴的條件碼標(biāo)志位是由前一條指令執(zhí)行結(jié)果所決定的,因此在使用跳轉(zhuǎn)指令時(shí)需要注意前一條指令的結(jié)果是否符合預(yù)期。同時(shí),在跨過一些較大距離的內(nèi)存位置時(shí),還需要確保指令地址是否能夠被正確地計(jì)算和訪問。
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
????;?JZ/JE?當(dāng)ZF置1時(shí)?也就是結(jié)果為零則跳轉(zhuǎn)?(leftOp?-?rightOp?=?0)
????mov?eax,1
????sub?eax,1?????;?zf=1?pf=1
????je?jump
????
????mov?eax,1
????mov?ebx,1
????cmp?eax,ebx???;?zf=1
????jz?jump
????
????;?JNZ/JNE?當(dāng)ZF置0時(shí)?也就是結(jié)果不為零則跳轉(zhuǎn)?(leftOp?-?rightOp?!=?0)
????mov?eax,2
????sub?eax,1
????jnz?jump??????;?zf=0?pf=0
????
????mov?eax,2
????cmp?eax,1
????jne?jump??????;?zf=0
????
????;?JC/JNC?當(dāng)?CF=1/0?設(shè)置進(jìn)位標(biāo)志則跳/未設(shè)置進(jìn)位標(biāo)志則跳
????mov?al,0
????cmp?al,1
????jc?jump
????jnc?jump
????
????;?JO/JNO?當(dāng)?OF=1/0?設(shè)置溢出標(biāo)志則跳/未設(shè)置溢出標(biāo)志則跳
????mov?al,0ffh
????add?al,1
????jo?jump
????
????;?JS/JNS?當(dāng)?SF=1/0?設(shè)置符號(hào)標(biāo)志則跳/未設(shè)置符號(hào)標(biāo)志則跳
????mov?eax,1
????cmp?eax,1
????js?jump???????;?cf=0?af=0
????
????;?JP/JNP?PF=1/0?設(shè)置奇偶標(biāo)志則跳(偶)/未設(shè)置奇偶標(biāo)志則跳(基)
????mov?al,00100100b
????cmp?al,0
????jp?jump????????;?zp=0
??jump:
????xor?eax,eax
????xor?ebx,ebx
????
????invoke?ExitProcess,0
??main?ENDP
END?main
跳轉(zhuǎn)指令與比較指令可以很好的結(jié)合起來,通過使用cmp eax,ebx
比較等式兩邊的值,影響相應(yīng)的標(biāo)志寄存器中的值,從而決定是否要跳轉(zhuǎn),常用的如下:
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
????;?JA(無符號(hào))/JG(有符號(hào))?跳轉(zhuǎn)標(biāo)志:?(left?>?right)?大于則跳轉(zhuǎn)
????mov?eax,100
????mov?ebx,200
????cmp?ebx,eax????;?無符號(hào)?ebx?>?eax
????ja?jump????????;?zf=0?pf=0
????
????mov?eax,20
????mov?ebx,-100
????cmp?eax,ebx????;?有符號(hào)?eax?>?ebx
????jg?jump????????;?zf=0?cf=1?pf=1?af=1
????
????;?JAE(無符號(hào))/JGE(有符號(hào))?跳轉(zhuǎn)標(biāo)志:?(left?>=?right)?大于或等于則跳轉(zhuǎn)
????mov?eax,50
????mov?ebx,20
????cmp?eax,ebx????;?無符號(hào)?eax?>=?ebx
????jae?jump???????;?jae?被替換成了jnb?小于則跳?(eax<ebx)
????
????mov?eax,50
????mov?ebx,-20
????cmp?eax,ebx????;?有符號(hào)?eax?>=?ebx
????jge?jump???????;?zf=0?af=1?pf=0?sf
????
????;?JB(無符號(hào))/JL(有符號(hào))?跳轉(zhuǎn)標(biāo)志:(left?<?right)?小于則跳轉(zhuǎn)
????mov?eax,10
????mov?ebx,20
????cmp?eax,ebx?????;?無符號(hào)?eax?<?ebx
????jb?jump?????????;?cf=0?af=0?pf=1
????
????mov?eax,-10
????mov?ebx,20
????cmp?eax,ebx?????;?有符號(hào)?eax?<?ebx
????jl?jump
????
????;?JBE(無符號(hào))/JLE(有符號(hào))?跳轉(zhuǎn)標(biāo)志:(left?<=?right)?小于或等于則跳轉(zhuǎn)
????mov?eax,20
????mov?ebx,20
????cmp?eax,ebx????;?無符號(hào)?eax?<=?ebx
????jbe?jump???????;?zf=1
????
????mov?eax,-20
????mov?ebx,10
????cmp?eax,ebx????;?無符號(hào)?eax,ebx
????jle?jump???????;?sf=1
????;?JNB(不小于則跳?同JAE)/JNA(不大于則跳?同JBE)?跳轉(zhuǎn)標(biāo)志:(lef?!><?right)?無符號(hào)
????mov?eax,10
????mov?ebx,5
????cmp?eax,ebx????;?eax?!<?ebx
????jnb?jump???????;?zf=0?cf=0
????
????mov?eax,5
????mov?ebx,10
????cmp?eax,ebx????;?eax?!>?ebx
????jbe?jump???????;?cf=1?af=1?zf=0
????
????;?JNL(不小于則跳?同JGE)/JNG(不大于則跳?同JLE)?跳轉(zhuǎn)標(biāo)志:(lef?!><?right)?有符號(hào)
????mov?eax,10
????mov?ebx,-5
????cmp?eax,ebx????;?eax?!<?ebx
????jnl?jump???????;?sf=0?cf=1?pf=1?af=1?zf=0
????
????mov?eax,-10
????mov?ebx,5
????cmp?eax,ebx????;?eax?!>?ebx
????jng?jump???????;?sf=1
??jump:
????xor?eax,eax
????xor?ebx,ebx
????
????invoke?ExitProcess,0
??main?ENDP
END?main
2.5 BT/BTR/BSF/BSR
BT 系列指令主要用于對特定寄存器中的位進(jìn)行測試、清除、設(shè)置或求反等操作,這些操作通常會(huì)影響條件碼寄存器CF
的值。這些指令的具體操作如下:
??BT 指令:測試特定寄存器中的位是否為 1,將測試結(jié)果存儲(chǔ)在條件碼寄存器
CF
的最低位中,即CF
的值等于被測試位的值。??BTC 指令:將特定寄存器中的位取反,被取反的位由
CF
最低位指示,即如果CF
為1
,則對應(yīng)位取反;否則不變。??BTR 指令:將特定寄存器中的位清零,被清零的位由
CF
最低位指示,即如果CF
為1
,則對應(yīng)位清零;否則不變。??BTS 指令:將特定寄存器中的位設(shè)置為 1,被設(shè)置的位由
CF
最低位指示,即如果CF
為 1,則對應(yīng)位設(shè)置為 1;否則不變。
相比之下,BSF
和BSR
指令則是對特定數(shù)據(jù)中的位進(jìn)行正反向掃描操作,進(jìn)而得到位中第一個(gè)1
和最后一個(gè)1
的位置,這些操作通常會(huì)影響條件碼寄存器ZF
的值。這兩個(gè)指令的具體操作如下:
??BSF 指令:從寄存器或內(nèi)存中獲取一個(gè)
WORD
或DWORD
數(shù)據(jù),從低位到高位掃描,找到第一個(gè)值為1
的位,將該位的偏移量存儲(chǔ)在目標(biāo)寄存器中,并將條件碼寄存器ZF
設(shè)置為相應(yīng)的值,如果未找到值為1
的位,則目標(biāo)寄存器的值未定義,且ZF
被清零。??BSR 指令:從寄存器或內(nèi)存中獲取一個(gè)
WORD
或DWORD
數(shù)據(jù),從高位到低位掃描,找到最后一個(gè)值為1
的位,將該位的偏移量存儲(chǔ)在目標(biāo)寄存器中,并將條件碼寄存器ZF
設(shè)置為相應(yīng)的值,如果未找到值為1
的位,則目標(biāo)寄存器的值未定義,且ZF
被清零。
如下代碼片段則是指令的更多使用方法,讀者可自行編寫代碼進(jìn)行測試,根據(jù)注釋信息相信很容易理解。
??.386p
??.model?flat,stdcall
??option?casemap:none
include?windows.inc
include?kernel32.inc
includelib?kernel32.lib
.code
??main?PROC
????;?bt?普通的位測試命令
????xor?edx,edx
????mov?dx,10000001b
????bt?dx,7??????????????;?把DX第7位送入CF?=?1
????bt?dx,6??????????????;?把DX第六位送入CF?=?0
????
????;?bts?位測試并置位
????mov?dx,10000001b
????bts?dx,6?????????????;?cf?=?0
????bts?dx,7?????????????;?cf?=?1
????
????;?btr?位測試并復(fù)位.在執(zhí)行BT同時(shí),把操作數(shù)的指定位置為0
????mov?dx,10000001b
????btr?dx,7
????btr?dx,6?????????????;?cf?=?0
????
????;btc?位測試并取反.在執(zhí)行BT同時(shí),把操作數(shù)的指定位取反
????mov?dx,10000001b
????btc?dx,0?????????????;?cf?=?1
????btc?dx,0?????????????;?cf?=?0
????
????;?BSF?執(zhí)行位掃描?由低->高位?|?BSR?由高?->?到低
????xor?edx,edx
????mov?dx,?0000111100001100b
????bsf?cx,dx????????????;?正向掃描,將掃描到1的位置放入CX
????bsr?cx,dx????????????;?反向掃描?zf=0?pf=0
????
????xor?ecx,ecx
????mov?cx,0
????mov?dx,0
????bsf?cx,dx
????lahf
????invoke?ExitProcess,0
??main?ENDP
END?main
本文作者: 王瑞 本文鏈接: https://www.lyshark.com/post/3125ea93.html 版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請注明出處!