- 匯編語言程序設計(第3版)
- 丁輝主編
- 2281字
- 2018-12-27 19:09:07
第3章 指令系統
本章以8086/8088指令系統為基礎,從介紹指令的基本格式,操作數的尋址方式入手,講述指令系統中各類指令的功能、使用方法和應用場合,并根據處理器的發展歷程,講述80386和Pentium處理器新增的指令。
3.1 指令格式
計算機的指令系統是指微處理器所能執行的各種指令的集合。微處理器的主要功能必須通過它的指令系統來實現。不同的微處理器有著不同的指令系統,其中每條指令與微處理器的一種基本操作相對應,這在設計微處理器時就已確定。
8086/8088指令系統包括上千條指令,這里所謂的指令可分為機器指令和匯編指令。機器指令用二進制代碼表示,便于計算機識別,但不利于用戶記憶和交流;匯編指令則用一些簡單的符號來表示機器指令,以彌補機器指令的不足。若無特殊說明,本書此后所論及的指令均為匯編指令。
微型計算機的每一條指令通常由兩部分構成。
1.操作碼(OP-Code)
操作碼指示計算機所要執行的操作類型。CPU執行指令時,首先將操作碼從指令隊列送到執行部件EU中的控制單元,經指令譯碼器分析識別后,產生執行本指令操作所需的時序控制信號,控制計算機完成規定的操作。
2.操作數(Operand)
操作數指出指令執行操作所需的數據或操作結果存放的位置。有兩個操作數的指令中一個操作數稱為源操作數,另一個稱為目的操作數。源操作數和目的操作數是參加操作的兩個操作數,而目的操作數又存放操作的結果,也就是說,運算后,參加運算的一個操作數將會丟失,但一般情況下不關心這個問題。如果以后的運算中還會用到這個操作數的話,則應在運算之前將其送到其他位置。
指令的基本格式如圖3.1所示。

圖3.1 指令的基本格式
3.2 尋址方式
計算機是靠指令加工處理信息的,信息寄存在寄存器中或存儲在存儲器中,執行指令時往往要從寄存器或存儲器中取出信息,加工處理后又存放到寄存器或存儲器中。對于一條具體的指令,如何在寄存器或存儲器中找到指令執行時所需的信息,如何確定執行結果的存放位置?這就需要了解尋址方式。尋址方式說明如何尋找操作數,以及如何確定執行結果存放位置。8086/8088指令涉及四種操作數:隱含操作數,立即操作數,寄存器操作數,以及存儲器操作數。由此就有對應的4類尋址方式。
3.2.1 固定尋址(Inherent Addressing)
這種尋址方式下,操作數隱含在指令中。8086/8088的某些單操作數指令規定操作數在CPU的某個固定的寄存器中,而這個寄存器又隱含在操作碼中,例如:加法的十進制調整指令DAA,其操作數總是固定隱含在AL中;還有的雙操作數指令,例如寄存器的入棧、出棧指令只給出一個操作數,而另一個操作數被固定隱含在棧頂。
使用這種尋址方式的指令不需要計算存儲器的有效地址EA,執行速度較快。
3.2.2 立即尋址(Immediate Addressing)
這種尋址方式下,操作數以常量的形式出現在指令中。操作數隨著指令一起進入指令隊列,不必執行總線周期,故稱為立即數。立即數可以為8位,也可以為16位。如果是16位數,則低字節存放在低地址單元中,高字節存放在高地址單元中。立即尋址方式用來表示常數,它常用于給寄存器賦初值,立即數只能用做源操作數,不能用做目的操作數。
【例3.1】MOV CX,9;立即數9作為源操作數賦給寄存器CX。
【例3.2】MOV AX,5807H
指令執行后(AX)=5807H,如圖3.2所示。圖中指令存放在代碼段中,OP表示該指令的操作碼部分,5807H則為立即數,它是指令的一部分。

圖3.2 指令執行情況
3.2.3 寄存器尋址(Register Addressing)
這種尋址方式下,操作數為通用寄存器或段寄存器(CS除外)。16位寄存器操作數可以是AX、BX、CX、DX、SI、DI、SP、BP、DS、SS及ES;8位寄存器操作數可以是AL、AH、BL、BH、CL、CH、DL和DH。這種尋址方式由于操作數就是CPU的寄存器,不需要執行總線周期,執行速度較快。因此,在既可使用寄存器尋址又可使用后述的存儲器尋址的場合,常常選用前者。
【例3.3】MOV AX,CX
若指令執行前(AX)=9602H,(CX)=2081H;則指令執行后,(AX)=2081H,(CX)內容保持不變。指令執行情況如圖3.3所示。

圖3.3 寄存器尋址方式執行情況
3.2.4 存儲器尋址
存儲器尋址方式下,操作數一般是代碼段之外的數據段、堆棧段、附加數據段中的存儲單元,指令給出的是存儲單元的地址或產生存儲單元地址的表達式。執行此類指令時,CPU首先根據操作數字段提供的地址信息,由執行部件EU計算出有效地址EA(EA是一個不帶符號的16位數據,代表操作數地址離段首地址的距離,即該地址到段首地址的字節數),再由總線執行部件BIU根據公式PA=(16×段首地址)+EA計算出操作數的物理地址。
一般而言,一條指令的目的操作數和源操作數不能同為存儲器操作數。存儲器尋址方式按EA計算方法的不同可以分為5種。
1. 直接尋址(Direct Addressing)
格式:(1)[常量]
(2)變量
直接尋址是最簡單的存儲器尋址。這種尋址方式下,操作數的有效地址由指令直接給出,是帶有方括號的常量或是變量。
需要說明的是,該方式下,操作數的段地址默認為在數據段寄存器DS中,即DS為默認段寄存器。因此,直接尋址方式下,作為操作數的存儲單元的物理地址為:
PA=16×(DS)+nn
這里nn表示常量或變量的偏移地址。
【例3.4】MOV AL,[1000H];將DS段1000H單元的內容傳送到AL中。
【例3.5】MOV AX,[1000H]
與上一條指令不同的是,指令執行后將DS段中偏移地址為1000H的字單元內容傳送到AX,即低地址1000H對應AL,高地址1001H對應AH。若(DS)=2000H,(21000H)=3412H,則該指令執行后(AX)=3412H。指令執行情況如圖3.4所示。

圖3.4 指令執行情況
使用直接尋址方式時應注意:
(1)直接地址可用數值表示,包括在[ ]之中,也可以用變量表示,例如:MOV AL,VALUE;這里,VALUE為變量,變量是有屬性的,它由數據段中定義數據的偽指令確定(偽指令將在第4章介紹)。
(2)若操作數在代碼段、堆棧段或附加段中,則應在操作數地址之前使用前綴指出段寄存器名,這種前綴稱為段超越前綴。例如:
MOV AL,ES:[2000H] ;將ES段2000H單元的內容傳送到AL中
段超越前綴也可以用于其他存儲器尋址方式中,以使得給定的段寄存器取代默認的段寄存器。
(3)直接尋址方式適合于處理存儲器的單個單元。IBM-PC機中為了避免指令字的長度過長,規定雙操作數指令除立即尋址方式之外必須有一個操作數使用寄存器或段寄存器,這就是一個變量常常先要送到寄存器中去的原因。
2.寄存器間接尋址(Register Indirect Addressing)
格式:[BX、BP、SI或DI]
這種尋址方式下,操作數的有效地址EA不像直接尋址那樣直接放在指令中,而是由基址寄存器BX、BP或變址寄存器SI、DI之一給出,即

如果指令中使用的是BX、SI和DI,則操作數在數據段中,且用數據段寄存器DS中的內容作為段地址,即操作數的物理地址為

【例3.6】MOV AL,[BX];設BX的內容為1000H,則指令功能是將DS段1000H單元的內容傳送到AL中。
【例3.7】MOV AX,[BX]
設(DS)=2000H,(BX)=1000H,(21000H)=3412H,物理地址PA=16×2000H+1000H=20000+1000H=21000H,執行情況如圖3.5所示。

