彙編語言複習筆記2:指令系統

彙整自個人OneNote筆記。

指令格式

1
標號:   指令助記符 目的操作數, 源操作數 ; 註釋

數據傳送類指令

重點掌握:MOV XCHG XLAT PUSH POP LEA

通用數據傳送指令

傳送指令 MOV

1
2
3

mov byte ptr [si], 0ah ; ds:[si]←0ah,字節操作
mov word ptr [si+2], 0bh; ds:[si+2]←0bh,字操作

交換指令 XCHG

1
2

xchg reg, reg/mem ; reg←→reg/mem,也可寫做xchg reg/mem, reg

換碼指令 XLAT

1
2

xlat ; al←ds:[bx+al]

堆棧操作指令

1
2

push/pop r16

進棧指令 PUSH

使SP減2,把一個字操作數存入棧頂。

出棧指令 POP

把一個字操作數傳送至目的操作數,使SP加2。

標誌傳送指令

標誌寄存器傳送指令傳送FLAGS的內容;標誌位操作指令對CF DF IF標誌復位或置位。

標誌寄存器傳送 LAHF SAHF PUSHF POPF

1
2
3
4
5
6
7

lahf ; AH←FLAGS的低字節
sahf ; FLAGS的低字節←AH
;(上兩條指令,除AH的第7/6/2/4/0位外任意)
pushf ; SP←SP-2,SS:[SP]←FLAGS
popf ; FLAGS←SS:[SP],SP←SP+2

標誌位操作 CLC STC CMC CLD STD CLI STI

CF/DF/IF標誌復位或置位。
CL:復位爲0
ST:置位爲1
CM:求反

  • 任意設置進位標誌:CLC STC CMC

  • 串操作指令:CLD STD

  • 編寫中斷服務程序時,禁止/允許可屏蔽中斷:CLI STI

地址傳送指令

有效地址傳送指令 LEA

1
2

lea r16, mem ; r16←mem的有效地址

指針傳送指令 LDS LES

1
2
3

lds r16, mem ; r16←mem,ds←mem+2
les r16, mem ; r16←mem,es←mem+2

輸入輸出指令

與外設進行數據交換。
外設:端口(Port)即I/O地址

輸入指令 IN

輸出指令 OUT

算術運算類指令

重點:ADD/ADC/INC SUB/SBB/DEC CBW/CWD

加法指令

加法指令 ADD

帶進位加法指令 ADC

主要與ADD配合,實現多精度加法。

1
2

adc dest, src ; dest←dest+src+cf

增量指令 INC

減法指令

參考對應的加法指令。

減法指令 SUB

帶借位減法指令 SBB

減量指令 DEC

其他

求補指令 NEG

用0減去操作數,結果返回給操作數。
對標誌的影響與用0作減法的SUB指令一樣。

1
2

neg reg/mem ; reg/mem←0-reg/mem

比較指令 CMP

執行的功能與SUB相似,但結果不回送至目的操作數。
配合Jcc

乘法指令

利用OFCF判斷乘積的高一半是否具有有效數值。

MUL:高一半爲0,則OF=CF=0;否則均爲1。

IMUL:高一半爲低一半的符號擴展,則OF=CF=0;否則均爲1。

無符號乘法 MUL

1
2
3

mul r8/m8 ; 無符號字節乘法,ax←al×r8/m8
mul r16/m16 ; 無符號字乘法,dx.ax←ax×r16/m16

有符號乘法 IMUL

1
2
3

imul r8/m8 ; 有符號字節乘法,ax←al×r8/m8
imul r16/m16 ; 有符號字乘法,dx.ax←ax×r16/m16

除法指令

對標誌沒有定義。
會產生結果溢出(除法錯中斷,8086CPU編號爲0的內部中斷):

  • 除數爲0
  • 商超出範圍

無符號除法 DIV

1
2
3

div r8/m8 ; 無符號字節乘法,al←ax÷r8/m8的商,ah←ax÷r8/m8的餘數
div r16/m16 ; 無符號字乘法,ax←dx.ax÷r16/m16的商,dx←dx.ax÷r16/m16的餘數

有符號除法 IDIV

1
2
3

idiv r8/m8 ; 有符號字節乘法,al←ax÷r8/m8的商,ah←ax÷r8/m8的餘數
idiv r16/m16 ; 有符號字乘法,ax←dx.ax÷r16/m16的商,dx←dx.ax÷r16/m16的餘數

符號擴展指令 CBW CWD

不影響標誌位,常用於獲得倍長的數據。
64H(表示十進制100)最高位$D_7$爲0,符號擴展後爲0064H(仍表示十進制100);FF00H(表示十進制-256)最高位$D_{15}$爲1,符號擴展後爲FFFFFF00H(仍表示十進制256)。
利用符號擴展指令可得到除法指令所需的倍長於除數的被除數。

1
2
3

cwd
idiv bx

對無符號除法:直接清零即可。

壓縮BCD碼加減調整指令DAA DAS

OF無定義,但影響其他標誌,比如CF

1
2
3
4
5

