§ 3.3.4 邏輯運算、移位、循環(huán)指令
1、 邏輯運算指令
邏輯運算有"與(AND)"、"或(OR)"、"非(NOT)"、"異或(XOR)"、"測試(TEST)"。

(1) 邏輯"與"AND
AND dst ,src
功能:dst←dst ∧ src,目的操作數(shù)dst與源操作數(shù)src對應(yīng)位相"與",結(jié)果放在dst中。
(2) 邏輯"或"指令
OR dst ,src
功能:dst←dst ∨ src,目的操作數(shù)dst與源操作數(shù)src對應(yīng)位相"或",結(jié)果放在dst中。
(3) 邏輯"異或"指令
XOR dst ,src
功能:dst←dst ⊕ src,目的操作數(shù)dst與源操作數(shù)src對應(yīng)位相"異或",結(jié)果放在dst中。(異或:不同的數(shù)異或為1;相同的數(shù)異或為0)。
(4) 邏輯"非"指令
NOT dst
功能:dst←,目的操作數(shù)dst每一位取反后,放在dst中。
(5)"測試"指令
TEST dst,src
功能:測試dst中某些位是否為1,當(dāng)要測試dst中某些位時,在src中對應(yīng)位置1。該指令使用"與"運算進行測試,但"與"運算的結(jié)果不送給dst,而只反映在標(biāo)志ZF中。當(dāng)對應(yīng)位為1時,ZF=1;當(dāng)對應(yīng)位為0時,ZF=0。
2、 移位指令
移位操作如圖3-17所示。

SAL,SHL,SAR,SHR指令的格式相同,以SAL為例:
SAL DX,1 ; DX的值左移一位,最低位補0
SAL AX,CL ;AX的值左移CL位,最低位補0,
;CL=0,1,2,....,255
算術(shù)移位(SAL、SAR)把操作數(shù)看成有符號數(shù)。SAR指令在移位過程中保持符號位不變。SAL指令不保持符號位,但當(dāng)符號位發(fā)生變化時(最高位與CF不同),用 OF標(biāo)志置1表示出來。
邏輯左移SHL把操作數(shù)看成無符號數(shù)。
將一操作數(shù)左移一位,相當(dāng)于將其乘2。將一操作數(shù)右移一位,相當(dāng)于將其除以2。因此,可以用移位操作代替部分乘除操作,只要不產(chǎn)生溢出,這種代替是正確的。(用CF標(biāo)志判別無符號數(shù)運算是否溢出,CF=1,表示溢出。用 OF標(biāo)志判別有符號數(shù)運算是否溢出,OF=1,表示溢出)。
操作數(shù)B7H(1011 0111B)連續(xù)左移時的變化

操作數(shù)B7H(1011 0111B)連續(xù)右移時的變化

3、 循環(huán)指令
循環(huán)操作如圖3-18所示。

