彙編與技術接口——指令系統漫談

文章根據北京理工大學李元章等老師所著《彙編語言與技術接口》所寫,文章僅作爲學習筆記使用,不得進行任何商業用途。轉載請說明出處!!

  這篇文章講解了彙編中常見的寄存器、CPU工作模式、內存管理。建議讀本片文章之前,先花一點時間去閱讀 “微處理器管理模式(上)”這篇文章,不然本篇文章出現得一些寄存器可能看不懂。下面是鏈接~
微處理器管理模式(上)

1.數據尋址方式

MOV 目標,源    ;把源操作數傳給目標

 1.1 CPU操作數尋址

參與運算的操作數來自CPU內部,包括以下兩種尋址方式:
(1)立即尋址方式
操作數直接包含在指令中,緊跟在操作碼之後的尋址方式稱爲立即尋址方式,把該操作數稱爲立即數,也成爲立即數尋址方式。

MOV BL,9    ;執行結果(BL)= 9

9是立即數,它的尋址方式是立即尋址方式。這種尋址方式只能出現在源操作數的位置。除立即尋址外,以下介紹的尋址方式既可以出現在源操作數也可以出現在目標操作數位置

(2)寄存器尋址方式
操作數直接包含在寄存器中,由指令指定寄存器的尋址方式
寄存器可以是通用寄存器,包括8位、16位、32位通用寄存器;也可以是段寄存器,但是目標寄存器不能是CS

MOV BX,AX
MOV ECX,9AH

其中,ECX、BX、AX均爲寄存器尋址方式,9AH爲立即尋址方式。

  這兩種方式在指令執行時,操作數都存儲於CPU中。除以上兩種尋址方式外,下一節將介紹的尋址方式的操作數都存儲於存儲器中。

 1.2 存儲器操作數尋址

(1)直接尋址方式

MOV EAX,[00404011H]

  [00404011H]是直接尋址方式的一種形式,這裏的00404011H用[ ]括起來,它表示一個普通變量的有效地址,而不是操作數本身。

MOV EAX,VAR

   由於彙編中用符號表示地址,所以指令中的源操作數VAR的尋址方式是直接尋址方式。若VAR對應的偏移量是00404011H。執行指令“MOV EAX,VAR”時,CPU從指令中知道VAR的地址爲00404011H,再從00404011H中取出一個雙字,送到EAX。這裏VAR是一個內存操作數,它的地址是直接從指令碼中取出的,而不必經過極端或其他操作。

段超越前綴格式爲:MOV EBX,ES:MEM
   指令明確表示使用ES所指向的附加數據段中的變量,而不是默認的DS所指向的數據段。

(2)寄存器間接尋址方式
若指令中使用的是BX、SI、EAX、ECX等,則默認操作數在DS段;若使用的是BP、EBP、ESP,則默認操作數在SS段。
   操作數的有效地址在寄存器而操作數本身在存儲器中的尋址方式稱爲寄存器間接尋址

MOV AL,[BX]

地址計算公式:物理地址=段基址*10H+有效地址

[BX]的尋址方式爲寄存器間接尋址方式,注意,BX用[ ]括起來,他表示BX寄存器中是有效地址而不是操作數,這也是寄存器間接尋址與寄存器尋址方式在彙編格式的區別

(3)寄存器相對尋址
有效地址EA =(基址<或變址>寄存器)+disp

MOV AL,8[BX]    ;也可以表示爲:MOV AL,[BX+8]8是位移量

實模式下,若(DS)=3000H,(BX)=70H ,(30078H)=12H,則物理地址=10H*(DS)+(BX)+8=30078H,該指令的執行結果是(AL)=12H

(4)基址變址尋址方式
有效地址EA=(基址寄存器)+(編址寄存器)

MOV AL,[BX][SI]   /  MOV AL,[BX+SI]
MOV EAX,[EBX][ESI]

(5)相對基址變址尋址方式
有效地址EA=(基址寄存器)+(編址寄存器)+disp

MOV AL,ARY[BX][SI]  / MOV AL,ARY[BX+SI]
MOV EAX,ARY[EBX][ESI]

(6)比例變址尋址方式
這種尋址方式是80386以上的微處理器才提供的

有效地址EA=(基址寄存器)+(編址寄存器)*比例因子+disp

MOV EAX,ARY[EBX][ESI]    ;(DS:[ARY+EBX+ESI]->EAX)
MOV EBX,[EBP+ECX*4+10H]   ;(SS:[EBP+ECX*4+10H]->EBX)

2.數據運算指令

 2.1數傳送指令

  2.1.1 通用數據傳送指令