圖3.5 寄存器間接尋址執行情況
指令執行后,(AX)=3412H。
若指令中使用的是BP,則操作數在堆棧段中,用堆棧段寄存器SS中的內容作為段地址,即操作數的物理地址為
PA=16×(SS)+(BP)
寄存器間接尋址通常用來對一維數組進行處理。只需在執行完一條指令后改變間接尋址寄存器BX、BP、SI和DI中的內容,就可以使用同一個地址表達式來指定一維數組中的不同元素,從而對連續的存儲器單元進行存/取操作。
3. 基址尋址(Based Addressing)
格式:偏移量[BX或BP]
其中偏移量可以是常量或變量,還可以表示為[BX或BP][偏移量]和[BX或BP+偏移量]。
這種尋址方式與寄存器間接尋址方式的區別僅在于,只能使用基址寄存器BX和BP,且指令中還要指定一個8位或者16位的偏移量,操作數的有效地址EA等于基址寄存器BX或BP的內容與偏移量之和,該偏移量在兩個字節范圍內,即

【例3.8】MOV AL,80H[BP];設BP內容為2040H,則指令功能是將堆棧段20C0H單元的內容傳送到AL中。
該指令又可表達為
MOV AL,[BP][80H] 或MOV AL,[BP+80H]
【例3.9】MOV AX,COUNT[BX]
設(DS)=2000H,(BX)=1000H,COUNT=3000H,(24000H)=1058H,其尋址示意圖如圖3.6所示。指令執行后,(AX)=1058H。

圖3.6 基址尋址方式執行情況
基址尋址通常也用來訪問一維數組中的元素,用偏移量來確定數組的起點,基址寄存器的值選擇一個元素。與寄存器間接尋址一樣,因數組中所有元素具有相同的長度,只要改變基址寄存器的內容,就可以使用同一個地址表達式選擇數組中任意的元素。
4.變址尋址(Indexed Addressing)
格式:偏移量[SI或DI]。
其中偏移量可以是常量或變量,其他的表示形式類似于基址尋址方式,只需將基址寄存器BX、BP換成變址寄存器SI、DI即可。變址尋址中總是使用段寄存器DS的內容作段首地址,操作數的有效地址EA等于間址寄存器內容和位移量之和,即

變址尋址方式同樣適合處理數組,通常SI用于源數組的變址尋址,DI則用于目的數組的變址尋址。
例如: MOV AX,ARRAY1[SI] MOV ARRAY2[DI],AX
其中ARRAY1和ARRRAY2分別用來表示源數組和目的數組的起點。若用上述兩條指令,配上修改SI、DI值的指令,構成循環,就可實現將源數組移動到目的數組的目的。
5.基址變址尋址(Based Indexed Addressing)
格式:偏移量[BX或BP+SI或DI]。
其中偏移量可以是常量或變量,其他的表示形式類似于基址尋址方式,只需將基址寄存器換成基址+變址寄存器即可。
這種尋址方式下,存儲器操作數的有效地址EA是指令指定的基址寄存器BX、BP之一與變址寄存器SI、DI之一的內容以及偏移量三者之和,即

這里共有四種組合情況,并且根據基址是在BX還是在BP中,確定尋址操作數是在數據段還是堆棧段。對于前者,段寄存器使用DS;對于后者,段寄存器使用SS。基址變址尋址的操作數物理地址為

【例3.10】MOV AX,3000H[BX+SI]
設(DS)=1000H,(BX)=0400H,(SI)=1260H;
則:EA=0400H+1260H+3000H=4660H
PA=10000H+4660H=14660H
指令的執行情況如圖3.7所示。指令執行后,(AX)=1058H。

圖3.7 基址變址尋址方式執行情況
應當注意以下指令是錯誤的:
MOV AX,30H[BX][BP] MOV AX,10H[SI][DI]
基址變址尋址方式同樣適合數組或表格的處理,由于基址和變址寄存器中的內容都可以改變,在處理二維數組時尤為方便。
這種尋址方式中,若偏移量為0,則偏移量可默認。即指令
MOV AX,0[BX+SI]
可表示為
MOV AX,[BX+SI]
3.3 指令的執行時間
通常,一條指令的執行時間是指計算機取指令、取操作數、執行指令及傳送結果各個階段所需時間的總和。如果要詳細討論各種指令的執行時間是一個比較復雜的問題,這里只作簡單介紹。
由于指令是存放在存儲器中,因此運算器要執行指令就需先訪問存儲器,但是8086/8088 CPU的執行部件EU和總線接口部件BIU是并行工作的,BIU可以預先把指令取到指令隊列緩沖器中存放,形成了取指和執行的并行,這樣,在計算指令的執行時間時,就不把取指時間計算在內。
執行指令的時間,除了EU中的基本執行時間外,有些指令在執行過程中可能需要多次訪問內存,包括取操作數和存放操作數結果等,要執行總線的讀/寫周期,這樣,執行一條指令的時間就是指令的基本執行時間及存取操作數時間的總和。指令的基本執行時間因指令的不同而異,相互之間有很大的差別,而存取操作數所需的計算有效地址EA的時間又隨尋址方式的不同而異。
表3.1表示執行幾種不同的指令所需的時間;表3.2表示執行加法時不同的尋址方式所需的時間;表3.3表示在不同的尋址方式下計算EA所需的時間。在這些表格中,所有的時間都以時鐘周期數表示(計算機是按照節拍工作的,這里所說的節拍稱為時鐘周期)。
表3.1 指令的基本執行時間舉例

表3.2 加法指令的執行時間

表3.3 計算有效地址EA所需的時間

從表3.1至表3.3可以看出,不僅不同指令的執行時間差別很大,而且同一種指令使用不同的尋址方式時執行時間的差別也是很大的,通過以下例題可以對指令的執行時間有一個具體的了解。
【例3.11】設8086的時鐘頻率為5MHz(即時鐘周期=0.2μs),試求兩個字節相加的ADD指令在各種尋址方式下,指令的執行時間t。
(1)目的操作數和源操作數均為寄存器操作數。需要3個時鐘周期,即
t=3×0.2=0.6(μs)
(2)目的操作數為寄存器操作數,源操作數為基址變址尋址的存儲器操作數。需要的時鐘數為
t=9+EA=9+12=21(T)
第一項的9為這種尋址方式下指令的基本運算和基本操作時間,第二項為計算EA的時間,即
t=21×0.2(μs)=4.2(μs)
(3)目的操作數為基址變址尋址的存儲器操作數,源操作數為寄存器操作數。需要的時鐘數為
t=16+EA=16+12=28(T)=5.6(μs)
第一項的16為這種尋址方式下指令的基本運算和基本操作時間,第二項為計算EA的時間。
對于其他的尋址方式下ADD指令的執行時間,請讀者練習計算。
從上述的例子可以看出:對于同一條ADD指令而言,因尋址方式不同,執行指令的時間也不同,即執行的效率有差異,有時這種差異還很大。從表3.2還可以得知,同一類的指令使用不同的尋址方式時指令的長度也不一樣,占用存儲器的字節數差異也很大。當一個實際的應用程序要求運行效率較高和占用空間較小時,程序的設計者不僅要研究算法、數據結構,還要研究指令與尋址方式的選用,才能編制出高效而簡潔的程序。
3.4 Intel8086/8088指令系統
8086/8088指令系統包括約百種指令助記符,它們與尋址方式結合,再加上操作數字節數的不同,可以構成上千種指令。這些指令按照功能可分為6類。
(1)數據傳送指令;
(2)算術運算指令;
(3)位操作指令;
(4)串操作指令;
(5)轉移指令;
(6)處理器控制指令。
本節將主要介紹前3類指令的格式和功能,后3類指令本節僅作概要介紹,詳情將在后面的相關章節中講解。為便于指令的介紹,現作以下約定。
(1)指令中的IMM表示立即數,IMM8僅表示8位立即數,IMM16僅表示16位立即數。
(2)指令中的REG表示寄存器操作數。它可代表8位寄存器AH、AL、BH、BL、CH、CL、DH和DL,以及16位寄存器AX、BX、CX、DX、SP、BP、SI和DI。REG8僅表示8位寄存器,REG16僅表示16位寄存器。指令中的SEGREG表示段寄存器操作數。它可代表CS、DS、ES及SS。
(3)指令中的MEM表示存儲器操作數,它可以表示任何一種存儲器尋址方式下的操作數。MEM8、MEM16及MEM32分別表示8位、16位及32位存儲器操作數。
(4)在對指令功能作說明時,用圓括號來表示所括起部分的內容。例如用(AX)表示AX的內容,用(2040H)表示偏移地址為2040H的存儲單元的內容。
(5)在指令的圖示中,對于存儲器單元一般只標出偏移地址。
3.4.1 數據傳送指令
數據傳送指令用于寄存器、存儲器或輸入/輸出端口之間傳送數據或地址,這類指令共14條,按其特點可分為四組,如表3.4所示。
表3.4 數據傳送指令表