ROL,RCL,ROR,RCR指令的格式相同,以ROL為例:
ROL BX,1 ; BX的值循環(huán)左移一位
ROL WORD PTR [DI],CL ;內(nèi)存單元的值循環(huán)左移CL位 ;CL=0,1,2,....,255
§3.3.5 控制轉(zhuǎn)移指令
8086程序中的指令存放在內(nèi)存中的一個或幾個段中,這些段稱為代碼段,CPU執(zhí)行的下一條指令的地址由CS(代碼段基地址寄存器)和IP(指令指針)指定。CPU正在執(zhí)行的指令所在的代碼段稱為"當(dāng)前代碼段",其基地址為CS的值。代碼段的容量可達64K,IP的值為0000H~FFFFH。
一般情況下,CPU按順序執(zhí)行指令,每執(zhí)行一條指令,IP增加一個值(該值等于這條指令的長度,指指令的機器碼長度),當(dāng)IP到達一段的末尾時,改變CS的值并重新設(shè)定IP指向新段的開始。
若CPU正在執(zhí)行的指令為控制轉(zhuǎn)移指令,CPU改變執(zhí)行順序,轉(zhuǎn)移到另一處執(zhí)行。此時,IP 和/或 CS的值發(fā)生改變。
轉(zhuǎn)移指令包括:
子程序調(diào)用指令(CALL)和子程序返回指令(RET)。
無條件轉(zhuǎn)移指令(JMP)和條件轉(zhuǎn)移指令(JZ,JNZ等)。
重復(fù)(循環(huán))控制指令(LOOP,LOOPNZ等)。
中斷指令(INT n)和中斷返回指令(IRET)。
如果轉(zhuǎn)移指令只改變IP的值,不改變CS的值,即目標(biāo)指令仍在當(dāng)前代碼段中,稱為"段內(nèi)轉(zhuǎn)移"。
如果轉(zhuǎn)移指令改變IP和CS的值,即目標(biāo)指令不在當(dāng)前代碼段中,而在另一代碼段內(nèi),稱為"段間轉(zhuǎn)移"。(轉(zhuǎn)移后的代碼段成為新的當(dāng)前代碼段)。
1、 無條件控制轉(zhuǎn)移
(1) JMP指令
JMP 目標(biāo)地址
功能:無條件轉(zhuǎn)移到目標(biāo)地址。
在程序設(shè)計中,目標(biāo)地址通常用一個指令標(biāo)號來表示。
(2) 調(diào)用指令(CALL)和返回指令(RET)
CALL 目標(biāo)地址
RET [n];n為0~FFFFH之間的一個偶數(shù)
在大型程序中,有時,一段相同的程序多次被使用,可以把這段程序單獨提出來編寫,稱為"子程序",需要該段程序時,用CALL指令調(diào)用子程序,這種編程處理方法,稱為"子程序結(jié)構(gòu)",如圖19所示。

相對于子程序,調(diào)用程序稱為主程序如圖1所示。 CALL指令用在主程序中調(diào)用子程序,它使CPU轉(zhuǎn)入子程序執(zhí)行。RET用在子程序中控制CPU返回主程序,如圖20所示。
為了使CPU在執(zhí)行完子程序后,能正確地返回CALL指令的下一條指令,CALL指令必須把"返回地址"存入堆棧。RET從堆棧中取
出該返回地址,從而返回到主程序的正確位置。
如果子程序P與主程序M在同一個代碼段,稱為段內(nèi)調(diào)用,該子程序稱為NEAR型子程序;如果子程序P與主程序M不在同一個代碼段,稱為段間調(diào)用,該子程序稱為FAR型子程序。
段間調(diào)用與返回時,CALL/RET指令的操作(如圖21所示):

CALL:
?、?SP減2,把返回地址的段值(CS)推入堆棧。
② SP減2,把返回地址的偏移量(IP)推入堆棧。 ①、②兩步使RET正確返回。
?、?把子程序地址的偏移量送給IP,把子程序地址的段值送給CS。從而使CPU轉(zhuǎn)入子程序運行。
RET:
?、?從堆棧中取出返回地址的偏移量送給IP,SP加2。
② 從堆棧中取出返回地址的段值送給CS,SP加2。 從而使CPU執(zhí)行CALL指令后面的那條指令。
段內(nèi)調(diào)用與返回時,CALL/RET指令的操作:
CALL:(如圖22)