(1)傳送指令 MOV
格式:MOV DST,SRC
功能:SRC(源)→DST(目標)
說明:MOV指令可以實現一個字節、一個字 、一個雙字的數據傳送,
注意:源操作數和目標操作數的數據類型匹配問題,即應同爲字節、字或雙字型數據,可用PTR進行強制轉換。
數據傳送規則
– 立即數不能作爲目標操作數;
– 立即數不能直接送段寄存器;
– 目標寄存器不能是CS;
– 兩個段寄存器間不能直接傳送;
– 兩個存儲單元之間不能直接傳送。

 MOV    AL,5 
 MOV    DS,AX 
 MOV    [BX],AX 
 MOV    ES:VAR,12 
 MOV    WORD PTR [BX],10 
 MOV    EAX,EBX 

  “WORD PTR” 它明確指出BX所指向的內存 單元爲字型,立即數10被彙編爲16位的二進制數。若要生成8位的二進制數,需要用 “BYTE PTR”,這裏的類型顯式說明是必須的。

這裏簡要概述以下彙編中的PTR的常見用處,下面的文章將不在做說明:

ptr ->pointer (即指針)的縮寫。彙編裏面 ptr 是規定的字(即保留字),是用來臨時指定類型的。
(可以理解爲,ptr是臨時的類型轉換,相當於C語言中的強制類型轉換)

    mov ax,bx  ;是把bx寄存器裏的值賦予ax,由於二者都是word型,所以沒有必要加“WORD”。   
    mov ax,word ptr [bx]  ;是把內存地址等於“bx寄存器的值”的地方所存放的數據,賦予ax。
    由於只是給出一個內存地址,不知道希望賦予ax的是byte還是word,所以需要用word明確指出!
    
    所以,當兩個操作數的寬度不一樣時,就要用到ptr。
    也就是說,*p 用匯編表示就是:dword ptr [p],*p是取p所指內存地址處的值。

    總結,即有寄存器時一般不用ptr;沒有時一定要用(防止兩個操作數的寬度不一樣)。
    不管用在什麼位置,ptr的作用就是臨時指定類型。可以放在ptr前面的類型有:
    byte(字節)、word(字)、dword(雙字)、qword(四字)、tbyte(十字節)、far(遠類型)和near(近類型)

(2)帶符號擴展的數據傳送指令 MOVSX( 386以上)
格式:MOVSX DST,SRC
功能:SRC—>DST,DST空出位用SRC的符號位填充
說明:DST必須是16位或32位寄存器操作數,SRC可以是8位或16位寄存器或存儲器操作數,但不能是立即數。

(3)帶零擴展的數據傳送指令 MOVZX (386以上)
格式:MOVZX DST,SRC
功能:SRC—>DST,DST空出位用0填充
說明:DST必須是16位或32位寄存器操作數,SRC可以是8位或16位寄存器或存儲器操作數,但不能是立即數。

(4)交換指令 XCHG
格式:XCHG OPR1,OPR2
功能:交換兩個操作數。
說明:OPR是操作數,操作數可以是8位、 16位、32位。兩個操作數均不能是立即數,可以是寄存器操作數和存儲器操作數,並且其中之一必須是寄存器操作數

  2.1.2堆棧操作指令

堆棧數據的存取原則是“LIFO”——後進先出
堆棧段段基址→SS
堆棧棧頂地址→SP/ESP
堆棧用途: 對現場數據的保護與恢復、子程序與中斷服務返回地址的保護與恢復等。

(1)進棧指令 PUSH
格式:PUSH SRC
功能: SP = SP - 2
   SS:SP = (SRC)
說明:SRC可以是16位或32位(386以上) 的寄存器操作數或存儲器操作數。在80286以 上的機器中,SRC還可以是立即數。若SRC是 16位操作數,則堆棧指針減2;若SRC是32位 操作數,則堆棧指針減4。

(2)出棧指令 POP
格式:POP DST
功能: (DST) = SS:SP
   SP = SP + 2
說明:DST可以是16位或32位(386以 上)的寄存器操作數和存儲器操作數,也可 以是除CS寄存器以外的任何段寄存器。若 DST是16位,則堆棧指針加2;若DST是32位 ,則堆棧指針加4。

  2.1.3 輸入輸出指令

(1)輸入指令 IN
格式: IN ACR,PORT
功能:把外設端口(PORT)的內容傳送給累加器(ACR)。
說明:可以傳送8位、16位、32位,相應的累加器選擇AL、AX、EAX。

(2)輸出指令 OUT
格式:OUT PORT,ACR
功能:把累加器的內容傳送給外設端口。
說明:對累加器和端口號的選擇限制,同IN指令。

MOV AL,0 
OUT  61H,AL  ;61H端口← (AL) ;關掉PC揚聲器

MOV  DX,3F8H 
OUT  DX,AL  ;3F8H端口 ← (AL) ;向COM1端口輸出一個字符
  2.1.4 地址傳送指令

這類指令傳送的是操作數的地址,而不是操作數本身。