1.通用數據傳送指令
(1)MOV目的操作數,源操作數把源操作數傳送到目的操作數。
【例3.12】MOV AX,BX ;AX←(BX), 即將BX的內容傳送到AX中; MOV CL,80H ;CL←80H; MOV AL,[2000H] ;AL←(2000H), 即將EA為2000H(段地址取DS的值) 單元的值傳送到AL中。
說明:
① 源操作數不變(一般帶有源操作數的8086/8088指令都不改變源操作數的內容,本書對于例外指令將予以說明)。
② 立即數、段寄存器CS不能作為目的操作數。源操作數和目的操作數不能同為存儲器操作數,如圖3.8所示。

圖3.8 數據傳送關系圖
以下指令均是錯誤的:
MOV 64H, BL
MOV CS, AX
MOV [2000H], [BX]
③ 源操作數和目的操作數類型必須一致,即同為單字節數,或同為雙字節數,當指令中只有一個操作數的類型明確時,另一個操作數被視為同一類型。可以用“BYTE PTR”或“WORD PTR”將一個存儲器操作數定義為字節或字類型。當存儲器操作數為字類型時,寄存器或立即數的高字節對應其高地址,低字節對應其低地址(這種對應關系亦適用于其他指令)。
④ MOV指令的執行不影響標志寄存器。
【例3.13】MOV [2000H],AX
將AX的內容傳送到偏移地址為2000H的存儲單元中。指令執行情況如圖3.9所示。

圖3.9 指令執行情況
【例3.14】MOV WORD PTR [BX+SI],80H
當(BX)=2080H,(SI)=1040H時,表示將0080H傳送到偏移地址為30C0H的存儲單元中。指令執行情況如圖3.10所示。

圖3.10 指令執行情況
(2)PUSH源操作數
將源操作數壓入堆棧。先將SP的內容減2,再將雙字節的源操作數傳送到SP所指示的堆棧棧頂。
【例3.15】PUSH BX ;指令執行情況如圖3.11所示。

圖3.11 指令執行情況
(3)POP目的操作數
將棧頂內容彈至目的操作數。先將SP所指單元也即堆棧棧頂的一個字傳送到目的操作數,并將SP的內容加2。
【例3.16】POP AX
若該指令緊接在上述PUSH BX指令之后,則指令執行情況如圖3.12所示。

圖3.12 指令執行情況
堆棧是一個非常有用的存儲結構,它遵循先進后出的原則,通常用于子程序的調用和返回,現場的保護和恢復等場合。PUSH和POP指令一般應配對使用。使用時需注意以下4點:
① 堆棧操作指令中,有一個操作數是隱含的,這個操作數就是(SP)指示的棧頂存儲單元。
② 8086/8088堆棧操作都是字操作,不允許對字節操作。例如:PUSH AH不是正確指令。
③ 每執行一條入棧指令,(SP)自動減2,高字節和低字節先后入棧;執行出棧指令時,則相反,低字節和高字節先后出棧,(SP)自動加2。
④ CS寄存器可以入棧,但不能隨意彈出一個數據到CS。
【例3.17】設在一個被調用的子程序中,要使用到AX、BX、CX和DX,子程序的運行還可能影響狀態標志。為了使這些寄存器中的數據不被破壞,進入子程序時先予以入棧保護,子程序結束前再做出棧恢復。子程序中保護和恢復的程序段為
SUB1 PROC NEAR ; 定義過程 PUSHF PUSH AX PUSH BX PUSH CX PUSH DX ; 保護現場 ┇ POP DX POP CX POP BX POP AX POPF ; 恢復現場 SUB1 ENDP ; 過程結束
(4)XCHG目的操作數,源操作數
把源操作數和目的操作數互換。說明:該指令與MOV指令功能上的區別有兩點,其一,該指令不允許使用立即數和段寄存器作為操作數;其二,該指令改變源操作數的內容。
2.累加器專用傳送指令
(1)XLAT,把(BX)與(AL)相加形成有效地址EA,將該單元中的單字節數傳送到AL中。
【例3.18】MOV BX,4C02H MOV AL,1DH XLAT
有關存儲單元情況如圖3.13所示,則執行上述指令后,(AL)=55H。
這是一條專門用于AL和字節表中某一存儲單元之間進行數據傳送的指令。字節表的首地址在BX中,根據AL設置的偏移地址,就可以將該單元的內容傳送到AL中。
(2)IN累加器,端口地址
從指定端口輸入一個字節到AL或輸入一個字到AX。端口地址以數值形式給出或通過DX間接給出。當端口地址大于255時,則只能由DX間接給出。
【例3.19】IN AX,16H ; 從端口16H輸入一個字到AX中。

圖3.13 執行情況
【例3.20】MOV DX,280H IN AL,DX ; 從端口280H輸入一個字節到AL。
說明:該指令及后述的OUT指令是專用于累加器和I/O端口之間進行數據傳送的指令,操作數的確定方式有別于前述尋址方式。其一,端口地址不加“[ ]”;其二,使用DX作為專用間址寄存器。
(3)OUT端口地址,累加器
實現輸出,即與IN指令相反方向的數據傳送。
3. 地址傳送指令
地址傳送指令實現操作數地址的傳送。
(1)LEA目的操作數,源操作數
將源操作數的有效地址EA傳送給通用寄存器。
【例3.21】MOV BX,0408H MOV SI,2000H LEA BP,[BX+SI+6] ; 將240EH送BP(而不是將240EH單元的內容送BP!)。
(2)LDS目的操作數,源操作數
將源操作數指定的存儲單元中的雙字(通常為段地址和有效地址)傳送給DS及目的操作數,高兩字節送DS,低兩字節送目的操作數。
【例3.22】已知(DS)=30C0H,相關存儲區情況及執行以下指令的功能如圖3.14所示。

圖3.14 指令執行情況
LDS SI,[40H]
(3)LES目的操作數,源操作數
與LDS指令的區別僅在于,傳送地址時將高兩字節送ES,而不是送DS。
說明:
① 地址傳送指令的源操作數必須是存儲器操作數,目的操作數必須是16位通用寄存器。
② LEA指令與LDS、LES指令所傳送的有效地址有區別。LEA指令所傳送的有效地址為源操作數的有效地址,而LDS及LES指令所傳送的有效地址在源操作數所指的存儲單元中。
4. 標志傳送指令
這組指令專用于對標志寄存器操作。如前所述,8086/8088標志寄存器具有16位,LAHF和SAHF僅對其低8位操作,而PUSHF和POPF對整個標志寄存器操作。
(1)LAHF,將標志寄存器低8位送AH。
(2)SAHF,將(AH)送標志寄存器低8位。
(3)PUSHF,與PUSH指令功能相似,該指令的特殊之處僅在于,壓入堆棧的是標志寄存器的內容。
(4)POPF,與POP指令功能相似,該指令的特殊之處僅在于,彈出的堆棧的內容是送標志寄存器。
標志傳送指令中SAHF和POPF指令將直接影響標志寄存器的內容。利用這一特性,可以方便地改變標志寄存器中指定位的狀態。
說明:數據傳送指令中僅SAHF及POPF影響標志寄存器的內容。
3.4.2 算術運算指令
算術運算指令分為二進制數算術運算指令和BCD數算術運算調整指令。
1. 二進制數算術運算指令
參加算術運算的二進制數可以是單字節數或雙字節數,也可以是無符號數或有符號數(有符號數在機器內部以補碼形式表示)。由于匯編語言源程序中往往需要判斷運算結果是否超出范圍,是否為零,是否為負數等,所以二進制數算術運算指令除了產生與操作數位數相同的結果外,還將影響標志寄存器中的相應標志以便在必要時實現上述判斷。該類指令共14條,按照四則運算分為4組,如表3.5所示。
表3.5 二進制算術運算指令表