?、?SP減2,把返回地址的偏移量(IP)推入堆棧。以便RET正確返回。(不保存返回地址的段值)。
② 把子程序地址的偏移量送給IP。從而使CPU轉(zhuǎn)入子程序運行。
RET:從堆棧中取出返回地址的偏移量,送給IP,SP加2。
從而使CPU執(zhí)行CALL指令后面的那條指令。
"RET n"(n為偶數(shù))指令,除完成一般RET指令的動作外,還使SP加n。"RET n"用于有入口參數(shù)的子程序中,清除主程在執(zhí)行CALL指令之前推入堆棧的入口參數(shù)。
2、 條件控制轉(zhuǎn)移指令
條件控制轉(zhuǎn)移指令,以一個或幾個標(biāo)志位作為條件,或以CX的值作為條件,當(dāng)條件滿足時,轉(zhuǎn)移到目標(biāo)地址,否則,執(zhí)行下一條指令。
條件轉(zhuǎn)移指令的一般格式是:
JX 短目標(biāo)地址
其中,X是表示條件的1~3個字母。"短目標(biāo)地址"是指,JX指令與目標(biāo)地址之間的距離范圍為-128~+127。(區(qū)別:無條件轉(zhuǎn)移指令JMP可以跳轉(zhuǎn)到任何位置)。
條件轉(zhuǎn)移指令的中,相當(dāng)一部分指令的條件,是CMP、SUB等指令比較兩個數(shù)后,在標(biāo)志寄存器中設(shè)置的標(biāo)志位。以CMP指令為例,無符號數(shù)和有符號數(shù)比較后,設(shè)置的標(biāo)志位不同,如下表所示
"CMP dst,src"指令執(zhí)行后設(shè)置的標(biāo)志

條件轉(zhuǎn)移指令使用大于(Greater)、小于(Less)來反應(yīng)有符號數(shù)比較后設(shè)置的標(biāo)志位。使用高于(Above)、低于(Below)來反應(yīng)無符號數(shù)比較后設(shè)置的標(biāo)志位,如下表所示。

3、 重復(fù)控制指令(循環(huán)指令)
重復(fù)控制指令屬于條件轉(zhuǎn)移指令,當(dāng)條件滿足時,轉(zhuǎn)移到目標(biāo)地址,從而使重復(fù)控制指令與目標(biāo)地址之間的程序(稱為循環(huán)體)被重復(fù)執(zhí)行(循環(huán))。
(1) LOOP指令
LOOP 短目標(biāo)地址
功能:使CX的值減1后,若CX≠0,轉(zhuǎn)移到目標(biāo)地址。
注意,LOOP指令使CX減1時,不會引起標(biāo)志位的變化。
LOOP指令相當(dāng)于以下兩條指令:
DEC CX
JNZ 短目標(biāo)地址 LOOP指令使循環(huán)體執(zhí)行CX次如圖3-23所示。

當(dāng)CX被賦初值0時,循環(huán)體被執(zhí)行65536次。
(2) LOOPZ(或LOOPE)
格式:LOOPZ 短目標(biāo)地址
功能:使CX減1后,當(dāng)CX≠0且ZF=1時,轉(zhuǎn)移到目標(biāo)地址。
LOOPZ/LOOPE指令使循環(huán)體最多執(zhí)行CX次,在循環(huán)過程中,若不滿足ZF=1,將提前結(jié)束循環(huán)。
(3) LOOPNZ(或LOOPNE)
格式:LOOPNZ 短目標(biāo)地址
功能:使CX減1后,當(dāng)CX≠0且ZF=0時,轉(zhuǎn)移到目標(biāo)地址。
LOOPNZ/LOOPNE指令使循環(huán)體最多執(zhí)行CX次,在循環(huán)過程中,若不滿足ZF=0,將提前結(jié)束循環(huán)。
§ 3.3.6 串操作指令
(一) 串的概念
在匯編語言程序設(shè)計中,"串"可以是任意一段連續(xù)的內(nèi)存(1~N字節(jié))。串中的每一個值可以是字符(字符串)或數(shù)據(jù)(數(shù)據(jù)串)?!〈趦?nèi)存中的地址以串的第一字節(jié)的地址表示,如,設(shè)字符串'ABCDEF'在內(nèi)存中按如下存放,則稱該串的地址為 0724H。

