8086指令系統學習


學習指令關注:

  • 指令的匯編格式
  • 指令基本功能
  • 指令支持的尋址方式
  • 指令執行對標志位的影響
  • 指令的特殊要求

數據傳送類指令

  • 通用數據傳送指令:MOV、XCHG、PUSHPOP
  • 累加器專用傳送指令:IN、OUT、XLAX
  • 地址傳送指令:LEA、LDS、LES
  • 標志寄存器傳送指令:LAHF、SAHF、PUSHF、POPF
  • 符號擴展指令:CBWCWD

除了SAHF和POPF指令外,均不影響標志位

通用數據傳送指令MOV

格式:MOV DST,SRC;(DST)<--(SRC)

數據傳輸規則

數據傳輸規則

非法指令主要現象:

  • 兩個操作數的類型不一致,或者不確定;
    • MOV [BX][SI],1;兩個操作數類型不明確
    • MOV BP,AL;兩操作數類型不一樣
  • CS不能作為目的操作數(不能顯示地修改),DX不能作為存儲器尋址的寄存器
  • 傳送方向錯誤

后續的雙操作數指令一般也是這樣規定指令的

數據交換指令XCHG(exchange)

格式:XCHG OPR1,OPR2;(OPR1)<-->(OPR2) 兩操作數值交換

注意:

  • 遵守數據傳輸規則
  • 兩個操作數都不能使用段寄存器和IP,也不能使用立即數

換碼指令XLAT(查表指令)

格式:XLATXLAT OPR;(DS:[BX+AL])->AL (OPR是為了提高可讀性)

可用於將一種代碼轉換為另外一種代碼

使用方法:

  • 先在數據段中建立一張字節表格(長度不超過256,即2^8),表格的內容是要換取的代碼
  • 表格的首地址送寄存器BX
  • 要換取的對應編碼相對於表格首地址的位移量送寄存器AL
  • 執行XLAT,AL中即為轉換后的編碼

堆棧操作

堆棧是主存中一塊連續的存儲區域,常用於數據的暫存、交換、子程序的參數傳遞等場合。

堆棧操作按照后進先出原則。

  • 在8086系統里,堆棧所在的段為堆棧段,最大空間為64KB。
    • 段地址由SS寄存器指示
    • SP始終指示棧頂單元
  • 8086系統從較大地址開始分配和使用(其他段地址從小地址開始)
SSEG SEGMENT STACK;堆棧段開始
	DW 100 DUP(?) ;大小為100字
SSEG ENDS		  ;堆棧段結束

程序裝入時,操作系統將SSEG的段基址置入SS,堆棧段的字節置入SP,即200(0C8H)

如果未定義堆棧段,用戶程序裝入內存時:

ES,DS指向PSP(Program Segment Prefix 程序段前綴區);SS指向用戶程序區;CS指向用戶代碼段;(SP)=0000H指向64KB存儲器尾部

對於8086系統堆棧操作:

  • 進棧操作:PUSH SRC

    • 執行:(SP) <- (SP)-2; ((SP)+1,(SP)) <- (SRC);
  • 出棧出棧:POP DST

    • 執行:(DST) <- ((SP)+1,(SP)); (SP) <- (SP)+2;

注意:

  • 對於8086系統堆棧操作只支持字為單位的操作
  • 不支持立即尋址
  • CS不能作為目的操作數

地址傳送指令

  • 有效地址送寄存器指令:

    LEZ REG, SRC; (REG) <- SRC

  • 指針送寄存器和DS指令

    LDS REG,SRC; (REG) <-(SRC), (DS) <- (SRC+2)

    取兩個字分別送往寄存器和DS

  • 指針送寄存器和ES指令

    LES REG, SRC; (REG) <- (SRC), (ES) <- (SRC+2)

注意:

  • REG不能為段寄存器
  • SRC必須為存儲器尋址方式

LEA與MOV區別

標志寄存器傳送指令

操作數都隱藏

  1. 標志送AH指令:LAHF ; (AH) <- (FLAGS低字節)

  2. AH送標志寄存器指令:SAHF; (FLAGS低字節) <- (AH)

  3. 標志進棧指令:PUSHF; (SP) <- (SP)-2, ((SP)+1, (SP)) <- (FLAGS)

  4. 標志出棧指令:POPF; (FLAGS)<- ((SP)+1,(SP)) , (SP)<-(SP)+2

POPF,PUSHF可用於子程序中,分別用來恢復主程序標志與保存主程序標志