(1)傳送有效地址指令 LEA
格式:LEA REG,SRC
功能:把源操作數的有效地址送給指定的寄存器。
說明:源操作數必須是存儲器操作數

LEA BX,ASC[SI]       ;把DS:[ASC+SI]單元的16位偏移量送給BX

(2)MOV 指令傳送地址
  MOV 指令除了可以實現數據傳送外, 還可實現地址傳送,方法是藉助於SEG 和OFFSET操作符。
設TAB爲一條語句的符號地址,則可以有 以下指令:

MOV AX,SEG TAB  ;把TAB的段基址送給AX寄存器 
MOV DI,OFFSET TAB ;把TAB的偏移量送給DI寄存器
  2.1.5 標誌位傳送指令

(1)16位標誌進棧指令 PUSHF
格式:PUSHF
功能: 先使堆棧指針寄存器SP-2,然後壓入標誌寄存器FLAGS的內容到棧頂單元。
SP-2; FLAGS→棧頂單元。

(2)16位標誌出棧指令 POPF
格式:POPF
功能:先將堆棧指針所指向的字彈出到FLAGS寄存器,然後使堆棧指針寄存器SP+2

(3)32位標誌進棧指令 PUSHFD
格式:PUSHFD
功能:ESP減4;EFLAGS→棧頂。

(4)32位標誌出棧指令 POPFD
格式:POPFD

 2.2 算術運算指令

  2.2.1 類型轉換指令

  這類指令實際上是把操作數的最高位進行擴展,用於處理帶符號數運算的操作數類型匹配問題。這類指令均不影響標誌。
  所謂符號擴展,就是將數據的表示大小加倍,數值仍保持不變,即將符號位擴展到同樣大小的寄存器空間中去,由兩部分構成一個比原值表示大一倍的數。

(1)字節擴展成字指令 CBW
格式:CBW
功能:把AL寄存器中的符號位值擴展到AH中
說明:在8086中CBW指令將AL的最高有效位D7擴展至AH,即:如果AL的最高有效位是0,則AH = 00;AL的最高有效位爲1,則AH = FFH。AL不變

例1:AL=88H,執行CBW,AH=FFH
1000 1000
1111 1111 1000 1000

例2:AL=44H,執行CBW,AH=00H
0100 0100
0000 0000 0100 0100

(2)字擴展成雙字指令 CWD
格式: CWD
功能:把AX的符號位值擴展到DX中
說明:規則:若AX最高位=1,則執行後DX=FFFFH;若AX最高位=0,則執行後DX=0000H。AX值不變。

(3).雙字擴展成四字指令 CDQ
格式:CDQ (386以上)
功能: EAX符號位擴展到EDX中

(4).AX符號位擴展到EAX指令 CWDE
格式: CWDE (386以上)
功能: AX寄存器符號位擴展到EAX高16位

  2.2.2 二進制加法指令

任何一條二進制加、減法指令均適用 於帶符號數和無符號數運算。

(1)加法指令 ADD
  格式: ADD DST,SRC
  功能:(DST)+(SRC)→ DST
  說明:對操作數的限定同MOV指令。
  標誌:影響OF、SF、ZF、AF、PF、CF標誌

(2)帶進位加法指令 ADC
  格式: ADC DST,SRC
  功能:(DST)+(SRC)+ CF → DST
  說明: 對操作數的限定同MOV指令,該指令 、適用於多字節或多字的加法運算。
  標誌: 影響OF、SF、ZF、AF、PF、CF標誌

 ADC  AX,35 ;(AX)= (AX)35+CF

(3)加1指令 INC
  格式:INC DST
  功能:(DST)+1→DST
  標誌:除不影響CF標誌外,影響其它五個算術運算特徵標誌。
  說明:INC指令的操作數的類型可以是通用寄存器存儲單元,但不可以是段寄存器。字或字節操作均可。對於存儲單元,需要用BYTE PTR或者WORD PTR說明是字節還是字操作。

.data
szMsg      sbyte         'M1=%d',0ah,0      ;0dh回車,0ah 換行
M1			DW				20

.code
main   proc
	   inc		  	WORD PTR		M1
       invoke             printf,offset szMsg,M1	
       ;下面三行和上邊的打印效果相同
       mov ax,M1
	   inc ax
       invoke             printf,offset szMsg,ax
       
	   ret

(4)互換並加法指令 XADD(486以上)
  格式:XADD DST,SRC
  功能: (DST)+(SRC)→TEMP
  (DST)→SRC TEMP→DST
  說明:TEMP是臨時變量。該指令執行後,原 DST的內容在SRC中,和在DST中。
  標誌:影響OF、SF、ZF、AF、PF、CF。

  2.2.3 二進制減法指令

(1)減法指令 SUB
  格式: SUB DST,SRC
  功能:(DST)-(SRC)→ DST
  標誌: 影響OF、SF、ZF、AF、PF、CF標誌。
實例:SUB AX,35
   SUB WORD PTR[BX],56

  減法指令執行後若使CF=1,則對無符號數而言發生了溢出。若使OF=1,則對帶符號數而言發生了溢出。

(2)帶借位減法指令 SBB
  格式: SBB DST,SRC
  功能: (DST)-(SRC)-CF → DST
  說明: 除了操作爲減外,其它要求同ADC, 該指令適用於多字節或多字的減法運算。 標誌:影響OF、SF、ZF、AF、PF、CF

SBB  AX,35 ;(AX)= (AX)35-CF

(3)減1指令 DEC
  格式: DEC DST
  功能:(DST)-1→DST
  說明:使用本指令可以很方便地實現地址指針或循環次數的減1修改。
標誌:除不影響CF標誌外,影響其它 五個算術運算特徵標誌。

(4)比較指令 CMP
  格式:CMP DST,SRC
  功能:(DST)-(SRC),影響標誌位。
  說明:這條指令執行相減操作後只根據結果設置標誌位,並不改變兩個操作數的原值,其它要求同SUB。CMP指令常用於比較兩個數的大小。
標誌:影響OF、SF、ZF、AF、PF、CF標誌

(5)求補指令 NEG
  格式: NEG DST
  功能:對目標操作數(含符號位)求反加1,並且把結果送回目標。即:實現0-(DST)→DST
  說明:利用NEG指令可實現求一個數的相反數。 標誌:影響OF、SF、ZF、AF、PF、CF標誌。其中對CF和OF的影響如下:

  • 對操作數所能表示的最小負數(例若操作數是8 位則爲-128)求補,原操作數不變,但OF被置1
  • 當操作數爲0時,清0 CF。
  • 對非0操作數求補後,置1 CF。
  2.2.3 二進制乘法指令

(1)無符號乘法指令 MUL
  格式:MUL SRC
  功能:實現兩個無符號二進制數乘。
  說明:該指令只含一個源操作數(不能是立即數), 另一個乘數必須事前放在累加器中。可以實現8位、16 位、32位無符號數乘。例如:若操作數是16位的,則與AX中的內容相乘,乘積放在DX:AX這一對寄存器中。具體操作爲:

  • 字節型乘法:(AL)×(SRC)8→AX
  • 字型乘法: (AX)×(SRC)16→DX:AX
  • 雙字型乘法:(EAX)×(SRC)32→EDX:EAX

  標誌:影響CF、OF、SF、ZF、AF、PF,而只有 CF、OF有意義,其它標誌不確定。
  對CF和OF的影響是:若乘積的高半部分(例:字節型乘法結果的AH)爲0,則對CF和OF清0,否則置 CF和OF爲1。

(2)帶符號乘法指令 IMUL
  功能:實現兩個帶符號二進制數乘。
  格式1IMUL SRC
  說明:這種格式的指令除了是實現兩個帶符號 數相乘且結果爲帶符號數外,其它與MUL指令相同。 所有的80X86 CPU都支持這種格式。
  標誌:影響CF、OF、SF、ZF、AF、PF,而只有CF、OF 有意義,其它標誌不確定。
  對CF和OF的影響是:若乘 積的高半部分爲低半部分的符號擴展,則對CF和OF 清0,否則置CF和OF爲1。

格式2IMUL REG,SRC (286以上)
說明:REG和SRC的長度必須相同,目標操作數 REG必須是16位或32位通用寄存器,源操作數 SRC可以是寄存器或存儲器操作數。
具體操作爲: (REG)16×(SRC)16→REG16

格式3IMUL REG,imm8 (286以上)
格式4IMUL REG,SRCreg/m ,imm8 (286以上)

  2.2.3 二進制除法指令

(1)無符號除法指令 DIV
  格式:DIV SRC
  功能:實現兩個無符號二進制數除法。
  說明:該指令只含一個源操作數,該操作數 作爲除數使用,注意它不能是立即數。被除數必須事前放在隱含的寄存器中。可以實現8位、16位、 32位無符號數除。
在這裏插入圖片描述
(2)帶符號除法指令 IDIV
  格式:IDIV SRC
  功能:實現兩個帶符號二進制數除。
  說明:除了是實現兩個帶符號數相除且商和餘數 均爲帶符號數、餘數符號與被除數相同外,其它與 DIV指令相同。 具體操作同無符號數除法。

 2.3 位運算指令

  2.3.1 邏輯運算指令

  邏輯運算指令見下表。這些指令的操作數可 以是8位、16位、32位,其尋址方式與MOV指令的限制相同。

在這裏插入圖片描述

AND EAX,0     ;將EAX寄存器清0
XOR AL,20H    ;轉換AL中字母的大小寫
  2.3.2 位測試指令

  從386開始增加了位測試指令,它們包括BT 、BTS、BTR和BTC。這些指令首先把指定位的值送給CF標誌,然後對該位按照指令的要求操作。
格式:

BT DEST,SRC
BTC DEST,SRC
BTR DEST,SRC
BTS DEST,SRC

功能:按照源操作指定的位號,測試目的操作數,當指令執行時,被測試位的狀態被複制到進位標誌CF。
BT將SRC指定的DEST中一位的數值複製到CF。
BTC將SRC指定的DEST中一位的數值複製到CF,且將DEST中該位取反。
BTR將SRC指定的DEST中一位的數值複製到CF,且將DEST中該位清0。
BTS將SRC指定的DEST中一位的數值複製到CF,且將DEST中該位置1。

  目標可以是16位或32位的寄存器或存儲器操作數,源可以是8位的立即數、寄存器存儲器或存儲器操作數,若是後兩種情況,其長度一定要和目標長度相同。若源操作數是立即數,則其值不應超過目標操作數長度。

  2.3.3 位掃描指令

(1)順向掃描指令 BSF
格式:BSF DST,RSC
功能:從右向左掃描RSC操作數中第一個含1的位,並把掃描到的第一個含1的位號送DST操作數。 若RSC=0,則DST值不確定。

(2)逆向掃描指令 BSR
格式:BSR DST,RSC

  2.3.4 基本移位指令

  這類指令實現對操作數移位,包括 SHL、SAL、SHR和SAR指令。
在這裏插入圖片描述
PS:例如SHR(右移):指令使目的操作數邏輯右移一位,最高位用 0 填充。最低位複製到進位標誌位,而進位標誌位中原來的數值被丟棄

  • 第一種是邏輯移位 (logic shift),空出來的位用 0 填充
  • 另一種移位的方法是算術移位 (arithmetic shift),空出來的位用原數據的符號位填充

  可以用邏輯移位指令實現無符號數乘除法運算,(只要移出位不含1):
SHL DST,n執行後是原數的2^n倍
SHR DST,n執行後是原數的1/2^n
  可以用算術移位指令實現帶符號數乘除法運算,只要移位操作不改變符號位: SAL DST,n執行後是原數的2^n倍
SAR DST,n執行後是原數的1/2^n (只要移出位不含1)

  2.3.5 循環移位指令

這類指令實現循環移位操作,包括ROL 、ROR、RCL、RCR指令。
 在這裏插入圖片描述
PS:ROL(循環左移)指令把所有位都向左移。最高位複製到進位標誌位和最低位。
   RCL(帶進位循環左移)指令把每一位都向左移,進位標誌位複製到 LSB,而 MSB 複製到進位標誌位。(通常,MSB位於二進制數的最左側,LSB位於二進制數的最右側)

3.程序控制指令

 3.1 轉移指令的尋址方式

  本節討論的尋址方式是用來確定轉移及調用指令的轉向地址。即CPU是如何找到下一條指令的。
  無條件轉移指令格式:JMP 目標

  其中的目標有各種尋址方式。這些尋址方式可以被分爲段內轉移段間轉移兩類。段內轉移隻影響指令指針IP值;段間轉移既要影響IP值,也要影響代碼段寄存器CS的值。

PS:下面可能會出現這類格式:

  • NEAR(段內近調用): 調用程序和子程序在同一代碼段中,只能被相同代碼段的其他程序調用;
  • FAR(段間遠調用): 調用程序和子程序不在同一代碼段中,可以被相同或不同代碼段的程序調用.
  3.1.1 段內直接尋址方式

  轉向的有效地址是當前指令指針寄存器的內容和指令中指定的8位、16位位移量之和,該位移量是一個相對於指令指針的帶符號數。
在這裏插入圖片描述
  EA就是要轉向的本代碼段內指令地址的偏移量。它是通過把IP的當前值加上指令中給出的位移量disp得到的,從而使IP指向下一條要執行的指令,實現段內轉移。

  • 若位移量是8位的,則稱爲短轉移,可以實現在距離下條指令的+127~-128字節範圍之內轉移。其彙編指令格式:JMP SHORT LAB 。在於當前16位的IP值相加時,系統自動把8位位移量擴展成16位,擴展方法是高8位全部用位移量的符號位填充;在於當前32位的IP值相加時,則高24位全部用位移量的符號位填充。
  • 若位移量是16位或32位的,則稱爲近轉移。其彙編指令格式:JMP LAB
    JMP NEAR PTR LAB
  3.1.2 段內間接尋址方式

  轉向的有效地址在一個寄存器或內存單元中,該寄存器號或內存地址按上節介紹的與操作數有關的尋址方式(立即尋址方式除外)獲得。所得到的有效地址送給IP,於是實現轉移。指令格式及舉例見下表。
在這裏插入圖片描述
PS

JMP  WORD  PTR  [BX]  
說明:式中WORD  PTR  [BX]表示BX指向一個字型內存單元。
	1.這條指令執行時,先按照操作數尋址方式得到存放轉移地址的內存單元:
	10H ×(DS)+(BX)= 20300H
	2.再從該單元中得到轉移地址:
	EA=(20300H)= 0500H
	3.於是,(IP)=EA=0500H,下一次便執行CS:500H處的指令,實現了段內間接轉移。 
  3.1.3 段間直接尋址方式

  指令中直接給出轉向的4字節的偏移量和段基址,只需把它們分別送給IP和CS後即可實現段間轉移。指令格式:

JMP  FAR  PTR  LAB 

圖(a)適用於16位操作數長度,執行時把偏移量送給IP,段基址送給CS。
圖(b)適用於32位操作數長度,執行時把偏移量送給EIP,段選擇符送給CS。
在這裏插入圖片描述

  3.1.4 段間間接尋址方式

  用一個雙字內存變量中的低16位取代IP值,高16位取代CS值,從而實現段間轉移。該雙字變量的地址可以由除立即尋址和寄存器尋址方式以外的其它與數據有關的尋址方式獲得。

JMP  DWORD  PTR  [BX]  
設:(DS)= 2000H,(BX)= 0300H
    (IP)= 0100H,(20300H)= 0
    (20301H)= 05H
    (20302H)= 10H
    (20303H)= 60H
	說明:式中DWORD  PTR  [BX]表示BX指向一個雙字變量。
	這條指令執行時,先按照與操作數有關的尋址方式得到存放轉移地址的內存單元:
10H×(DS)+(BX)= 20300H
再把該單元中的低字送給IP,高字送給CS,即0500H →IP,6010H→CS,
下一次便執行6010:0500H處的指令,實現了段間間接轉移。

 3.2 轉移指令

  這類指令包括無條件轉移指令條件轉移指令

(1)無條件轉移指令
格式:JMP DST
功能:無條件轉移到DST所指向的地址

(2)條件轉移指令
  執行這類指令時通過檢測由前邊指令已設置的標誌位確定是否轉移,所以它們通常是跟在影響標誌的指令之後。這類指令本身並不影響標誌。

格式:JCC LABEL
功能:如果條件爲真,則轉向標號處,否則順序執行下一條指令。
說明:其中cc爲條件,LABEL是要轉向的標號。在8086-80286中,該地址應在與當前IP值的-128~+127範圍之內,即只能使用與轉移地址有關的尋址方式的段內短轉移格式,其位移量佔用一個字節。

  • 檢測單個標誌位實現轉移的條件轉移指令,這組指令根據一個標誌位的設置情 況決定是否轉移。
    在這裏插入圖片描述
  • 根據兩個帶符號數比較結果實現轉移的條件轉移指令,利用上表中提供的指令,可以實現兩個帶符號數的比較轉移。
    在這裏插入圖片描述
  • 根據兩個無符號數比較結果實現轉移的條件轉移指令

在這裏插入圖片描述

  • 測試CX/ECX值爲0轉移指令。這類指令不同於以上介紹的條件轉移指令,因爲它們測試的是CX或ECX寄存器的內容是否爲0,而不是測試標誌位。這類指令只能使用與轉移地址有關的尋址方式的段內短轉移格式,即位移量只能是8位的。

格式JCXZ LABEL   ;適用於16位操作數
      JECXZ LABEL  ;適用於32位操作數
功能:測試CX(或ECX)寄存器的內容,當CX(或ECX)= 0時則轉移,否則順序執行。
說明:此指令經常用於在循環程序中判斷循環計數的情況。

 3.3 循環指令

循環指令可以控制程序的循環。它們的特點是:

  • 用CX或ECX(操作數長度爲32位時)作爲循環次數計數器。
  • 不影響標誌。

(1)循環指令 LOOP
 格式:LOOP LABEL
 功能:(CX)-1→CX,若(CX)≠0,則轉向標號處執行循環體,否則順序執行下一條指令。
 說明:若操作數長度爲32位,則其中的CX應爲ECX。在LOOP指令前,應先把循環計數的初始值送給CX(或ECX)。
(2)相等循環指令 LOOPE/LOOPZ
(3)不等循環指令 LOOPNE/LOOPNZ

 3.4子程序調用與返回指令

  3.4.1子程序調用指令CALL

格式:CALL DST
功能:調用子程序。執行時先把返回地址壓入堆棧,再形成子程序入口地址,最後把控制權交給子程序。
說明:其中DST爲子程序名或子程序入口地址,其目標地址的形成與JMP指令有異同。

  • 與JMP指令相同點:
    段內直接/間接調用、段間直接/間接調用。只是不能使用段內直接尋址方式的SHORT格式。指令的執行結果是無條件轉到標號處。
  • 與JMP指令不同點:
    CALL轉移後要返回,所以要保存返回地址; JMP轉移後不再返回,所以不必保存返回地址。