add/adc al, i8/r8/m8
daa ; 將al的加和調整爲壓縮BCD碼
sub/sub al, i8/r8/m8
das ; 將al的減差調整爲壓縮BCD碼

非壓縮BCD碼加減乘除調整指令AAA AAS AAM AAD

1
2
3
4
5
6
7
8
9
10
11

add/adc al, i8/r8/m8
aaa ; 將al的加和調整爲壓縮BCD碼
; ah←ah+調整的進位
sub/sub al, i8/r8/m8
aas ; 將al的減差調整爲壓縮BCD碼
; ah←ah-調整的借位
mul r8/m8
aam ; 將ax的乘積調整爲非壓縮BCD碼
aad ; 將ax中非壓縮BCD碼調整爲二進制數
div r8/m8

位操作類指令

邏輯運算指令

邏輯與 AND

皆1方爲1。

1
2
3

add reg, imm/reg/mem
add mem, imm/reg

CF=OF=0;SF ZF PF根據結果;AF未定義。
可用於復位(0相與,1變0)。

邏輯或 OR

皆0方爲0。
標誌位變化同AND
可用於置位(1相或,0變1)。

邏輯異或 XOR

不同方爲1。
標誌位變化同AND
可用於求反(1相異或,1變0,0變1);自身XOR則清零。

邏輯非 NOT

按位取反,不影響標誌位。

1
not     reg/mem

測試指令 TEST

類似AND,結果不返回至操作數。

1
2

test al, 01h ; 測試最後一位是否爲0(是則ZF=1)

移位指令

邏輯左移 SHL

1
2

shl reg/mem, 1/cl ; 邏輯左移1/cl位(最低位補0,最高位進入CF)

邏輯右移 SHR

1
2

shr reg/mem, 1/cl ; 邏輯右移1/cl位(最高位補0,最低位進入CF)

算術左移 SAL

1
2

sal reg/mem, 1/cl ; 算術左移1/cl位(同SHL)

算術右移 SAR

1
2

sar reg/mem, 1/cl ; 算術右移1/cl位(最高位不變,最低位進入CF)

小結

若最高位改變:OF=1

  • shl/sal 1位相當於無符號數乘2

  • shr 1位相當於無符號數除以2

  • sar 1位相當於有符號數除以2(與idiv有別)

    • 如-5(FBH)經SAR右移1位等於-3(FDH),但IDIV指令執行-5÷2結果爲-2

循環移位指令 ROL ROR RCL RCR

1
2
3
4
5

rol reg/mem, 1/cl ; 不帶進位循環左移
ror reg/mem, 1/cl ; 不帶進位循環右移
rcl reg/mem, 1/cl ; 帶進位循環左移
rcr reg/mem, 1/cl ; 帶進位循環右移

控制轉移類指令

重點JMP JCC LOOP CALL RET INT n IRET 常用系統功能調用

CS:當前指令所在代碼段的段地址

IP:要執行的下一條指令的偏移地址

無條件轉移指令 JMP

段內轉移:

  • 近轉移(near):在當前代碼段64KB(±32KB)範圍內轉移。
  • 短轉移(short):在段內-128~127的範圍的轉移。

段間轉移:

  • 遠轉移(far):更改CS段地址和IP偏移地址。可在1MB範圍內轉移。目標地址用32位遠指針表示,即邏輯地址。

通常彙編程序根據位移量大小自動形成短轉移/近轉移/遠轉移指令。同時彙編程序也提供shortnear ptrfar ptr強制。

  • 段內轉移 相對尋址:jmp label ; ipip+位移量

  • 段內轉移 間接尋址:jmp r16/m16 ; ipr16/m16

1
2
3

jmp ax
jmp word ptr[2000h]
  • 段間轉移 直接尋址:jmp far ptr label ; iplabel的偏移地址,cslabel的段地址

  • 段間轉移 間接尋址:jmp far ptr mem ; ip[mem]cs[mem+2]

條件轉移指令 Jcc

1
2

jcc label

判斷單個標誌位狀態

  • JZ/JEJNZ/JNE利用ZF,判斷結果是否爲0(或相等)

  • JSJNS利用SF,判斷結果正負

  • JOJNO利用OF,判斷結果是否溢出

  • JP/JPEJNP/JPO利用PF,判斷結果中1的個數奇偶

  • JC/JB/JNAEJNC/JNB/JAE利用CF,判斷結果是否進位/借位

比較無符號數高低

高(Above)、低(Below)。
利用CF確定高低,利用ZF確定相等。

  • JB/JNAE

  • JNB/JAE

  • JBE/JNA

  • JNBE/JA

比較有符號數大小

大(Greater)、小(Less)。
利用SFOF確定大小,利用ZF確定相等。

  • JL/JNGE

  • JNL/JGE

  • JLE/JNG

  • JNLE/JG

循環指令 LOOP

1
2
3
4
5

jcxz label ; cx=0則轉移到標號label
loop label ; cx←cx-1;cx≠0則轉移到label
loopz label ; cx←cx-1;cx≠0且zf=1則轉移到label
loopnz label ; cx←cx-1;cx≠0且zf=0則轉移到label