類型轉換指令(符號位擴展指令)

  • CBW; (AL)->AX 將字節擴展為字
  • CWD; (AX)->(DX,AX) 將字擴展為雙字

操作數隱含,擴展為符號位擴展。

若(AX) = BA45H

CWD; (DX)=FFFFH,(AX)=BA45H

CBW; (AX)=0045H


關於無符號擴展,只要將高半部分清0即可,可以通過MOV來實現

算法運算類指令

加法指令

  • 加法指令:ADD DST,SRC ;(DST)<-(DST)+(SRC)
  • 帶進位加法:ADC DST,SRC ;(DST)<-(DST)+(SRC)+CF
  • 加1指令:INC OPR

注意:

  • 加法指令影響狀態標志位,但INC指令不影響CF標志位
  • 支持的操作數類型和MOV同,但操作數不能為段寄存器

減法指令

  • 減法指令:SUB DST,SRC ;(DST)<-(DST)-(SRC)
  • 帶借位減法:SBB DST,SRC ;(DST)<-(DST)-(SRC)-CF
  • 減一指令:DEC OPR ;(OPR)<-(OPR)-1
  • 求補指令:NEG OPR ;(OPR)<-0-(OPR)
  • 比較指令:CMP OPR1,OPR2 ;(OPR1)-(OPR2)

注意:

  • 減法指令影響狀態標志位,但DEC指令不影響CF標志位
  • 減法指令對標志位的影響和加法指令不同。詳細看

XYZW均為已定義的雙字數據,用指令序列實現:

W<-X+Y+24-Z

DATA SEGMENT
	X DD 778899AAH
	Y DD 9ABCDEF0H
	Z DD 56789ABCH
	W DD ?
DATA ENDS
CODE SEGMRNTma
	ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
	  MOV DS,AX
	  MOV AX,WORD PTR X
	  MOV DX,WORD PTR X+2
	  ADD AX,WORD PTR Y  ;X+Y低字部分
	  ADC DX,WORD PTR Y+2;X+Y高字部分
	  ADD AX,24
	  ADC DX,0
	  SUB AX,WORD PTR Z
	  SBB DX,WORD PTR Z+2
	  MOV WORD PTR W,AX
	  MOV WORD PTR W+2,DX ;結構存入W

乘法指令

  • 無符號數乘法指令:MUL SRC
  • 有符號數乘法指令:IMUL SRC

執行操作:

(根據SRC類型判斷執行哪種操作,結果為雙倍字長)

  • 字節操作:(AX)<-(AL)X(SRC)
  • 字操作:(DX,AX)<-(AX)x(SRC)