(二) 串操作的特點
在匯編語言程序設(shè)計中,可對串進行如下操作:
(S=STRING ,B=BYTE, W= WORD)
串的傳送 MOVS/MOVSB/MOVSW(MOVE)
串的比較 CMPS/CMPSB/CMPSW(COMPARE)
串的檢索 SCAS/SCASB/SCASW(SCAN)
存串 STOS/STOSB/STOSW(STORE)
取串 LODS/LODSB/LODSW(LOAD)
這些操作有如下特點:
(1) 可對字節(jié)串(如MOVSB)或字串操作(如MOVSW)。
(2) 源操作數(shù)(稱為源串): 段地址DS,偏移量SI
目的操作數(shù)(稱為目的串):段地址ES,偏移量DI
串操作指令是唯一的一組源操作數(shù)和目的操作數(shù)均在內(nèi)存的指令。
(3) 串操作指令執(zhí)行時,每執(zhí)行一次,自動修改源串和目的串的地址偏移量SI和DI。SI和DI的修改方式與標(biāo)志寄存器的方向標(biāo)志

DF有關(guān):STD指令:置DF=1 (Set DF)
CLD指令:置DF=0 (Clear DF)
(4) 串操作指令可以加重復(fù)前綴。
1、 字符串的傳送指令
把源字符串中DS:SI處的元素(字節(jié)或字)復(fù)制到目的字符串中ES:DI處,且自動修改SI、DI。

MOVS 目的字串,源字串 ;每次復(fù)制一字。
MOVSW ;每次復(fù)制一字
MOVSB ;每次復(fù)制一字節(jié)。
執(zhí)行字符串的傳送指令,有以下五個步驟:
(1) 用CLD指令使DF=0或用STD指令使DF=1,以指頂字符串的傳送指令執(zhí)行后,SI、DI是增加(DF=0)或減少(DF=1)。
(2) 源字符串的地址送DS、SI。
(3) 目的字符串的地址送ES、DI。(當(dāng)源字符串和目的字符串在同一數(shù)據(jù)段時,ES=DS,且一般在程序的起始處設(shè)置)。
(4) 將字節(jié)或字數(shù)送入CX。
(5) 執(zhí)行字符串傳送指令。
字符串傳送中,DF標(biāo)志位的影響。
DF標(biāo)志位影響字符串指令執(zhí)行后SI、DI是增加(DF=0)或減少(DF=1),如圖3-24所示。

2、 字符串的比較指令
兩個字符串對應(yīng)位置的元素(字節(jié)或字)進行比較(DS:SI處元素與ES:DI處元素比較),比較結(jié)果反應(yīng)在標(biāo)志寄存器的標(biāo)志位。且自動修改SI、DI。
CMPS 目的字串,源字串;DS:SI處與ES:DI處比較一字。
CMPSW ;DS:SI處與ES:DI處比較一字。
CMPSB ;DS:SI處與ES:DI處比較一字節(jié)。
CMPSxx指令使用"源串中DS:SI處元素-目的串ES:DI處元素"的算法進行比較。(區(qū)分:"CMP dst,src"指令使用"dst-src"的算法進行比較)。
3、 字符串的掃描指令
AL或AX與目的字符串中ES:DI處的元素(字節(jié)或字)進行比較,比較結(jié)果反應(yīng)在標(biāo)志寄存器的標(biāo)志位。且自動修改DI。(該指令不使用SI,因此,該指令執(zhí)行時SI不變)。即,查找(稱為掃描)字符串中是否含有與AL/AX相同的元素。
SCAS 目的字串 ;AX與ES:DI處比較。
SCASW ;AX與ES:DI處比較。
SCASB ;AL與ES:DI處比較。
SCASxx指令使用"AL/AX-目的串中ES:DI處元素"的算法進行比較。
4、 字符串的裝入指令
把源字符串中DS:SI處的元素(字節(jié)或字)裝入AL或AX中。且自動修改SI。(該指令不使用DI,因此,該指令執(zhí)行時DI不變)。LODS 源字串 ;DS:SI處的元素(字)→AX。
LODSW ;DS:SI處的元素(字)→AX。
LODSB ;DS:SI處的元素(字節(jié))→AL。
5、 字符串的存儲指令
把AL或AX中的值存入目的字符串中ES:DI處。且自動修改SI。(該指令不使用SI,因此,該指令執(zhí)行時SI不變)。
STOS 源字串 ;AX →ES:DI處。
STOSW ;AX→ES:DI處。
STOSB ; AL→ES:DI處。