子程序指令 CALL RET

子程序調用指令 CALL

1
2
3
4
5

CALL label ; 段內調用 直接尋址
CALL r16/m16 ; 段內調用 間接尋址
CALL far ptr label ; 段間調用 直接尋址
CALL far ptr mem ; 段間調用 間接尋址

CALL指令需要保存返回地址:

  • 段內調用:入棧偏移地址IP

    • SPSP-2,SS:[SP]IP
  • 段間調用:入棧偏移地址IP和段地址CS

    • SPSP-2,SS:[SP]IP
    • SPSP-2,SS:[SP]CS

子程序返回指令 RET

1
2
3
4
5

ret ; 無參數段內返回
ret i16 ; 有參數段內返回
ret ; 無參數段間返回
ret i16 ; 有參數段間返回

需要彈出CALL指令壓入堆棧的返回地址。

  • 段內返回:出棧偏移地址IP

    • IPSS:[SP]SPSP+2
  • 段间返回:出棧偏移地址IP和段地址CS

    • IPSS:[SP]SPSP+2
    • CSSS:[SP]SPSP+2

返回指令RET的參數

1
2

ret i16 ; SP←SP+i16

可以方便廢除執行CALL指令之前入棧的參數。

中斷指令 INT i8 IRET INTO

8086可管理256个中斷。

  • 外部中斷

    • 可屏蔽中斷:可由CPU中斷允许標誌IF控制
    • 非屏蔽中斷:不受CPU中斷允许標誌IF控制
  • 內部中斷

    • 除法錯中斷:溢出,0號中斷
    • 指令中斷:中斷調用指令 INT i8
    • 斷點中斷:斷點調試 INT 3
    • 溢出中斷:執行溢出中斷指令,OF=1產生的4號中斷
    • 單步中斷:TF=1在每條指令執行後產生的1號中斷
1
2
3
4

int i8 ; 中斷調用(產生i8號中斷)
iret ; 中斷返回
into ; 溢出中斷指令:若OF=1,產生4號中斷,否則順序執行

系統功能調用

INT 21H,AH=02H 輸出字符

DL=字符的ASCII碼

INT 10H,AH=0EH 輸出字符

AL=字符的ASCII碼

BL=字符顏色值(圖形方式)

BH=頁號(字符方式)

(通常使BX=0)

INT 21H,AH=09H 輸出字符串

DS:DX=欲顯示字符串在主存中的首地址,以$(24H)結束

INT 21H,AH=01H 輸入字符

AL=字符的ASCII碼

INT 16H,AH=0 輸入字符

AX=鍵值代碼

標準ASCII碼按鍵:AL=ASCII碼,AH=掃描碼

INT 21H,AH=0AH 輸入字符串

DS:DX=緩衝區首地址

緩衝區的定義

  • 第1字節:最多欲接收的字符個數(1-255,含回車)
  • 第2字節:實際輸入的字符個數
  • 第3字節開始:輸入的字符串

INT 21H,AH=0BH 按鍵判斷

AL=0,當前沒有按鍵;

AL=FFH,當前已經按鍵。
僅判斷當前是否有按下的鍵,設置AL後退出。

INT 16H,AH=1 按鍵判斷

ZF=1,無按鍵;

ZF=0,有按鍵,且AX=鍵值代碼。
僅判斷當前是否有按下的鍵,設置ZF後退出。

串操作類指令

重點:MOVS STOS LODS CMPS SCAS REP

串尋址方式

  • 源操作數:SI尋址,默認DS段,允許段超越

  • 目的操作數:DI尋址,默認ES段,不允許段超越

SI DI自動修改(增減1或2)

CLDDF=0,地址指針增1或2

STDDF=1,地址指針減1或2

串傳送 MOVSB MOVSW

ES:[DI]DS:[SI]

SI DI加減1或2

串存儲 STOSB STOSW

ES:[DI]AL/AX

DI加減1或2

串讀取 LODSB LODSW

AL/AXDS:[SI]

SI加減1或2

串比較 CMPSB CMPSW

DS:[SI]-ES:[DI]

SI DI加減1或2

串掃描 SCASB SCASW

AL/AX-ES:[DI]

DI加減1或2

重複前綴指令 REP REPZ REPNZ

配合不影響標誌的MOVS STOS LODSREP前綴

rep movsb相當於:

1
2
3
4

again: movsb
dec cx
jnz again

rep stosw相當於:

1
2
3
4

again: stosw
dec cx
jnz again

配合影響標誌的CMPS SCASREPZ REPNZ前綴

REPZ/REPE相當於:CX≠0且ZF=1則繼續比較。

REPNZ/REPNE相當於:CX≠0且ZF=0則繼續比較。

處理機控制類指令

空操作指令 NOP

不執行任何操作,佔用一個字節存儲單元,空耗一個指令執行週期。
常用於程序調試。

段超越前綴指令 CS: SS: DS: ES:

封鎖前綴指令 LOCK

暫停指令 HLT

交權指令 ESC

1
2

esc i6, reg/mem

8086浮點指令交給8087執行。

等待指令 WAIT

實現8086與8087同步運行。