注意:

  • SRC若為存儲器操作數時,注意ptr明確類型;SRC不能為立即數和段寄存器

  • 除了CF與OF外,對其他標志位沒有定義(執行后標志是任意的,不可預測)

  • 乘法指令對CF/OF的影響:(高半位有無有效數字)

    MUL指令:\(CF,OF=\left\{\begin{array}{rcl}00 &乘積的高一半為0\\11&否則\end{array}\right.\)

    IMUL指令:\(CF,OF=\left\{\begin{array}{rcl}00 &乘積的高一半是低一半的符號擴展\\11&否則\end{array}\right.\)

除法運算

  • 無符號數除法運算:DIV SRC
  • 有符號數除法運算:IDIV SRC

執行操作:(被除數是除數的雙倍)

  • 字節操作:

    (AL)<-(AX)/(SRC)的商

    (AH)<-(AX)/(SRC)的余數

  • 字操作

    (AX)<-(DX,AX)/(SRC)的商

    (DX)<-(DX,AX)/(SRC)的余數

注意:

  • SRC若為存儲器操作數時,注意ptr明確類型;SRC不能為立即數
  • 對所有的狀態標志位均無定義
  • 兩N位數相除,應首先把被除數符號擴展為2N位

位運算類指令

邏輯運算指令

  • 非:NOT OPR
  • 與:AND DST,SRC
  • 或:OR DST,SRC
  • 異或:XOR DST,SRC
  • 測試:TEST OPR1,OPR2 ;(OPR1)與(OPR2)

注意:

  • NOT指令不影響標志位;除了NOT外,其他均影響
  • CF,OF標志位清0;SF,PF,ZF根據運算結果的特征設置;AF無定義

應用:

  • OR:有選擇地使操作數置1

  • AND:有選擇地清0

  • TEST:位測試,與條件轉移指令一起完成對特定位的判斷,實現相應的程序轉移

    判斷偶數:

    TEST AL,1 ;若為0則為偶數,則ZF=1
    JZ EVEN
    
  • XOR:

    • 有選擇地取反(和1異或取反,和0異或不變)
    • 寄存器清0(與自身進行邏輯異或,且執行速度快)

移位指令

  • 邏輯左移:SHL OPR,CNT

    CF<-左 右<-0

  • 邏輯右移:SHR OPR,CNT

    0->左 右->CF

  • 算術左移:SAL OPR,CNT

    CF<-左 右<-0

  • 算術右移:SAR OPR,CNT

    左->左 右->CF

  • 循環左移:ROL OPR,CNT

    CF<-左 右<-左

  • 循環右移:ROR OPR,CNT

    右->左 右->CF

  • 帶進位循環左移:RCL OPR,CNT

    CF<-左 右<-CF(初始)

  • 帶進位循環右移:RCR OPR,CNT

    CF(初始)->左 右->CF

操作數:

  • OPR可用除立即數以外的任何尋址方式
  • \(\left\{\begin{array}{rcl}CNT=1,&SHL&OPR,1\\CNT>1,&MOV&CL,CNT\\&SHL&OPR,CL\end{array}\right.\)

狀態標志位:

  • CF=移除的值

  • \(OF=\left\{\begin{array}{rcl}1&CNT=1時,最高有效位的值發生變化\\0&CNT=1時,最高有效位的值不變\end{array} \right.\)

    當CNT>1時,OF不確定

  • 除此之外,移位指令SF、ZF、PF根據移位結果設置,AF無定義

  • 循環移位指令:不影響SF、ZF、PF、AF

用移位指令實現:AX<-(AX)x10

SHL AX,1
MOV BX,AX
SHL AX,1   ;AX<-4(原AX)
SHL AX,1   ;AX<-8(原AX)
ADD AX,BX  ;AX<-(8AX)+(2AX)

將DX,AX中32位數值左移一維

SHL AX,1
RCL DX,1

表達式計算(應用)

X、Y、Z、V、W均為16位有符號數,計算W<-(V-(X*Y+Z-1234))/X

MOV AX,X
IMUL Y    ;X*Y
MOV CX,AX 
MOV BX,DX ;(BX,CX)為X*Y
MOV AX,Z
CWD       ;(DX,AX)為Z
ADD CX,AX
ADC BX,DX ;(BX,CX)為X*Y+Z
SUB CX,1234
SBB BX,0  ;(BX,CX)為X*Y+Z-1234
MOV AX,V
CWD       ;(DX,AX)為V
SUB AX,CX
SBB DX,BX ;(DX,AX)為V-(X*Y+Z-1234)
IDIV X	  ;(V-(X*Y+Z-1234))/X,商在AX,余數在DX
MOV W,AX  ;保存結果

轉移控制類指令

指令尋址方式(確定下一條將要執行指令地址的方法)

  1. 順序尋址

  2. 跳轉尋址:通過轉移控制類指令實現(主要是改變CS:IP的值)

    如何確定轉移控制類指令的轉向地址?

    • 直接尋址(用標號表達)

      指令代碼中直接給出地址差(目標地址相對於當前ip的位移量),將要轉移到的目標地址就是當前IP值加上地址差。

    • 間接尋址方式(用存儲器或存儲器操作數表達)

      代碼中指示寄存器或存儲單元,目標地址從中獲得

根據跳轉范圍不同,采用不同的轉移方式:

  • 段內尋址

    • 近轉移(near)

      • 在當前代碼64kB范圍內注意

      • 不需要修改CS段地址,只要改變IP偏移地址

    • 短轉移(short)

      • 轉移范圍可以用一個字
  • 段間尋址

    遠轉移(far)

    • 在1MB范圍內
    • 需要更改CS段地址和IP偏移地址
    • 目標地址必須用一個32位數表達,即邏輯地址

實際編程過程中,匯編程序會選擇處理轉移方式,也可以人為規定。

無條件轉移指令

JMP OPR; 程序無條件轉向OPR指令的目標地址開始執行指令

JMP 指令支持段內、段間轉移:

  1. 段內轉移

    JMP 標號

    • IP<-(IP)+標號(IP值的偏移量)

    • (CS)不變

  2. 段間轉移

    JMP FAR PTR 標號

    • (IP)<-標號轉移地址
    • (CS)<-標號段地址

條件轉移指令

有二十多個,將Jcc當做條件轉移指令的一個統稱:

JCC label;條件滿足,發生轉移

  • 若轉移:IP<-IP+8位位移量;否則順序執行

  • 只支持短轉移

  • 不影響標志位,但要利用標志位

根據利用的標志位不同,分為4種情況:

  1. 根據單個條件標志的設置情況轉移

    測試條件
    JZ(JE) ZF=1
    JNZ(JNE) ZF=0
    JS SF=1
    JNS SF=0
    JO OF=1
    JNO OF=0
    JP PF=1
    JNP PF=0
    JC CF=1
    JNC CF=0
  2. 測試CX的值為0則轉移

    JCXZ OPR ;(CX)=0

  3. 比較兩個無符號數,根據比較結果轉移

    指令 轉移條件 說明
    JA/JNBE OPR CF=0且ZF=0 X>Y時,轉移
    JAE/JNB OPR CF=0或ZF=1 X>=Y時,轉移
    JNAE/JBOPR CF=1且ZF=0 X<Y時,轉移
    JNA/JBE OPR CF=1或ZF=1 X<=Y時,轉移
  4. 比較兩個有符號數,根據比較結果轉移

    指令 轉移條件 說明
    JG/JNLE OPR SF=OF且ZF=0 X>Y時,轉移
    JGE/JNL OPR SF=OF或ZF=1 X>=Y時,轉移
    JNGE/JL OPR SF!=OF且ZF=0 X<Y時,轉移
    JNG/JLE OPR SF!=OF或ZF=1 X<=Y時,轉移

循環類指令

  • 循環指令:

    LOOP OPR ;測試條件:(CX)!=0

  • 為0(相等)循環指令:

    LOOPZ(LOOPE) OPR ;測試條件:ZF=1且(CX)!=0

  • 不為零(不相等)循環指令:

    LOOPNZ/LOOPNE OPR ;測試條件:ZF=0且(CX)!=0

執行步驟:

  1. (CX)<-(CX)-1
  2. 檢測是否滿足測試條件,如果滿足則(IP)<-(IP)+8位位移量,循環;不滿足則退出循環,順序執行。

注意:

  • CX為隱含計數器,存放循環次數

  • 只支持短轉移

  • 使用LOOPZ/LOOPE,LOONZ/LOOPNE指令來控制循環時,既有計數(CX)控制又有條件(ZF)控制。有兩種可能會結束循環。所以一般應用在循環結束后用條件轉移指令分開這兩種情況,分別處理。

	MOV CX,10
L1: ...
	...
	LOOP L1 ;L1到LOOP指令之間指令序列將重復執行10次

指令"MOV CX,10"稱為"裝載循環計數器",必須在循環前執行;若在循環中執行會造成死循環

計算1+2+3……+100,結果保存到SUM中

	  XOR AX,AX;累加器清0
	  MOV BX,1 ;BX<-1
	  MOV CX,100

AGAIN:ADD AX,BX
	  INC BX
	  LOOP AGAIN

	  MOV SUM,AX

子程序調用和返回指令


子程序是完成特定功能的一段程序

當主程序執行這個功能時,采用CALL調用指令轉移到子程序起始處;完成子程序后,采用RET指令返回到主程序繼續執行(利用堆棧保存返回地址)

子程序定義偽指令:

子程序名 PROC 屬性
	... ;子程序體
子程序名 ENDP
  • 子程序名:子程序入口的序號地址,子程序名應為合法的標識符,子程序名不能與同一源程序中的標號、變量名、其他子程序名等相同
  • 屬性:類型屬性(NEAR(缺省),FAR)

  1. 段內調用與返回

    • 段內直接調用

      CALL 子程序名 ;NEAR屬性

      操作:

      • (SP)<-(SP)-2
      • (SS:SP)<-(IP)
      • (IP)<-子程序入口偏移地址
    • 段內返回

      RET ;按NEAR屬性返回

      操作:

      • (IP)<-(SS:SP) ;從堆棧中取出返回地址
      • (SP)<-(SP)+2
    • 帶參數返回

      RET n ;帶參數返回

      操作:

      • (IP)<-(SS:SP) ;從堆棧中取出返回地址
      • (SP)<-(SP)+2+n;調整棧頂位置,回到之前的值

  2. 段間調用與返回

    • 段間調用

      CALL 子程序名

      操作:

      • (SP)<-(SP)-2
      • (SS:SP)<-(CS) ;入棧
      • (SP)<-(SP)-2
      • (SS:SP)<-(IP) ;入棧
      • (IP)<-子程序入口的偏移地址
      • (CS)<-子程序入口的段地址
    • 段間返回

      RET ;按FAR屬性返回

      • (IP)<-(SS:SP)
      • (SP)<-(SP)+2
      • (CS)<-(SS:SP)
      • (SP)<-(SP)+2
ZEROBYTES PROC
	PUSH AX
	PUSH CX		;保護現場
	XOR AX,AX	;AX清0
	MOV CX,128	;循環次數CX
ZEROLOOP: MOV [BX],AX ;將BX所對應的地址單元清0
	ADD BX,2	;修改地址
	LOOP ZEROLOOP
	POP CX		;恢復現場
	POP AX
ZEROBYTES ENDP

中斷與中斷返回指令

中斷指令有三條:INT、IRET、INTO

8086CPU支持256個中斷,每個中斷用一個8位二進制編碼標識(即中斷類型碼,也稱中斷向量號

中斷向量:中斷服務程序的入口地址(首地址),為含有段地址CS和偏移地址IP的32位邏輯地址。

中斷向量與中斷向量號的區別?

與子程序不同,中斷指令程序不能用中斷程序名標識中斷地址,因為中斷有隨機性。

中斷指令是統一管理的。

8086系統從物理地址0000H開始集中存放個中斷向量。

  • 按照中斷類型碼從小到大的順序依次存放
  • 每個中斷向量占4個字節(32位),采用小端方式存儲,其中高字為段地址,低字為偏移地址
  • 256個中斷占1KB區域(256 * 4=210 字節)即中斷向量表
  • 類型碼為N的中斷向量存放的物理地址為4N

中斷指令:INT n

執行操作:

(SP)<-(SP)-2
((SP)+1,(SP))<-(FLAGS)
(SP)<-(SP)-2
((SP)+1,(SP))<-(CS)
(SP)<-(SP)-2
((SP)+1,(SP))<-(IP)
(IP)<-(n*4)
(CS)<-(n*4+2)

中斷返回指令:IRET

執行操作:

(IP)<-((SP)+1,(SP))
(SP)<-(SP)+2
(CS)<-((SP)+1,(SP))
(SP)<-(SP)+2
(FLAGS)<-((SP)+1,(SP))
(SP)<-(SP)+2

注意:

  • n(0~255)是中斷類型。由於類型碼為N的中斷向量存放的物理地址為4N,因而能找到它在中斷向量表對應的中斷向量,即段地址:偏移地址
  • INT會清零IF和TF,但不影響其他標准位
  • IRET影響標志位由堆棧中取出的值確定

一個指令:INT proc ;proc為23H

如何手動存儲CS:IP值?

XOR AX,AX ;AX清零
MOV DS,AX
MOV SI,34H*4 ;DS:SI = 0:34H*4 該中斷類型的邏輯地址
MOV WORD PTR [SI],offset proc
MOV WORD PTR [SI+2],SEG

溢出中斷指令INTO

功能: 檢測OF標志位

  • OF=1時產生中斷類型為4的中斷
  • OF=0時不起作用

指令完成操作(中斷類型碼為4):

  1. 標志寄存器入棧
  2. 斷點地址入棧,CS先入,然后IP入
  3. 從中斷向量表中獲取中斷服務程序入口地址(IP<-(0:11H,0:10H) CS<-(0:12H,0:13H)

處理機控制指令

用於修改標志寄存器的標志位或控制CPU的動作

  1. 標志位操作指令完成標志位的復位,置位等操作
  2. 外部同步指令用於控制CPU,不影響標志位
標志位操作指令格式 操作
STC CF<-1
CLC CF<-0
CMC CF取反
STD DF<-1
CLD DF<-0
STI IF<-1,開中斷
CLI IF<-0,關中斷

外部同步指令:

  1. 處理器暫停指令HLT:使處理器處於暫停,只有復位信號(RESET)、外部中斷請求(NMI、INTR)可使其退出;常用於等待中斷或多處理機的同步操作
  2. 處理機等待指令WAIT:處理檢測\(\overline{\text{TEST}}\) 引腳信號。\(\overline{\text{TEST}}\) 為高電平時處理器空轉;\(\overline{\text{TEST}}\) 為低電平時,處理器退出中轉,執行后續操作
  3. 空操作NOP:占一個指令周期,用於調整延時


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM