指令是使計算機執行某種特定操作的二進制編碼。
8086 CPU指令系統有133條指令,通常分為數據尋址方式和程序尋址方式
8086指令是不定長,一般為1~6個字節。
數據尋址方式
隱含尋址
指令已經默認對CPU中的某個寄存器進行操作,不用在指令中指明所使用的寄存器,即隱含了規定的操作數,這樣的尋址方式稱為隱含尋址。立即數尋址
寄存器尋址
存儲器操作數尋址
執行單元EU根據指令中給出的尋址方式計算出16位的偏移量,稱為有效地址(EA)送到總線接口單元BIU,經過加法器生成20位實際物理地址,在存儲器讀寫總線周期對存儲器進行操作,一般在表示EA時,用 [操作數] 表示。
由于計算EA需要時間,進行總線操作比較慢,因此存儲器操作尋址比前三種要慢。
直接尋址
例:MOV SI, [2000H]
默認使用DS段,若需使用其他段可使用段超越:MOV SI, ES:[2000H]-
寄存器間接尋址
可間接尋址的寄存器有:BX、BP、SI、DI
例:MOV AL, [BX]BX用于間接尋址時,默認段寄存器為DS,允許段超越 BP用于間接尋址時,默認段寄存器為SS,允許段超越 SI用于間接尋址時,默認段寄存器為DS,允許段超越 DI用于間接尋址時,只有在串操作指令中,默認段寄存器為ES,其余情況默認段寄存器均為DS,不允許段超越
注:IP只能在代碼段中(CS)尋址,SP只能在堆棧段(SS)中尋址
-
寄存器相對尋址
基址尋址
操作數的有效地址是一個基址寄存器的內容加上一個8位或者16位的偏移量,基址寄存器是BX或者BP。
例:MOV AX,[BX+1000H]
有時也寫成 MOV AX,1000H[BX]或MOV AX,[BX]1000H變址尋址
操作數的有效地址是一個變址寄存器的內容加上一個8位或者16位的偏移量,變址寄存器是SI和DI。
例:MOV AX, ARRAY[SI]基址加變址尋址
操作數的有效地址是由基址寄存器和變址寄存器的內容相加產生
例:MOV AX, [BP+SI]相對的基址加變址尋址
操作數的有效地址是由基址寄存器、變址寄存器和偏移量三者相加產生。
例:MOV AX, [BX+SI+3H]
也可寫成MOV AX,3H[BX][SI]或MOV AX,3H[BX+SI]數據串尋址
DS:SI指示源串,ES:DI指示目的串,串長度計數用CX,并自動修改指針和計數器值,只用于串操作命令。
例:MOVSB ;((ES:DI))((DS:SI)),CX=CX-1,SI=SI+1,DI=DI+1
- I/O端口尋址
操作數存放在I/O端口中,指令執行時必須通過累加器(AX或AL)實現對端口的訪問
直接端口尋址
指令直接提供8位端口的地址。
例:IN AL, 63H
當端口地址用一個字節來表示時,可使用直接端口尋址間接端口尋址
由DX寄存器給出16位端口地址。
例:MOV DX, 162H
IN AX, DX
程序尋址方式
段內直接尋址
短跳轉:把IP的內容加上一個字節的補碼數作為新的IP,往前最多跳-128個字節,往后最多跳127個字節。
近跳轉:把IP的內容加上兩個字節的補碼數作為新的IP,往前最多跳-32768個字節,往后最多跳32767個字節。
段內間接尋址
將寄存器或存儲器操作數的內容賦給IP
段間直接尋址
直接在指令中給出新的CS和IP內容
段間間接尋址
用存儲器操作數的內容賦給CS和IP
8086指令格式
指令一般由1~6個字節組成,具體格式如下圖:
- 字節1
OPCODE:指令操作碼
-
D:操作數傳輸方向(立即數指令和串操作指令除外)
- D=0,Reg為源操作數
- D=1,Reg為目的操作數
-
W:操作數字節長度
- W=0,字節操作
- W=1,字操作
- 字節2,尋址方式
- MOD:尋址方式字段
- 00=存儲器方式,指令中無偏移量
- 01=存儲器方式,指令中有8位偏移量
- 10=存儲器方式,指令中有16位偏移量
- 11=寄存器方式,指令中無偏移量
- Reg:寄存器編碼字段
000=AL/AX | 100=AH/SP | 001=CL/CX | 101=CH/BP |
---|---|---|---|
010=DL/DX | 110=DH/SI | 011=BL/BX | 111=BH/DI |
- R/M:寄存器/存儲器字段
- 在MOD=11,寄存器模式下,R/M給出第二個操作數的寄存器編碼。
-
在MOD≠11,存儲器模式下,R/M給出計算有效地址的方法。
image.png
- 字節3~字節6
DISP:存儲器操作數地址偏移量,長度由MOD字段定義
DATA:指令中的立即數
8086指令系統
操作數符號表示
符號 | 含義 |
---|---|
DST | 目的操作數 |
SRC | 源操作數 |
TARGET | 循環、轉移和調用指令操作數 |
imm | 立即操作數,字節或字 |
acc | 累加器AL或AX |
reg | 寄存器操作數 |
seg_reg | 段寄存器 |
mem | 存儲器操作數 |
short_label | 短標號(8位偏移量) |
near_label | 近標號(16位地址或偏移) |
far_label | 遠標號(32位地址) |
數據傳送指令
通用數據傳送指令 MOV DST,SRC
堆棧及堆棧操作
堆棧是一種按先進后出(FILO)原則存取的存儲器,它由堆棧指針寄存器SS:SP和RAM中的一部分組成,主要用于子程序調用或中斷子程序的現場保護和恢復,以及參數傳遞等。
SP的內容總是指向棧頂,即最后推入信息所在單元。
進棧指令 PUSH SRC
出棧指令 POP DST
交換指令 XCHG DST,SRC
-
累加器專用傳送指令
- 輸入指令 IN AL/AX,PORT/DX
- 輸出指令 OUT PORT/DX,AL/AX
PORT為8位直接地址 - 換碼指令 XLAT : (AL)←((BX)+(AL))
-
地址傳送指令
- 有效地址傳送指令 LEA reg16,SRC:(reg16) ←SRC
- 指針送寄存器和DS
LDS reg16,mem32 :(reg16) ←(mem32);(DS) ←(mem32+2) - 指針送寄存器和ES
LES reg16,mem32 :(reg16) ←(mem32); (ES) ←(mem32+2)
-
標志寄存器傳送
- LAHF : (AH) ←(flag低字節)
- SAHF : (flag低字節) ←(AH)
- PUSHF : (SP) ←(SP)-2, ((SP)+1),(SP)) ←flag
- POPF : flag ←((SP)+1),(SP)), (SP) ←(SP)+2
算術指令
- 加法指令
- ADD DST,SRC : (DST) ← (SRC) + (DST)
- ADC DST,SRC : (DST) ← (SRC) + (DST)+CF
- INC DST : (DST) ←(DST)+1 //不影響進位標志CF
- 減法指令
- SUB DST,SRC : (DST) ←(DST)-(SRC)
- SBB DST,SRC : (DST) ←(DST)-(SRC)-CF
- DEC DST : (DST) ←(DST)-1 //不影響進位標志CF
- NEG DST : (DST)=0-(DST) //求補指令
- CMP DST,SRC : (DST)-(SRC),僅影響標志 //比較指令
- 乘法指令
無符號數乘法
MUL SRC : (AX) ←(AL)*(SRC)或(DX,AX) ←(AX)*(SRC)有符號數乘法
IMUL SRC : (AX) ←(AL)(SRC)或(DX,AX) ←(AX)(SRC)
- 除法指令 //除數必須為被除數一半字長
無符號數除法指令 DIV SRC
(AL) ←(AX)/(SRC);(AH) ←(AX)%(SRC)
或(AX)←(DX,AX)/(SRC);(DX) ←(DX,AX)%(SRC)有符號數除法指令 IDIV SRC : 操作與DIV相同
- 類型轉換指令
字節轉換成字指令(有符號數)CBW
若(AL) <80H則(AH)←0,否則(AH) ←FFH即將AL符號位擴展到AH有符號字轉換成雙字指令CWD
若(AX)<8000H,則(DX) ←0,否則(DX) ←FFFFH
- BCD碼調整指令
加減運算非壓縮BCD碼高4位的值可不為0,乘除時高4位必須是0。
-
壓縮BCD碼調整指令
- DAA :對BCD碼加法運算結果(AL)進行調整。
- DAS :對BCD碼減法運算結果(AL)進行調整。
-
非壓縮BCD碼調整
- AAA :對非壓縮BCD碼加法運算結果進行調整,進位送(AH)中
- AAS :對非壓縮BCD碼減法運算結果進行調整
- AAM :對非壓縮BCD碼乘法運算進行調整
- AAD :對非壓縮BCD碼除法運算進行調整
邏輯指令
- 邏輯運算指令
- AND DST,SRC (DST) ←(DST)&(SRC)
- OR DST,SRC (DST) ←(DST)|(SRC)
- NOT DST ~DST
- XOR DST,SRC (DST) ←(DST)^(SRC)//異或
- TEST DST,SRC (DST)&(SRC),僅影響標志
- 移位指令
- 邏輯左移指令 SHL DST,count :DST左移count位,每左移一位,最低位補0,最高位進入CF
- count可以為數字,也可以為CL做移位計數。
- 算術左移指令 SAL DST,count :同SHL
- 邏輯右移指令 SHR DST,count :最高位添零,最低位進入CF
- 算術右移指令 SAR DST,count :最高位不變,最低位進入CF
- 循環左移指令 ROL DST,count :最高位進入CF和最低位
- 循環右移指令 ROR DST,count :最低位進入CF和最高位
- 帶進位循環左移指令 RCL DST,count
- 帶進位循環右移指令 RCR DST,count
串處理指令
- 數據串傳送指令:唯一的目的操作數和源操作數都在存儲器中的指令
-
串傳送指令 MOVSB/MOVSW :DST與SRC做類型檢查
- MOVSB : ((ES:DI)) ←((DS:SI)),(SI) ←(SI)±1, (DI)←(DI)±1
- MOVSW :((ES:DI)) ←((DS:SI)),(SI) ←(SI)±2, (DI) ←(DI)±2
其中,加、減地址指針SI和DI由FLAG中的DF決定,DF=0地址增加,DF=1地址減小。
-
建立方向標志指令
- CLD ;DF←0
- STD ;DF←1
REP重復前綴
例:REP MOVSB :以CX寄存器做計數器,每傳送一個數(CX)減1,直到(CX)為0。
REPZ/REPE : 若(CX)≠0且ZF=1時繼續執行,否則退出。
REPNZ/REPNE : 若(CX)≠0且ZF=0(比較不相等)時繼續執行,否則退出。-
存入串指令 STOSB/STOSW : DST做類型檢查
- STOSB : ((ES:DI)) ←(AL), (DI) ←(DI)±1
- STOSW : ((ES:DI)) ←(AX),(DI) ←(DI)±2
由DF決定方向,可加入前綴REP。
-
從串中取指令 LODSB/LODSW :SRC做類型檢查
- LODSB : (AL) ←((DS:SI)) , (SI) ←(SI)±1
- LODSW : (AX) ←((DS:SI)) ,(SI) ←(SI)±2
地址增減由DF決定
- 字符串掃描和比較指令
-
串比較指令 CMPS : SRC和DST僅做類型檢查
- CMPSB ;((DS:SI))-((ES:DI)), (SI) ←(SI)±1, (DI) ←(DI)±1
- CMPSW ;((DS:SI))-((ES:DI)), (SI) ←(SI)±2, (DI) ←(DI)±2
串比較僅影響標志,地址增減由DF決定。
-
串掃描指令 SCAS : DST做類型檢查
- SCASB : (AL)-((ES:DI)) ,(DI) ←(DI)±1
- SCASW : (AX)-((ES:DI)) ,(DI) ←(DI)±2
僅影響標志,地址增減由DF決定,可加條件前綴。
控制轉移指令
- 無條件轉移指令:JMP TARGET
- JMP short_label :(IP)<-(IP)+short_label 短跳轉
- JMP near_label :(IP)<-(IP)+near_label 近跳轉
- JMP far_label :(CS:IP)<-far_label 遠跳轉
- 條件轉移指令
- 根據單個標志轉移
指令 | 含義 | 測試條件 |
---|---|---|
JZ short_label | 結果為0轉移 | ZF=1 |
JE short_label | 結果相等轉移 | ZF=1 |
JNZ short_label | 結果不為0則轉移 | ZF=0 |
JNE short_label | 結果不相等則轉移 | ZF=0 |
JS short_label | 結果為負則轉移 | SF=1 |
JNS short_label | 結果非負則轉移 | SF=0 |
JNO short_label | 結果不溢出則轉移 | OF=0 |
JO short_label | 結果溢出則轉移 | OF=1 |
JP short_label | 奇偶為1則轉移 | PF=1 |
JPE short_label | 偶轉移 | PF=1 |
JNP short_label | 奇偶為0則轉移 | PF=0 |
JPO short_label | 奇轉移 | PF=0 |
JB short_label | 有借位轉移 | CF=1 |
JNAE short_label | 不大于等于轉移 | CF=1 |
JC short_label | 有進位轉移 | CF=1 |
JNB short_label | 無借位轉移 | CF=0 |
JAE short_label | 大于等于轉移 | CF=0 |
JNC short_label | 無進位轉移 | CF=0 |
- 兩個無符號數比較轉移
A大于 | B小于 | E等于 |
---|---|---|
JB/JNAE/JC | CF=1 | 小于 |
JNB/JAE/JNC | CF=0 | 不小于 |
JBE/JNA | CF|ZF=1 | 不大于 |
JNBE/JA | CF|ZF=0 | 大于 |
- 兩個有符號數比較轉移
G大于 | L小于 | E等于 |
---|---|---|
JL/JNGE | SF^OF=1 | 小于 |
JNL/JGE | SF^OF=0 | 不小于 |
JNLE/JG | (SF^OF)|ZF=0 | 大于 |
JLE /JNG | (SF^OF)|ZF=1 | 不大于 |
- 測試CX值,為0則轉移
JCXZ short_label :(CX)=0則轉移
- 循環指令
- LOOP short_label : (CX) ←(CX)-1,(CX)≠0則轉移
- LOOPZ/LOOPE short_label : (CX) ←(CX)-1,(CX)≠0且ZF=1則轉移
LOOPNZ/LOOPNE short_label :(CX) ←(CX)-1,(CX)≠0且ZF=0則轉移
- 子程序調用與返回
子程序調用指令 CALL TARGET
具體指令
CALL near_proc;段內調用
CALL far_proc;段間調用
CALL mem16/regp16/mem32;返回指令 RET
帶立即數返回 RET IMM16
在RET指令的基礎上,當從堆棧中彈出IP和CS后,再將SP加上一個字的立即數,使得返回后(SP) ← (SP) + IMM16
中斷調用與返回
- 中斷調用
INT n
依次將FLAG,當前CS和IP(即斷點地址)放入堆棧,清除IF和TF。執行中斷類型碼為n的中斷服務程序。
注: INT n 的機器碼為 CDH n,INT 3 的機器碼特殊,為 CCHINTO
在有符號數運算結束以后,可以使用INTO,若OF=1,則執行中斷指令INT 4,否則無操作。IRET
中斷返回指令,從中斷程序返回主程序,恢復斷點和FLAG
控制類指令
- 標志處理指令
- CLC/STC/CMC 對CF 清0 / 置位 /取反
- CLD/STD 對DF 清0 / 置位
- CLI/STI 對IF 清0 / 置位
- 處理器控制指令
NOP | 空操作指令 | 占用一個字節的機器碼,不執行任何操作 |
---|---|---|
HLT | (Halt)停機指令 | 該指令使處理器處于停機狀態,以便等待一次外部中斷到來 |
WAIT | 等待指令 | 該指令使處理器處于空轉狀態,也可用來等待外部中斷的到來 |
ESC | (Escape)換碼指令,用作前綴 | 格式:ESC MEM,其中MEM指出一個存儲單元,ESC指令把該存儲單元的內容送到數據總線去 |
LOCK | 封鎖指令,用作前綴 | 該指令與其他指令聯合,用來維持總線的封鎖信號直到與其聯合的指令執行完為止 |