注:×表示根據操作結果設置標志;-表示標志不確定;空白表示標志不受影響。
(1)加法指令
① ADD 目的操作數,源操作數
將源操作數加到目的操作數,同時影響狀態標志。
ADD 指令執行后對標志的影響:
● OF 字節運算結果超出字節有符號數的范圍(-128~+127)或字運算結果超出字有符號數范圍(-32768~+32767)時,OF=1;否則OF=0。在把操作數視為有符數時,可通過該標志了解結果是否溢出。
● SF 運算結果的最高位為1時,SF=1;否則SF=0(即SF與結果的最高位一致)。
● ZF 運算結果為零時,ZF=1;否則ZF=0。
● AF 運算時,D3向D4產生進位時AF=1,否則AF=0。
● PF 運算結果的二進制位1的個數為偶數時,PF=1;否則PF=0。
● CF 運算時最高位產生進位時,即字節運算結果超出字節無符號數的范圍(0~255),字運算結果超出字無符號數的范圍(0~65535)時,CF=1;否則CF=0。在把操作數視為無符號數時,可通過該標志了解結果是否溢出。
【例3.23】ADD AL,BL
設(AL)=0A4H,(BL)=5CH,則指令執行后,(AL)=0,OF=0,SF=0,ZF=1,AF=1,PF=1,CF=1。
編程者往往要根據不同情況關心不同的標志位。例如:執行該指令時,機器并不能判別所得數據是有符號數還是無符號數,而編程者在使用此指令及其他相關指令時總是為了解決某一個具體問題,從而對這一點是清楚的。因此,在使用此指令后,將會根據所得數據是有符號數還是無符號數來關心不同的標志位。
當把相關數據視為有符號數,從OF=0可知相加結果未溢出,也即AL的內容“0”就是兩個有符號數0A4H(-01011100B)和5CH(+01011100B)之和。
當把相關數據視為無符號數,從CF=1可知相加結果產生進位也即“100000000B”就是兩個無符號數0A4H(10100100B)和5CH(01011100B)之和。
說明:源操作數和目的操作數類型必須一致,即同為字節或同為字,且兩者不能同為存儲器操作數(這一點適用于所有雙操作數的算術運算指令)。
② ADC目的操作數,源操作數
功能與ADD指令基本相同,唯一區別是:將該指令執行前的CF值加至目的操作數中。該指令主要用于多字節加法運算。
【例3.24】MOV DX, 2000H MOV AX, 8A04H ADD AX, 9D00H ADC DX, 45H
此程序段實現多字節數20008A04H與459D00H的相加。DX存放有被加數的高兩字節,AX存放有被加數的低兩字節。ADD指令實現兩數低兩字節的相加,相加后(AX)=2704H,CF=1(相加結果超過兩個字節)。ADC指令實現兩數高兩字節的相加,且將CF(即低兩字節相加產生的進位)加至DX,使DX內容為2046H。
③ INC目的操作數
功能與ADD指令基本相同,區別有兩點:其一,隱含的源操作數為1;其二,不影響CF標志。
該指令常用于某些計數器的計數,或用于修改地址。
【例3.25】MOV SI, 2000H MOV AL, [SI] INC SI ADD AL, [SI] ;(AL)為2000H單元和2001H單元內容之和
(2)減法指令
① SUB目的操作數,源操作數
將目的操作數減去源操作數,同時產生相應標志。SUB指令執行后對標志的影響與ADD指令基本相同,只不過這里只有“借位”而無“進位”。
② SBB目的操作數,源操作數
功能與SUB指令基本相同,唯一區別是:目的操作數除減去源操作數外,還要減去該指令執行前的CF值。
該指令主要用于多字節減法運算。
③ DEC目的操作數
功能與SUB指令基本相同,區別有兩點:其一,隱含的源操作數為1;其二,不影響CF標志。
④ NEG目的操作數
對目的操作數取補碼,結果送目的操作數。因為對一個數取補碼相當于用0減去此數,所以該指令也屬于減法運算指令。
⑤ CMP目的操作數,源操作數
功能與SUB指令基本相同,唯一區別是:目的操作數不被差值取代。該指令的作用在于根據兩操作數的大小關系產生狀態標志值,以便其后指令根據狀態標志確定程序流程。
(3)乘法指令
① MUL源操作數
實現無符號數乘法運算。將(AL)或(AX)作為被乘數,源操作數作為乘數,乘積送AX或送DX、AX。當源操作數為字節操作數時,默認(AL)為被乘數,乘積送AX;當源操作數為字操作數時,默認(AX)為被乘數,乘積高兩字節送DX,低兩字節送AX。指令執行情況如圖3.15所示。

圖3.15 乘法指令執行情況
例如: MUL CL ;AL、CL中的無符號數之積送AX; MUL [SI] ; 此為錯誤指令。原因在于,計算機無法判別源操作數是字節操 作數抑或字操作數; MUL WORD PTR [SI] ;AX中的無符號數與SI所指單元的字無符號數相乘,乘積送 DX和AX。
MUL指令影響進位標志CF和溢出標志OF(其他標志不確定)。若乘積高半部分(字節相乘時乘積中的(AH);字相乘時乘積中的(DX))非0,則CF=OF=1;否則,CF=OF=0。也即,CF=OF=1標志著AH或DX中放有乘積的有效位。
② IMUL源操作數
功能與MUL指令基本相同。區別僅在于,該指令實現有符號數乘法運算。此指令執行后,CF=OF=1亦標志著AH或DX中放有乘積的有效位。即標志著(AH)或(DX)不是對應的低半部分的符號擴展。
【例3.26】MOV AL,0FCH ;-4送AL; MOV CL,1FH ;+31送CL; IMUL CL ;(AL)與(CL)之積-124送AX, 即(AL)=84H,(AH) =FFH。此時CF=OF=0, 標志著(AH)是(AL)的符號擴展。
(4)除法指令
① DIV源操作數
實現無符號數除法運算。以(AX)或(DX)、(AX)中的內容為被除數,源操作數為除數。商送AL或AX,余數送AH或DX。當源操作數為字節操作數時,默認(AX)為被除數,商送AL,余數送AH;當源操作數為字操作數時,默認(DX)、(AX)內容為被除數,商送AX,余數送DX。指令執行情況如圖3.16所示。

圖3.16 除法指令執行情況
【例3.27】MOV AX,1001H ;4097送AX; MOV CL,20H ;32送CL; DIV CL ;(AX)與(CL)相除, 商128送AL, 余數1送AH。即(AL) =80H,(AH)=01H。
DIV指令執行后,各狀態標志位不確定。
說明:當源操作數為字節類型時,商的范圍為0~255(FFH);當源操作數為字類型時,商的范圍為0~65535(FFFFH)。超出范圍則產生0號中斷。
② IDIV源操作數
功能與DIV指令基本相同,區別在于,該指令實現有符號數除法運算。另外,8086/8088指令系統中規定余數的符號與被除數符號相同。例如:
MOV CX,4 IDIV CX ; 若已知DX、AX中放有4001H, 則該指令執行后,(AX)=1000H, (DX)=0001H。若已知DX、AX中放有-4001H, 則該指令執行后, (AX)=F000H(即-1000H),(DX)=FFFFH(即-1)。
③ CBW
將(AL)的符號位擴展到AH中(即使得AH各位與AL最高位相同),該指令常用在IDIV指令之前。CBW指令執行后,各狀態標志位不確定。例如:
MOV AL, 76H ;+76H送AL; CBW ;0076H送AX, 即+0076H送AX。 又如:MOV AL,98H ;-68H送AL; CBW ;FF98H送AX, 即-0068H送AX。
④ CWD
功能與CBW基本相同,區別僅在于,該指令是將(AX)的符號位擴展到DX中。
2.十進制數算術運算調整指令
前面所述的算術運算都是針對二進制數,但人們最為常用的卻是十進制數。在用計算機進行算術運算時,可以先將操作數做十→二進制轉換,然后做二進制數算術運算,再將結果做二→十進制轉換。為了便于十進制數的運算,8086/8088系統還提供了一組十進制數算術運算調整指令,該類指令將在5.2.1中詳細介紹。
3.4.3 位操作指令
8086/8088提供的位操作指令包括邏輯運算指令和移位指令,這類指令可直接對寄存器或存儲器操作數的位進行操作,如表3.6所示。
表3.6 位操作指令表

注:×表示根據操作結果設置標志;-表示標志不確定;空白表示標志不受影響。
1. 邏輯運算指令
(1)NOT目的操作數
將目的操作數按位取反,結果送目的操作數。例如
MOV AX,0 NOT AX ; 使(AX)為FFFFH。
(2)AND目的操作數,源操作數
將目的操作數與源操作數按位相與,結果送目的操作數。當兩個操作數的對應位都為1時,結果的對應位為1;否則為0。該指令常用于屏蔽目的操作的某些位,即使得目的操作數的某些位置0,其余保持不變。例如
MOV AL,49H AND AL,0FH ; 使(AL)=09H, 即屏蔽(AL)的高4位, 而低4位不變。
(3)OR目的操作數,源操作數
將目的操作數與源操作數按位相或,結果送目的操作數。當兩個操作數的對應位都為0時,結果的對應位為0;否則為1。該指令常用于使目的操作數的某些位置1,其余位保持不變。
例如(4)XOR目的操作數,源操作數
MOV AL,49H OR AL,3CH ; 使(AL)=7DH, 即使得(AL)中間4位置1, 其余位保持不變。
將目的操作數與源操作數按位作異或操作,結果送目的操作數。當兩個操作數的對應位不同時,結果的對應位為1;否則為0。該指令常用于判斷兩個數中哪些位不同,或用于改變指定位的狀態。例如
MOV DH, 12H XOR DH, 80H ; 使(DH)=92H, 即改變DH最高位狀態。 又如:XOR AX, AX ; 使(AX)=0。
(5)TEST目的操作數,源操作數
功能與AND指令基本相同,唯一區別是:目的操作數保持不變。該指令常用于檢測某種條件是否滿足,但又不希望改變目的操作數的場合。例如
TEST AL,01H ; 可用此指令檢測AL最低位的狀態。若AL最低位為0, 則兩操作數按位相 與的結果為0, 從而ZF=1; 若AL最低位為1, 則結果為1, 從而 ZF=0。
說明:邏輯運算指令中的兩個操作數不能同為存儲器操作數。
2. 移位指令
移位指令包括算術移位指令、邏輯移位指令和循環移位指令。這些指令只有目的操作數而無源操作數,并在指令中給出移位的位數。而且此位數只能用1或CL表示。
(1)算術、邏輯移位指令
算術移位指令(SAL、SAR)用于有符號數,而邏輯移位指令(SHL、SHR)用于無符號數。操作數的左移意味著小數點相對右移,而操作數的右移意味著小數點相對左移。算術、邏輯移位指令的功能如圖3.17所示。

圖3.17
① SHL/SAL 目的操作數,計數
SHL指令和SAL指令功能完全相同。將目的操作數左移若干位,每左移一位,最低位補0,最高位送CF。該指令可以方便地實現有符號數和無符號數乘以2n的運算(n為移位計數值),不過在使用時要注意是否發生溢出。例如
MOV AL,16H SHL AL, 1 ; 使(AL)即00010110B左移1位。移位后,(AL)=00101100B, 是原值的2 倍。CF 值為0。 又如:MOV BH,0EEH MOV CL, 2 SAL BH,CL ; 使BH中的有符號數11101110B左移2 位。移位后(BH)=10111000B, 是 原值的4倍(原值為-00010010B, 即-18; 移位后的值為-01001000, 即 -72)。
② SHR 目的操作數,計數
將目的操作數右移若干位。每右移一位,高位均補0,最低位送CF。該指令可以方便地實現無符號數除以2n的運算。
③ SAR 目的操作數,計數
將目的操作數右移若干位。每右移一位,高位均保持不變,最低位送CF。該指令可以方便地實現有符號數除以2n的運算。例如
MOV AL, 0F8H SAR AL, 1 ; 使AL中的有符號數11111000B右移1位。移位后(AL)=11111100B, 是 原值的1/2(原值為-00001000B, 即-8; 移位后的值為-00000100B, 即-4)。
(2)循環移位指令
循環移位指令的功能如圖3.18所示。

圖3.18
① ROL 目的操作數,計數
將目的操作數循環左移若干位。每左移一位,左移前的最高位送最低位以及CF。
② ROR 目的操作數,計數
將目的操作數循環右移若干位。每右移一位,右移前的最低位送最高位以及CF。
③ RCL 目的操作數,計數
將目的操作數連同CF循環左移若干位。每左移一位,左移前的最高位送CF,左移前的CF送最低位。
④ RCR 目的操作數,計數
將目的操作數連同CF循環右移若干位。每右移一位,右移前的CF送最高位,右移前的最低位送CF。
【例3.28】 MOV DX, 0FFF9H XOR AX, AX ; 使AX,CF清0。 SAR DX, 1 RCR AX, 1 SAR DX, 1 RCR AX, 1
該程序段實現DX、AX中的有符號數FFF90000H右移兩位。移位后DX、AX內容為FFFE 4000H,是原值的1/4(原值為-00000000000001110000000000000000B,移位后的值為-00000000000000011100000000000000B)。
3.4.4 串操作指令
串是指存儲器中的字節串(字節序列)或字串(字序列)。8086/8088系統對串的操作提供了5種基本的指令以及與之配合使用的重復前綴。它們常用于循環結構,本書將在7.2中對此做介紹。
3.4.5 轉移指令
一般情況下指令是順序地逐條執行的。但有時需要改變這種執行流程,8086/8088系統為此提供了轉移指令。轉移指令用于分支結構,本書將在6.2中對此做介紹。
3.4.6 處理器控制指令
處理器控制指令用于控制CPU的某些功能,如表3.7所示。
表3.7 處理器控制指令表

3.5 Intel80x86及Pentium指令系統
3.5.1 Intel80386新增和擴充指令
80386是80X86微處理器系列發展中的里程碑。80386指令系統包括了所有80286指令,并對80286的部分指令進行了功能擴充,還新增了一些指令,特別指出的是,80386提供了32位尋址方式可對32位數據直接操作。所有16位指令均可擴充為32位指令。80386有8個32位通用寄存器:EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI。它們分別是原來的16位通用寄存器AX,CX,DX,BX,SP,BP,SI,DI的擴展(詳細的寄存器結構在第2.3節已介紹),這些32位通用寄存器的低16位也可以作為16位通用寄存器獨立存取數據,也就是說80386對8086,80286是向上兼容的。對于數據段寄存器,80386在原有基礎上增加了兩個:FS和GS。80386的標志寄存器擴展到了32位,其中某些位沒有定義。80386在實地址模式下有9個標志位可用,在保護虛地址模式下有13個標志位可用,擴展后的標志寄存器也可稱為E標志寄存器(EFR)EFLAGS。
80386有實地址模式、保護虛地址模式和虛擬8086模式3種工作方式,在DOS環境中只能運行于實地址模式,可做為超高速8086芯片使用。
1. 數據傳送與擴展指令
(1)MOVSX寄存器,寄存器/存儲器
將源操作數傳送到目的操作數中。目的操作可以是16位或32位寄存器;源操作數可以是寄存器或存儲器操作數,其位數應小于或等于目的操作數的位數。當源操作數的位數少于目的操作數時,目的操作數的高位用源操作數的符號位填補。此指令適用于有符號數的傳送與擴展。該指令不影響狀態標志位。
(2)MOVZX寄存器,寄存器/存儲器
與MOVSX功能基本相同,唯一區別在于,當源操作數的位數少于目的操作數位數時,目的操作數的高位用“0”填補。該指令適用于無符號數的傳送與擴展。例如
MOV DL,86H MOVSX AX,DL ;86H擴展成FF86H送AX; MOVSX ECX,DL ;86H擴展成FFFF FF86H送ECX; MOVZX BX,DL ;86H擴展成0086H送BX; 又如: MOV WORD PTR[BX],68H ;0068H送BX所指定的內存單元; MOV AX,[BX] ;0068H送AX; MOVSX ESI,WORD PTR[BX] ; 將 0068H擴展成00000068H送ESI; MOVZX EDI,WORD PTR[BX] ; 將0068H擴展成00000068H送EDI。
2. 堆棧操作指令
(1)PUSH 8/16 /32位立即數
將8/16/32位立即數壓入堆棧。當然該指令執行后SP的值將減2或者4。通常使用以下方法來區別操作數是8位,16位還是32位立即數。
【例3.29】PUSH 'A' ; 將0041H壓入堆棧(8位立即數) PUSHW 15H ; 將0015H壓入堆棧(16位立即數) PUSHD 20H ; 將00000020H壓入堆棧(32位立即數)
在8086/8088指令系統中,PUSH指令允許的操作數只能是兩字節的寄存器操作數或兩字節的存儲器操作數。該指令中如果給出的數不夠16或32位,則自動擴展為16或32位后壓入堆棧。
(2)PUSHA
將所有通用寄存器AX,CX,DX,BX,SP,BP,SI,DI的內容按順序壓入堆棧,入棧的SP值是執行該指令之前SP的值。在執行完本指令后,SP值減16,如圖3.19所示。
(3)PUSHAD
將所有通用寄存器EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI的內容順序壓入堆棧,其中壓入堆棧的ESP是該指令執行前ESP的值。執行該指令后,ESP值減32。

圖3.19 執行PUSHA指令的堆棧情況
(4)POPA
將棧頂的內容順序彈至DI,SI,BP,SP,BX,DX,CX,AX(次序與PUSHA指令相反)。SP中的值是堆棧中所有通用寄存器彈出后,堆棧指針實際指向的值(不是棧中保存的SP值),也即該指令執行后SP的值,可以通過加16來恢復,如圖3.20所示。PUSHA及POPA均不影響狀態標志位。

圖3.20 執行POPA指令的堆棧情況
【例3.30】一個子程序被調用時,保存所有通用寄存器,可用下述指令實現: PUSHA CALL SUB1 POPA
顯然使用上述指令比使用PUSH指令和POP指令更方便。
(5)POPAD
將當前棧頂內容順序彈至EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX(次序與PUSHAD指令相反),但是最終ESP的值為彈出操作對堆棧指針調整后的值(而不是堆棧中保存的ESP的值)。也即執行該指令后ESP的值,可以通過增加32來恢復。
(6)PUSHFD
將32位標志寄存器EFLAGS的內容壓入堆棧。
(7)POPFD
將當前棧頂的4字節內容彈至EFLAGS寄存器。
上述堆棧操作指令中,除POPFD以外,其余均不影響狀態標志位。
(8)設置堆棧空間指令
格式:ENTER 16位立即數,8位立即數。
ENTER指令使用兩個操作數,16位立即數表示堆棧空間的大小,也即表示給當前過程分配多少字節的堆棧空間,8位立即數指出在高級語言內(如Pascal語言)調用自身的次數,也即嵌套層數。
說明:該指令使用BP寄存器而非SP作為棧基值。
【例3.31】ENTER 6,0
該指令為過程分配了6個字節的堆棧空間,其嵌套層數為0。指令執行情況如圖3.21所示。

圖3.21 ENTER指令執行情況
(9)撤銷堆棧空間指令
格式:LEAVE
該指令無操作數,撤銷由ENTER指令建立的堆棧空間。
【例3.32】有一個16位參數,在主程序中需交給一個子程序處理,結果再傳回主程序,可使用堆棧空間指令完成上述工作。
調用子程序的過程,參數存入到堆棧中 ENTER 4,0 ; 建立4字節堆棧空間 MOV AX,Number1 ; 保存參數1 MOV [BP-4],AX MOV AX,Number2 ; 保存參數2 MOV [BP-2],AX CALL COURSE ; 調用子程序 MOV AX,[BP-4] ; 取結果1 MOV Number1,AX MOV AX,[BP-2] ; 取結果2 MOV Number2,AX LEAVE ; 撤銷堆棧空間 ┇ ; 使用堆棧處理數據的子程序 COURSE PROC NEAR PUSHA MOV AX,[BP-4] ; 取參數1 MOV DX,[BP-2] ; 取參數2 ┇ ; 參數處理 ┇ MOV [BP-4],AX ; 保存結果1 MOV [BP-2],DX ; 保存結果2 POPA RET COURSE END
3. 地址傳送指令
(1)LFS寄存器,存儲器
將源操作數所指存儲單元的4字節或6字節內容送指定的寄存器及段寄存器FS(FS及GS為80386新增的段寄存器)。
當目的操作數為16位寄存器時,將4字節的存儲器操作數中的低兩字節送指定寄存器,高兩字節送段寄存器FS;當目的操作數為32位寄存器時,將6字節的存儲器操作數中的低4字節送指定寄存器,高兩字節送段寄存器FS。該指令不影響狀態標志位。
【例3.33】LFS BX, ARRAY
指令執行情況如圖3.22所示。

圖3.22 指令執行情況
(2)LGS寄存器,存儲器
該指令與LFS指令功能基本相同,唯一區別在于,該指令所涉及的段寄存器為GS。
(3)LSS寄存器,存儲器
該指令與LFS指令功能基本相同,唯一區別在于,該指令所涉及的段寄存器為SS。
4. 運算指令
在8086/8088指令系統中,乘法指令只給出一個操作數,另一個操作數隱含在AL或AX中,80386將其擴充為可以有兩個或3個操作數。
(1)IMUL寄存器,寄存器/存儲器/立即數
將通用寄存器中的有符號數作為被乘數,相同位數通用寄存器、存儲單元中的有符號數或立即數(如立即數與目的操作數不等長,運算時機器會自動將其符號擴展成與目的操作數等長)作為乘數,乘積送目的操作數。若乘積溢出,溢出位部分將丟失,且將OF及CF置1;否則將OF及CF置0。
說明:目的操作數的位數必須與源操作數位數相同。
例如: IMUL DX, 9
(2)IMUL寄存器,寄存器/存儲器,立即數
與前一指令功能基本相同,唯一區別在于,寄存器/存儲器為被乘數,立即數為乘數,乘積存放在第一個操作數中。例如:
IMUL EAX,DWORD DTR[BX],9 ; 將BX所指定的4字節存儲器操作數乘以9, 乘積送32位 通用寄存器EAX。
(3)CWDE
將AX中16位有符號數的符號位擴展到EAX的高16位中,即把AX的16位有符號數擴展為32位后,送EAX。
(4)CDQ
將EAX中32位有符號數擴展到EDX:EAX寄存器對中,使之成為64位有符號數,即將EAX中的符號位擴展到EDX中。
【例3.34】若DATA1中為16位有符號數,值為-5,DATA2中為32位有符號數,值為-7。將DATA1擴展成32位有符號數,將DATA2擴展成64位有符號數。
MOV AX,DATA1 ;AX中為-5(FFFBH) CWDE ; 擴展后EAX中為32位的-5(FFFF FFFBH) MOV EAX,DATA2 ;EAX中為-7(FFFF FFF9H) CDQ ; 擴展后EDX:EAX中為64位的-7(FFFF FFFF FFFF FFF9H)
5. 移位指令
(1)移位指令助記符 寄存器/存儲器 立即數(≤31)
8086中有8條移位指令,移位計數使用CL或1表示,且規定當移位次數大于1時,必須使用CL。從80286開始,則修改了上述的限制,當移位次數為1~31時,允許使用立即數。例如:
ROL AX,5 SHL WORD PTR[BX],18
(2)SHLD寄存器/存儲器,寄存器,CL/立即數
將第一操作數(16位或32位通用寄存器或存儲單元)左移若干位(左移位數由8位立即數或CL指定),空出位用第二操作數(與第一操作數長度相同的通用寄存器)高位部分填補,但第二操作數的內容不變,CF標志位中保留第一操作數最后的移出位。若僅移一位,當CF值與移位后的第一操作數的符號位不一致時,OF置1;否則OF置0。移位過程如圖3.23所示。

圖3.23 SHLD指令功能
【例3.35】MOV AX,8321H MOV DX,5678H SHLD AX,DX,1 ;(AX)=0642H,DX=5678H,CF=1,OF=1; SHLD AX,DX,2 ;(AX)=1909H,DX=5678H,CF=0,OF=0。
(3)SHRD寄存器/存儲器,寄存器,CL/立即數
將第一操作數(16位或32位通用寄存器或存儲器單元)右移若干位(右移位數由CL或8位立即數指定),空出位用第二操作數(與第一操作數長度相同的通用寄存器)低位部分填補,指令執行后,第二操作數內容不變,CF標志位中保留第一操作數最后的移出位。移位過程如圖3.24所示。