(1)段內調用
  這類調用指令實現同一段內的子程序調用,它只改變IP值,不改變CS值
  執行操作

  • 把返回地址(CALL之後的那條指令地址的偏移量部分(當前IP值))壓入堆棧。
  • 根據與轉移地址有關的尋址方式形成子程序入口地址的IP值。
  • 把控制無條件轉向子程序,即執行CS:IP處的指令。

段內直接調用
  格式:CALL A
  或: CALL NEAR PTR A
  功能:調用A子程序。執行時先把返回地址壓入堆棧,再使IP=(IP)+disp16,最後把控制權交給子程序。

段內間接調用
  格式:CALL REG/M
  功能:調用子程序。執行時先把返回地址壓入堆棧,再把指令指定的16位通用寄存器或內存單元的內容送給IP,最後把控制權交給子程序。

(2)段間調用
  這類調用指令可以實現段間調用(FAR型調用),執行時即要改變IP值,也要改變CS值。

段間直接調用
  格式:CALL FAR PTR PROCEDURE
  功能:調用PROCEDURE子程序。執行時先把返回地址(當前IP值和當前CS值)壓入堆棧,再把指令中的偏移量部分送給IP,段基址部分送給CS,最後把控制權交給子程序。

段間間接調用
  格式:CALL M
  功能:調用子程序。執行時先把返回地址(當前IP值和當前CS值)壓入堆棧,再把M的低字送給IP,高字送給CS,最後把控制權交給子程序。

  3.4.2子程序返回指令

  執行這組指令可以返回到被調用處。有兩條返回指令,它們都不影響標誌。以下介紹8086/8088的子程序調用指令。

返回指令 RET
  格式:RET
  功能:按照CALL指令入棧的逆序,從棧頂彈出返回地址(彈出一個字到IP,若子程序是FAR型還需再彈出一個字到CS),然後返回到主程序繼續執行。
無論子程序是NEAR型還是FAR型,返回指令的彙編格式總是用RET表示。但經彙編後會產生不同的機器碼。在DEBUG中,段間返回指令被反彙編成RETF。

帶立即數的返回指令
  格式:RET imm16
  功能:按照CALL指令入棧的逆序,從棧頂彈出返回地址(彈出一個字到IP,若子程序是FAR型還需再彈出一個字到CS),返回到主程序,並修改棧頂指針SP=(SP)+imm16。
  :其中imm16是16位的立即數,設通過堆棧給子程序傳遞了n個字型參數,則imm16=2n。

修改堆棧指針是爲了廢除堆棧中主程序傳遞給子程序的參數。

 3.5中斷調用與返回指令

  中斷就是使計算機暫時掛起正在執行的進程而轉去處理某種事件,處理完後再恢復執行原進程的過程。
  對某事件的處理實際上就是去執行一段例行程序,該程序被稱爲中斷處理例行程序或中斷處理子程序,簡稱爲中斷子程序。

  1. 中斷向量
      中斷向量就是中斷處理子程序的入口地址。在PC機中規定中斷處理子程序爲FAR型,所以每個中斷向量佔用4個字節,其中低兩個字節爲中斷向量的偏移量部分,高兩個字節爲中斷向量的段基址部分。
  2. 中斷類型號
      IBM PC機共支持256種中斷,相應編號爲0~255,把這些編號稱爲中斷類型號。
  3. 中斷向量表
      256種中斷有256箇中斷向量。把這些中斷向量按照中斷類型號由小到大的順序排列,形成中斷向量表。
      表長爲4×256= 1024字節,該表從內存的0000:0000地址開始存放,從內存最低端開始存放。

中斷調用指令 INT
  在8086/8088中,中斷分爲內中斷(或稱軟中斷)和外中斷(或稱硬中斷),本節只介紹內中斷的中斷調用指令。
  格式:INT n ;n爲中斷類型號
  功能:中斷當前正在執行的程序,把當前的FLAGS、CS、IP值依次壓入堆棧(保護斷點),並從中斷向量表的4n處取出n類中斷向量。其中(4n)→IP,(4n+2)→CS,轉去執行中斷處理子程序。

中斷返回指令 IRET
  格式:IRET
  功能:從棧頂彈出三個字分別送入IP、CS、FLAGS寄存器,把控制返回到原斷點繼續執行。

4.處理機控制指令

  這組指令可以控制處理機狀態以及對某些標誌位進行操作。

 4.1 標誌操作指令

  這組指令可以直接對CF、DF和IF標誌位進行操作,它們隻影響本指令所涉及的標誌。
在這裏插入圖片描述

 4.2 常用處理機控制指令

  這組指令可以控制處理機狀態,它們均不影響標誌,見下表。
