一、尋址方式
1、概念:
一條指令由操作碼和操作數構成,操作碼是系統定義好的符號,執行指定的操作,操作數即是指令的對象,而尋址方式就是操作數的指定方式
操作碼 目的操作數,源操作數
2、尋址方式的三種情況:
(1)CPU中(2)儲存器(3)I/O中
3、尋址方式分類
(1)隱含尋址:
指令中只有操作碼沒有指定的操作數,但是根據操作碼就可確定相應的操作數
MUL BL;
DIV BL;
(2)立即尋址:
指令中直接給出要操作的數
ADD AL,50
立即尋址只能用在源操作數上
(3)寄存器尋址:
A、指令中給出寄存器的名字,寄存器中的內容是要操作的數,這種方式稱為寄存器尋址。
B、可以使用寄存器:8個通用16位寄存器(AX,BX,CX,DX,SI,DI,BP,SP),以及8個8位寄存器(AH,AL,BH,BL,CH,CL,DH,DL)
ADD AL,BL
(4)段寄存器尋址:
A、指令中給出段寄存器的名字,段寄存器中的內容是要操作的數,這種方式稱為段寄存器尋址。
B、可以使用段寄存器:4個段寄存器(CS,DS,ES,SS)
C、8086中只有數據傳輸指令MOV,堆棧操作指令PUSH和POP可以使用段寄存器尋址方式
(5)I/0口尋址
A、操作數在I/O接口中,這種尋址方式為I/O尋址
B、只用使用IN/OUT操作。
C、直接IO尋址:使用一個8位無符號數指定端口號
間接IO尋址:使用一個16位寄存器DX來指定端口號
(6)轉移地址的尋址:
指令指針IP會一直指向下一條要執行的命令,所以使用指令轉移IP內容,成為轉移地址的尋址
(7)儲存器操作數的尋址
①概念:
8086CPU有20根地址線,所以儲存器每個單元的地址是20位(2進制),稱為物理地址,而CPU內部的寄存器都是16位,只用一個寄存器不能完整表示儲存器地址,所以拆成2個分量:段地址(CS,DS,ES,SS),偏移地址(BX,BP,SI,DI)
物理地址 = 段地址*10H + 偏移地址
②直接尋址
ADD AL,[Xvar]
將Xvar地址中的內容與AL相加,並儲存在AL中;其中Xvar是在數據段中定義的一個變量名
A、直接尋址:要用變量名指定地址
立即尋址:常數作為源操作數
ADD AL,[20H]
認為是立即尋址
③寄存器間接尋址
A、將儲存器的偏移地址存在一個16位寄存器中,然后用方括號中的16位寄存器指定此偏移地址,成為寄存器間接尋址
B、BX,SI,DI搭配DS(數據段)
BP搭配SS(堆棧段)
ADD AL,[BX]; 從數據段的此地址取數據
ADD AL,[BP]; 從堆棧段的此地址取數據
④寄存器相對尋址
A、就是在寄存器間接尋址的基礎上,使用BX+D(8位或者16位的常數偏移量)作為地址
ADD AL [SI+5]; ADD AL [BP-5];
⑤基址變址尋址
A、將一個基址寄存器(BX,BP)與一個變址寄存器(SI,DI)的內容相加作為偏移地址,段寄存器搭配由基址寄存器決定:BX搭配DS,BP搭配SS
B、計算公式:
物理地址=DS*10H+BX/DP+SI/DI
C、指令
ADD AL,[BX+SI]; 只能相加 ADD AL,[BP-DI]; 不能相減 ADD AL [BX+BP]; 也不能是兩個基址寄存器 ADD AL,[SI+DI]; 或者是兩個變址尋址器
⑥相對基址變址尋址
A、就是在寄存器基址變址尋址的基礎上,使用BX+SI+D(8位或者16位的常數偏移量)作為地址
ADD AL,[BP+BI+5] ADD AL,[BP+BI-5]; 同樣的,不能有減法
二、數據傳送指令
1、通用數據傳送指令
MOV dst,src;
(1)立即數傳送給寄存器或儲存單元
A、立即數只能作為源操作數
B、若寄存器是16位,立即數可以是16位或8位,若寄存器是8位的,立即數只能是8位的。
C、目的操作數是存儲器,而立即數是8位,則存儲器必須有類型說明
(2)通用寄存器與存儲器之間的傳送
若通用寄存器是8位,則按字節傳送,若是16位,則按字傳送。
(3)兩個通用寄存器之間的傳送
源和目的必須同為8位或者16位寄存器
(4)段寄存器與通用寄存器或存儲器之間的傳送
A、程序的一開始,經常需要用立即數對段寄存器賦初值,但是,立即數為源操作數,段寄存器為目的的操作數尋址方式是非法的,所以使用:
MOV AX,DATA
MOV DS,AX
B、段寄存器作為源操作數時:DS,SS,ES,CS都可以使用
作為目的操作數:CS不能使用
C、IP不能作為源操作數或者目的操作數
D、兩個存儲單元之間的傳送是允許的,所以
MOV AX,X1
MOV X2,AX
2、交換指令:
(1)指令格式
XCHG dst,src;
(2)操作數不能是立即數、段寄存器、存儲器操作數。
(3)操作數的長度要一致
3、堆棧操作指令
(1)入棧指令:
A、指令格式:
PUSH src
將一個源操作數壓入堆棧,具體過程:先將堆棧指針SP減2,然后將源操作數存入堆棧中SP所指的地址.
(2)出棧指令:
POP src
(3)一些注意事項:
A、POP和PUSH的操作數必須是16位的。通用寄存器和存儲器皆可。
B、一些錯誤指令:
PUSH 1234 不能是立即數 PUSH AL 不能使用8位寄存器 PUSH IP 不能使用IP寄存器 POP 1234H 不能使用立即數 POP AL 不能使用8位寄存器 POP CS CS不能作為目的操作數
4、查表指令
(1)指令格式:
XLAT
XLAT src_table
(2)demo
MOV BX OFFSET TABLE MOV AL,5 XLAT
5、輸入/輸出指令
(1)指令格式
(2)一些注意點:
A、操作數必須是累加寄存器AL或者AX;另一個操作數是8位無符號port或者16位的數據寄存器DX,用來指定I/O接口電路中的一個地址
B、地址超8位,只能使用間接尋址。
6、地址傳送指令
(1)有效地址傳送:
A、指令格式:
LEA reg16,mem
源操作數必須是存儲器操作數,目的操作數必須是16位的通用寄存器,功能是將存儲器操作數的偏移地址傳送給給一個16通用寄存器.
B、OFFSET:功能是取存儲器操作數的偏移地址。
(2)地址指針送寄存器和DS
LDS reg16,mem32; 等同於 reg16<---[mem32],DS<---[mem32+2]
(3)地址指針送寄存器和ES
LES reg16,mem32; 等同於 reg16<---[mem32],ES<---[mem32+2]
7、標志位傳送指令
(1)標志寄存器送AH
A、指令格式:
LAHF; 等同於AH<----標志寄存器的低八位
(2)AH送標志寄存器
A、指令格式:
SAHF; 標志寄存器低8位<------AH
PS:只能對標志寄存器的低八位進行操作
(3)標志寄存器入棧
A、指令格式:
PUSHF; SP<------SP-2 SS:[SP]<------ 標志寄存器
(4)標志寄存器出棧
A、指令格式:
POPF; 標志寄存器<-------SS:[SP], SP<----SP+2
三、匯編語言程序結構:
DATA SEGMENT ;數據段開始
…… ;偽指令,定義數據段變量
DATA ENDS ;數據段結束
EXTRA SEGMENT ;擴展段開始
…… ;偽指令,定義擴展段變量
EXTRA ENDS ;擴展段結束
STACK SEGMENT ;堆棧段開始
…… ;偽指令,定義數據段變量
STACK ENDS ;堆棧段結束
MAC1 MACRO ;宏指令定義開始
…… ;偽指令或者指令,宏定義體
ENDM ;宏指令定義結束
CODE SEGMENT ;代碼段開始
ASSUME CS:CODE,DS:DATA,ES:EXTRA,SS:STACK
START: ;主程序起始地址定義
MOV AX,DATA ;寄存器初始化
MOV DS,AX
MOV AX,EXTRA
MOV ES,AX
MOV AX,STACK
MOV SS,AX
…… ;指令
CALL SUB1 ;調用子程序
……; ;指令
MAC1 ;調用宏指令
…… ;指令
MOV AH,4CH ;返回DOS
INT 21H
SUB1 PROC ;子程序定義開始
……
RET ;返回主程序
SUB1 ENDP ;子程序定義結束
CODE ENDS ;代碼段結束
END START ;結束匯編
1、分段結構
(1)代碼段結束處,必須加入如下代碼,實現返回系統的功能
MOV,AH,4CH
INT 21H
(2)子程序中必須有RET使之能返回主程序
2、語句格式
(1)指令語句:
A、格式:
標號:操作碼 目的操作數,源操作數;注釋
(2)偽指令語句:
A、格式:
變量 操作碼 操作數,……,操作數;注釋
B、作用:
匯編時起到輔助作用,不產生機器碼,也稱為指示性語句。
(3)宏定義語句
A、格式:
標號:宏定義指令名 實際參數;注釋
B、使用MACRO偽指令定義了一條宏指令之后,在代碼段中就可以用宏指令語句來調用此宏指令。
3、變量和標號:
變量和標號都是來表示存儲器中的地址,標號只能在代碼段中定義,變量可以在任意段中定義。標量和標號都有段地址、偏移地址和類型三種屬性,變量的類型屬性有:BYTE,WORD,DWORD幾種。標號的類型有NEAR或者FAR兩種。
4、操作數、表達式和操作符
(1)算術操作符:+ – * / 和MOD
加減可以對地址進行操作
(2)邏輯操作符:AND,OR,XOR,NOT,SHL(左移),SHR(右移)
和指令操作碼方法一致,但只能對數值進行操作,不能對地址進行操作
(3)關系操作符:EQ(相等)、NE(不等)、GT(大於)、LT(小於)、GE(大於等於)、LE(小於等於)
A、用0表示假,用0FFH或者0FFFFH表示真。
B、可以比較數值也可以比較地址
(4)分析操作符:SEG,OFFSET,TYPE,LENGTH和SIZE
SEG | 取段地址 |
OFFSET | 取偏移地址 |
TYPE | 取類型 1:BYTE 2:WORD 4:DWORD |
LENGTH | 取變量中用DUP定義的數據的個數 |
SIZE | LENGTH和TYPE的乘積 |
(5)屬性操作符:HIGH、LOW、SHORT、PTR、THIS和段操作符共6個
HIGH | 取高字節 |
LOW | 取低字節 |
SHORT | 段類型 |
PTR | 改變標號 |
THIS | 改變變量類型 |
5、常用偽指令
(1)符號定義偽指令
A、格式:
名稱 EQU 表達式 ;使用EQU定義的名稱可以進行修改
名稱 = 表達式 ;不可以進行修改
B、作用:
就是定義個符號常量的作用。
(2)數據定義偽指令
A、格式:
變量 偽操作符 表達式,表達式,……;注釋
變量 偽操作符 重復次數 DUP(表達式,表達式,……);注釋
B、說明
①其中變量和注釋可有可無,然后定義數據的偽操作符有以下5個:DB(字節),DW(字)、DD(雙字)、DQ(8個字節)和DT(10個字節)
②若要定義一組數是相同的,使用第二種方法
③若要預留地址空間,沒有初始數值,則數據項可以寫為”?“每一個”?“代表一個數據,占用的地址為由偽操作符決定
四、匯編成語上機過程,(使用尋址方式驗證代碼來書寫)
1、DOSBox模擬器初始化
其中g:\匯編目錄下有:
2、編輯
鍵入代碼后回車。
edit xunzhi.asm
得到如上界面,進行書寫代碼,並保存。
3、匯編
如圖鍵入代碼,回車回車回車
這里會顯示語法錯誤信息,如果有錯就會報錯
3、鏈接
鍵入代碼回車
沒有錯誤,則進行調試
5、調試
如圖鍵入代碼:然后回車就進入調試
(1)鍵入U回車
A、U命令是反匯編,將內存中的機器碼反匯編成指令顯示。
B、可能每次不能顯示全部指令,所以再U可以繼續顯示,U0可以返回到代碼段的首部
(2)在內存中查看數據段,擴展段和堆棧段中的數據
查看內存中的數據使用命令
D+地址:0
D076A:0
再次鍵入D命令,會繼續往下面顯示
(3)單步運行程序,查看運行結果
t=0 從第一句開始,按t順心執行