圖3.24 SHRD指令功能
【例3.36】MOV AX,4B02H ;AX=0100101100000010 MOV BX,6040H ;BX=0110000001000000 SHRD AX,BX,7 ;AX右移7位,BX的低7位移入AX中, 結果為AX=10000000 10010110(8096H), BX=6040H(保持不變), CF=0。
指令執行情況如圖3.25所示。

圖3.25 指令執行情況
6. 位操作指令
(1)位測試及設置指令
測試指令可用來對指定位進行測試,因而可根據該位的值來控制程序流的執行方向,而置位指令可對指定的位進行設置。
① BT 存器/存儲器地址,寄存器/立即數
第一操作數(16位或32位通用寄存器或存儲單元)指定要測試的內容,第二操作數(與第一操作數同長度的通用寄存器或8位立即數)指定要測試的位,將被測內容的指定測試位的值送CF,其他狀態標志不確定。
【例3.37】設BX指向一個存儲單元數,CX值為4。
BT [BX],CX ; 檢查由BX指向數據的第4位, 并將該位值送入CF; JC Swhere ; 若CF=1, 則轉移。
若用8086指令完成,可寫成:
MOV AX,[BX] ; 將BX指向的數裝入AX中; TEST AX,10H ; 檢查第4位是否為1; JNZ Swhere ; 若CF=1, 則轉移。
② BTC 存器/存儲器地址,寄存器/立即數
該指令在BT指令功能的基礎上,將被測位取反。
③ BTR 存器/存儲器,寄存器/立即數
該指令在BT指令功能的基礎上,將被測位清0。
④ BTS 存器/存儲器,寄存器/立即數
該指令在BT指令功能基礎上,將被測位置1。
【例3.38】MOV AX, 1234H
(2)位掃描指令
BT AX,2 ;(AX)=1234H,CF=1 BTC AX,2 ;(AX)=1230H,CF=1 BTR AX,2 ;(AX)=1230H,CF=0 BTS AX,2 ;(AX)=1234H,CF=0
位掃描指令用于找出寄存器或存儲器地址中所存數據的第一個或最后一個是1的位。該指令可用于檢查寄存器或存儲器或存儲單元是否為0。
① BSF 寄存器,寄存器/存儲器
對第二操作數(16位或32位通用寄存器或存儲器)從最低位到最高位進行掃描,將首先掃描到的“1”的位號送第一操作數(與第二操作數位數相同的通用寄存器),且使ZF置0。若第二操作數的各位均為0,則第一操作數的值不確定,且使ZF置1。其他狀態標志位不確定。
② BSR 寄存器,寄存器/存儲器
與BSF指令功能基本相同,唯一區別在于,該指令是從最高位到最低位進行掃描。
例如: MOV EAX,01234567H BSR ECX,EAX ;(ECX)=18H,ZF=0 BSF AX,CX ;(AX)=03H,ZF=0
7. 條件設置指令
這組80386特有的指令用于測試指定的標志位所處的狀態,并根據測試結果,將指定的一個8位寄存器或內存單元置1或置0。它們類似于條件轉移指令中的標志位測試,但前者根據測試結果將操作數置1或置0,而后者根據測試結果決定轉移還是不轉移。
指令格式為
SET條件 寄存器/存儲器
說明:條件是指令助記符的一部分,用于指定要測試的標志位。例如
SETZ AL ; 當ZF=1, 則(AL)=1, 否則(AL)=0 SETNC BYTE PTR[BX] ; 當CF=0, 則BX所指字節單元內容為1
8. 內存范圍檢查指令
格式:BOUND 16位寄存器,32位存儲器
以32位存儲器低兩字節的內容為下界,高兩字節的內容為上界。若16位寄存器的內容在此上、下界表示的地址范圍內,程序正常執行;否則產生INT 5中斷(DOS并未提供該類型中斷處理程序,使用時用戶需自行編寫)。當出現這種中斷時,返回地址指向BOUND指令,而不是BOUND后面的指令,這與返回地址指向程序中下一條指令的正常中斷是有區別的。
【例3.39】BOUND指令的應用。
DATA SEGMENT BOTTOM EQU 0 TOP EQU 19 ANS LABEL DWORD ; 給ANS分配32位地址; WANS DW BOTTOM,TOP ; 對邊界初始化; BOFF DB TOP+1 DUP(?) ; 分配數組; DATA ENDS CODE SEGMENT ┇ ; 假設SI為數組的地址指針; BOUND SI,ANS ; 檢查SI是否在數據地址范圍內, 否則進入類型5中斷; MOV DX,BOFF[SI] ; 若在范圍內, 繼續使用。 ┇ CODE ENDS
3.5.2 Pentium新增指令
1. 字節交換指令
格式:BSWAP寄存器
將32位通用寄存器以字節為單位進行高低字節的交換,即對指定寄存器的32位操作數的位31~24與位7~0,位23~16與位15~8交換。該指令不影響狀態標志位。
【例3.40】寄存器(EDX)=12345678H BSWAP EDX 則指令執行后,(EDX)=78563412H。
80X86系列處理器按“高高低低”的原則存儲多字節數據,但某些處理器按“低低高高”的原則存儲數據,BSWAP指令特別適宜于這兩種數據格式之間的轉換。
2. 互換并相加指令
格式:XADD寄存器/存儲器,寄存器
該指令將第一操作數(8位,16位或32位通用寄存器或存儲單元)與第二操作數(與第一操作數位數相同的通用寄存器)內容互換,并將兩者之和送第一操作數。該指令對狀態標志位的影響與ADD指令相同。
【例3.41】若BX所指單元內容為11223344H,(EAX)=00224466H, XADD [BX],EAX
指令執行后,(EAX)=11223344H,而BX所指單元內容為1144 77AAH。XADD指令功能相當于XCHG和ADD這兩條指令的功能。該指令允許使用LOCK前綴。
3.比較并交換指令
(1)格式:CMPXCHG寄存器/存儲器,寄存器
該指令將第一操作數(8位,16位或32位通用寄存器或存儲單元)內容與對應長度的累加器(AL,AX或EAX)內容作比較,若相等,則使ZF置1,且將第二操作數(與第一操作數位數相同的通用寄存器)內容送第一操作數;否則使ZF清0,且第一操作數送對應累加器。
【例3.42】CMPXCHG ESI,EBX
若(ESI)=(EAX),則ZF=1,且將(EBX)送ESI;否則ZF=0,且將(ESI)送EAX。
(2)8字節比較交換指令
格式:CMPXCHG8B存儲器
將EDX:EAX中的8字節值與指定的8字節存儲器操作數相比較,若相等,則使ZF置1,且將ECX:EBX中的值送指定的8字節存儲單元替換原有存儲器操作數;否則使ZF=0,且將指定的8字節存儲操作數器送EDX:EAX。
【例3.43】設BX所指8字節存儲單元內容為0011223344556677H,(EDX)=0,(EAX)=FFFF FFFFH。
CMPXCHG8B [BX]
則該指令執行后,(EDX)=00112233H,(EAX)=44556677H,ZF=0。
4.Cache管理指令
(1)使整個片內Cache無效指令
格式:INVD
該指令用于將CPU內部Cache的內容無效。其具體的操作是刷新內部Cache,并分配一個專用總線周期刷新外部Cache,執行該指令不會將外部Cache中的數據寫回主存,即Cache中數據自然丟失。
(2)寫回并使Cache無效指令
格式:WBINVD
該指令功能與INVD相似,具體操作是刷新內部Cache。并分配一個專用總線周期將外部Cache的數據寫回主存,并在此后的一個專用總線周期將外部Cache刷新。
(3)使TLB無效指令
格式:INVLPG
該指令使頁式管理機構內的高速緩沖器TLB中的某一項作廢。若TBL中含有一個存儲器操作數映象的有效項,則該TBL項被標記為無效。
5.處理器特征識別指令
格式: CPUID
根據EAX中的參數,將處理器的說明信息送EAX,特征標志字送EDX。
6.讀時間標記計數器指令
格式: RDTSC
將Pentium中的64位時間標記計數器的高32位送EDX,低32位送EAX。該計數器隨每一個時鐘遞增,在Reset后該計數器被置0。利用該計數器可檢測程序運行性能。
7.讀模型專用寄存器指令
格式: RDMSR
將ECX所指定的模型專用寄存器的內容送EDX、EAX,具體來說,高32位送EDX,低32位送EAX。若所指定的模型寄存器不是64位,則EDX、EAX中的對應位無定義。
8.寫模型專用寄存器指令
格式: WRMSP
將EDX、EAX的內容送到由ECX指定的模型專用寄存器。具體來說,EDX和EAX的內容分別作為高32位和低32位。若指定的模型寄存器有未定義或保留的位,則這些位的內容不變。
本小節只是簡單介紹了Pentium新增指令,對這幾條指令的理解和應用要求具備Pentium體系結構方面的知識,請參閱有關文獻資料。
習題
3.1 分別指出下列指令中源操作數和目的操作數的尋址方式。
1)MOV AX,0100H 2)MOV [SI],AL 3)ADC BL,[2000H] 4)AND BYTE PTR[2000H],1 5)MOV 2[BX][DI],DX 6)OR AX,80H[SI]
3.2 指出以下指令是否合法。
1)MOV CS,AX 2)MOV [2000H],AL 3)ADD [2000H],40H 4)MUL AX,BX 5)AND 184CH,AX 6)MOV DS,0 7)INC [BX] 8)SBB AX,[DX] 9)RCL BX,2 10)POP AL 11)XCHG BX,4050H 12)CWB
3.3 試根據以下要求寫出相應的匯編語言指令。
1)將CX寄存器的內容與DX寄存器的內容相加,結果存入DX寄存器中。
2)用寄存器BX和DI的基址變址尋址方式把存儲器中的一個字節數據與AH寄存器的內容相加,并把結果存入AH寄存器中。
3)用寄存器BX和位移量2000H的寄存器相對尋址方式把存儲器的一個字數據和(DX)相加,并把結果送回存儲器中。
4)將數0C3H與(BL)寄存器相加,結果送回BL寄存器中。
5)將存儲器數據段中1300H單元(采用直接尋址方式)中的一個字數據與立即數3456H相減,結果送回存儲器1300H單元。
3.4 假設AX中的數據為6987H,DATE1分別為下列數值時,執行ADD AX,DATE1指令后,標志位SF、ZF、CF和OF的狀態是什么?
1)1234H 2)4801H 3)EB30H 4)902AH
3.5 假設AX中的數據為3760H,DATE1分別為下列數值時,執行CMP AX,DATE1指令后,標志位SF、ZF、CF和OF的狀態是什么?
1)1234H 2)4801H 3)EB30H 4)902AH
3.6 設(SP)=2040H,(AX)=12D4H,(BX)=36F4H。試回答:
1)執行PUSH AX指令后,(SP)=?
2)再執行PUSH BX及POP AX指令后,(SP)=?,(AX)=?
3.7 寫出執行以下計算的指令序列,其中X,Y,Z,R和Q均為存放16位帶符號數單元的地址。
1)Q←X+(Z-Y) 2)Q←X+(Y+9)-(Z+3) 3)Q←(X*Y)+(Z/R) 4)Q←5*(X-Y)+R/(Z+8)
3.8 現有(DS)=4000H,(BX)=0100H,(SI)=0002H,(40100H)=11H,(40101H)=22H,(40102H)=33H,(40103H)=44H,(41200H)=55H,(41201H)=66H,(41202H)=77H,(41203H)=88H,試說明下列各條指令執行完成后AX的內容。
1)MOV AX,0100H 2)MOV AX,[BX] 3)MOV AX,1200H 4)MOV AX,BX 5)MOV AX,[BX][SI] 6)MOV AX,1100H[BX] 7)MOV AX,1100H[BX][SI] 8)MOV AX,2[BX]
3.9 已知:(DS)=2000H,(ES) =3000H,(CS)=5000H,(SS)=4000H (AX)=5566H,(BX)=1000H,(BP)=0010H,(21000H)=1122H,(31000H)=7766H,(40010H)= 0FFFFH。
請寫出下列各條指令獨立執行完后,有關寄存器及存儲單元的內容。
1)ADD AL,[BX] 2)AND AX,BX 3)SUB ES:[BX],AX 4)XOR [BP],AX
3.10 在數據段DATA中已為0120H單元定義的符號名為MESS,其中存放的數據為1122H。
1)試問以下兩條指令有什么區別,指令執行結束后AX寄存器的內容是什么。
MOV AX,MESS LEA AX,MESS
2)試問以下兩條指令有什么區別,指令執行結束后AX寄存器的內容是什么。
MOV AX,MESS MOV AX,OFFSET MESS
3.11 寫出各種使AL置0的指令。
3.12 用兩種方法實現將(AL)乘以10值送AX的功能。
3.13 寫一程序段,將附加段2000H~2003H四個字節之和送AX。
3.14 假設(DX)=0F7H,變量DATA1中內容為9EH,確定下列每條指令執行后的結果。
1)AND DX,DATA1 2)XOR DX,DATA1 3)OR DX,DATA1 4)SHL DX,1 5)XOR DX,0FFH 6)AND DX,0H 7)TEST DX,80H 8)TEST DX,01H
3.15 試寫出移位指令執行后BX寄存器的內容,執行前(BX)=6CB5H,CF=0。
1)MOV CL,04H SHR BX,CL 2)MOV CL,03H SAL BX,CL 3)ROR BX,1 4)MOV CL,06H RCR BX,CL
3.16 若(AX)=0012H,(BX)=0034H,則下列指令執行后AX為多少?
MOV CL,8 ROL AX,CL ADD AX,BX
3.17 試分析下面的程序段所完成的功能。
MOV CL,4 SHL DX,CL MOV BL,AH SHL AX,CL SHR BL,CL OR DL,BL
3.18 下列程序段執行后(AL)=?(DL)=?完成的是什么功能?
MOV CL,4 MOV AL,48H MOV DL,AL AND AL,0FH OR AL,30H SHR DL,CL OR DL,30H
3.19 編寫程序使:
1)BX寄存器低4位置1
2)AX寄存器的低4位清0
3)AX寄存器各位取反
4)CX寄存器的低4位取反
5)用TEST指令測試AL寄存器的位1、位5和位7是否同時為1,如果是則把0FFH送CL寄存器,否則將0送CL寄存器。
6)將AH的低4位與AL的低4位拼成一個字節(AH的低4位為拼裝后的高4位),結果送AH中。
3.20 說明80386的32位通用寄存器與16位通用寄存器這間的關系。
3.21 80386的尋址方式有何特點。
3.22 設AX中有一有符號數,請用兩條不同的指令將AX中的值擴展到EAX中。
3.23 請用兩條不同的指令使BX所指的32位存儲器操作數的第20取反。
3.24 用一條指令實現把EAX中的32位數保存到寄存器對DX:AX中。
3.25 設寄存器對EDX:EAX中放有0102030405060708H,請寫出指令使其中的內容成為0807060504030201H。
3.26 試給出下列指令序列執行后目的寄存器的內容。
1)MOV BX,-10H MOVSX EBX,BX 2)MOV DL,-37H MOVSX ECX,DL 3)MOV AX,37H MOVZX ECX,AX 4)MOV CL,0A3H MOVZX EAX,CL
3.27 編寫程序段,將EBX、ECX和ESI寄存器的內容相加,其和存入EDI寄存器中(不考慮溢出)。
- SoapUI Cookbook
- AngularJS Web Application Development Blueprints
- Eclipse Plug-in Development:Beginner's Guide(Second Edition)
- 用Flutter極速構建原生應用
- The Data Visualization Workshop
- RabbitMQ Cookbook
- 移動增值應用開發技術導論
- Clojure for Java Developers
- Java 7 Concurrency Cookbook
- 精益軟件開發管理之道
- Getting Started with the Lazarus IDE
- Mastering Data Analysis with R
- Mastering Magento Theme Design
- Learning GraphQL and Relay
- Learning Scrapy