在這裏插入圖片描述

5.塊操作指令

  利用塊操作指令可以直接處理兩個存儲器操作數,方便地處理字符串或數據塊(批量處理)。
常用的塊操作指令
在這裏插入圖片描述
:塊操作指令中,指令後面的B、W、D代表操作數的大小,分別代表字節、字、雙字的內存操作數。

源操作數與目標操作數
在這裏插入圖片描述

 5.1 塊指令的特點

指令格式
  塊指令可以顯式地帶有操作數,也可以使用隱含格式。例如塊傳送指令MOVS,可以有以下幾種格式:
  顯式:MOVS DST, SRC
  隱式:MOVSB   ;字節傳送
     MOVSW   ;字傳送
     MOVSD   ;雙字傳送
經常使用隱含格式。操作數時應先建立地址指針。

操作數
  塊指令可以處理寄存器操作數存儲器操作數
  若爲寄存器操作數只能放在累加器中;
  對於存儲器操作數應先建立地址指針:若爲源操作數,則必須把源串首地址放入SI寄存器,缺省情況尋址DS所指向的段,允許使用段超越前綴;若爲目標操作數,則必須把目標串首地址放入ES:DI寄存器,不允許使用段超越前綴。

地址指針的修改
  塊指令執行後系統自動修改地址指針SI(ESI)、DI(EDI)。若爲字節型操作其修改量爲1,若爲字型操作其修改量爲2,若爲雙字型操作其修改量爲4。

方向標誌
  方向標誌DF決定地址指針的增減方向。
  DF=0,則地址指針增量;
  DF=1,則地址指針減量。
  可以用CLD和STD指令復位和置位DF。

重複前綴
  塊指令前可以加重複前綴REPE/REPZ、 REP或REPNE/REPNZ,使後跟的串指令重複執行。重複次數應事先初始化在計數器CX中。

(1)重複前綴 REP
  若(CX)=0,則結束重複,順序執行下一條指令。
  若(CX)≠0,則執行後跟的串操作指令,然後修改計數器(CX)-1→CX,繼續重複上述操作。
  若地址長度爲32位的,則使用ECX。

(2)相等重複前綴 REPE/REPZ
  REPE/REPZ可以用在比較類塊操作指令之前,當比較相等且重複次數未到時重複執行後跟的串指令。其執行的操作爲:
  若(CX)=0(計數到)或ZF=0(不相等),則結束重複,順序執行下一條指令。否則執行後跟的塊操作指令,修改計數器(CX)-1→CX。繼續重複上述操作。
  若地址長度爲32位的,則使用ECX。

(3)不等重複前綴 REPNE/REPNZ

 5.2 塊指令

  1. 塊傳送指令 MOVS

  顯式格式:MOVS DSTm,SRCm
  隱含格式:MOVSB MOVSW MOVSD
  功能:源→目標,即([SI])→ES:[DI],且自動修改SI、DI指針。主要將DS:SI地址的數據複製到ES:DI地址中。
  標誌:不影響標誌位。

在MOVS操作結束後,(E)SI與(E)DI寄存器會自動的增加或者減少,而依據則是根據EFLAGS寄存器中的DF標誌位來判斷增加還是減少。

  • 如果DF標誌位爲0,則(E)SI與(E)DI寄存器則自增
  • 如果DF標誌位爲1,則(E)SI與(E)DI寄存器則自減
  1. 取塊指令 LODS

  顯式格式:LODS SRCm
  隱含格式:LODSB LODSW LODSD
  功能:源→累加器,即([SI]) →AL(或AX、EAX),且自動修改SI指針。
  說明:若DF=0,則LODSB(或LODSW、LODSD)使SI加1(或2、4);若DF=1,則LODSB(或LODSW、LODSD)使SI減1(或2、4)。若地址長度是32位的,則SI相應爲ESI。
  標誌:不影響標誌位。

  1. 存塊指令 STOS

  顯式格式:STOS DSTm
  隱含格式:STOSB STOSW STOSD
  功能:累加器→目標,即(AL(或AX、EAX)) →ES:[DI],且自動修改DI指針。
  說明:若DF=0,則STOSB(或STOSW、STOSD)使DI加1(或2、4);若DF=1,則STOSB(或STOSW、STOSD)使DI減1(或2、4)。若地址長度是32位的,則DI相應爲EDI。
  標誌:不影響標誌位。

  1. 塊輸入指令 INS
    顯式格式:INS DSTm,DX
    隱含格式:INSB INSW INSD

  2. 塊輸出指令 OUTS
    顯式格式:OUTS DX,SRCm

  3. 塊比較指令 CMPS
    顯式格式:CMPS DSTm,SRCm

  4. 塊掃描指令 SCAS
    顯式格式:SCAS DSTm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章