1: 基本結構
DATAS SEGMENT ;此處輸入數據段代碼 DATAS ENDS STACKS SEGMENT ;此處輸入堆棧段代碼 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS ;段尋址偽指令用來指明段與段寄存器的對應關系 START: MOV AX,DATAS MOV DS,AX ;此處輸入代碼段代碼 MOV AH,4CH ; INT 21H ; dos系統調用系統終端 執行AH程序中程序退出指令 CODES ENDS END START ; 指定開始的地址
2:基本指令
一、數據傳送指令
1、傳送指令:MOV (move)
(1) CPU內部寄存器之間的數據傳送,如:mov ah,al
(2) 立即數送至通用寄存器(非段寄存器)或存儲單元,如:mov al,3 mov [bx],1234h
(3) 寄存器與存儲器間的數據傳送,如:mov ax,var mov ax,[bx]
二、堆棧操作指令
1、進棧指令:push
格式:push src
功能: 把16位數據src壓入堆棧。
注: 源操作數src可以是通用寄存器和段寄存器,也可以是字存儲單元
如: push si
push [si]
push var ;var是16位(字)變量
2、出棧指令:pop
格式:pop dst
功能:從堆棧彈出16位數據至dst
注: dst可以是通用寄存器和段寄存器,但不能是CS,可以是字存儲單元
如: pop si
pop [si]
pop var ;var是字變量
三 加減運算指令
(1) add(Addtion)
格式:add OPRD1,OPRD2
功能:OPRD1 = OPRD1 + OPRD2
注: 影響FLAG
如:add al,5
add bl,var ;var是字節變量
add var,si ;var是字變量
(2) adc(add with Carry) ;帶進位的加法
格式:adc OPRD1,OPRD2
功能:帶進位的加法,OPRD1 = OPRD1 + OPRD2 + CF
注: 影響FLAG,主要用於多字節運算
如: adc al,[bx]
adc dx,ax
adc dx,var ;var是字變量
(3) inc(Increment)
格式:inc OPRD
功能:OPRD = OPRD + 1
注: 不影響CF
如:inc al
inc var ;var是字節變量,也可以是字變量
inc cx
2、減法指令:sub、sbb、dec、neg、cmp
(1) sub(Subtraction)
格式:sub OPRD1,OPRD2
功能:OPRD1 = OPRD1 - OPRD2
如: sub ah,12
sub bx,bp
sub al,[bx]
sub [BP],AX
sub AX,VAR ;VAR是字變量
(2) sbb(Sub with Borrow)
格式:sbb OPRD1,OPRD2
功能:OPRD1 = OPRD1 - OPRD2 - CF
注: 主要用於多字節數相減的情況
(3) dec(decrement)
格式:dec OPRD
功能:OPRD = OPRD - 1
注: 操作數OPRD可以是通用寄存器,也可以是存儲單元。相減時把操作數作為一個無符號數對待,這條指令影響ZF、SP、OF、PF、AF,但不影響CF,該指令主要用於調整地址指針和計數器。
(4) neg(Negate)
格式:NEG OPRD
功能:對操作數取補,即OPRD = 0 - OPRD
注: 操作數可以是通用寄存器,也可以是存儲單元。此指令結果影響CF、ZF、OF、AF、PF,一般會使CF為1,除非OPRD=0
(5) cmp(Compare)
格式:cmp OPRD1,OPRD2
功能:執行OPRD1 - OPRD2,但運算結果不運送到OPRD1
注: 該指令通過OPRD - OPRD2影響標志位CF、ZF、SF、OF、AF、PF來判斷OPRD1和OPRD2的大小關系。通過ZF判斷是否相等;如果是無符號數,通過CF可判斷大小;如果是有符號數,通過SF和OF判斷大小
四、乘除運算指令
(1) mul(Multiply) ;無符號數乘法指令
格式:MUL OPRD
功能:將OPRD與AX或AL中的操作數相乘,結果保存在DX:AX中或AX中
注: 無符號數相乘分為16位*16位和8位*8位,結果分別為32位和16位,保存在DX:AX中或AX中,其中結果為32位時,DX為高16位,AX為低16位;結果為16位時,AH為高8位,AL為低8位。
(2) imul(Signed Multiply) ;有符號數乘法指令
格式:IMUL OPRD
功能:把乘數和被乘數均作為有符號數進行乘法運算。其余與mul類似
注: 如果乘積結果的高位部分(DX或AH)不是低位的符號擴展,則CF=1,OF=1,否則CF=0,OF=0。即CF=1,OF=1表示AH或DX中含有結果的有效數。
如果除數為0,或8位數除時商超過8位,16位數除時商超過16位,則認為是除溢出,引起0號中斷。除法指令對標志位的影響無定義。
2、除法指令:div、idiv
(1) div(Division) ;無符號數除法指令
格式:DIV OPRD
功能:OPRD為除數,被除數存放在DX:AX或AX中,做除法,結果存放在DX:AX(DX存放余數,AX存放商)或AX(AH余數,AL商)。
注: 8086中除法有32位除以16位和16位除以8位。前者被除數為32位,高位在DX中,低位在AX中,除數OPRD為16位通用寄存器或16位存儲器操作數,結果為16位,其中16位余數存放在DX中,16位商存放在AX中;若為16位除以8位,被除數存放在AX中,OPRD為8位通用寄存器或存儲器操作數,結果8位余數存放在AH中,8位商存放在AL中。
(2) idiv(Signed Division) ;有符號數除法指令
格式:IDIV OPRD
功能:把除數和被除數看做有符號數做除法,其余與div類似
3、符號擴展指令:cbw、cwd
(1) cbw(Convert Byte to Word)
格式:CBW
功能:把寄存器AL中的符號位擴展到寄存器AH
(2) cwd(Convert Word to Double Word)
格式:CWD
功能:把寄存器AX中的符號擴展到寄存器DX
五、邏輯運算和移位指令
(1) NOT
格式:NOT OPRD
功能:把操作數OPRD取反,然后送回OPRD。
注: OPRD可以是通用寄存器,也可以是存儲器操作數,此指令對標志沒有影響
(2) AND
格式:AND OPRD1,OPRD2
功能:對兩個操作數進行按位邏輯“與”運算,結果送到OPRD1中
注: 該指令執行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果,AF未定義。
某個操作數與自身相與,值不變,但可以使CF置0。
(3) OR
格式:OR OPRD1,OPRD2
功能:對兩個操作數進行按位邏輯“或”運算,結果送到OPRD1中
注: 該指令執行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果,AF未定義。
某個操作數與自身相或,值不變,但可以使CF置0。
(4) XOR
格式:XOR OPRD1,OPRD2
功能:對兩個操作數進行按位邏輯“異或”運算,結果送到OPRD1中
注: 該指令執行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果,AF未定義。
(5) TEST
格式:TEST OPRD1,OPRD2
功能:把OPRD1與OPRD2按位“與”,但結果不送到OPRD1中,僅影響標志位。
注: 該指令執行后,CF=0,OF=0,標志PF、ZF、SF反映運算結果。常用於檢測某些位是否為1
2、一般移位指令:SAL/SHL,SAR/SHR
(1) SAL/SHL(Shift Arithmetic Left / Shift Logic Left) ;算術左移/邏輯左移
格式:SAL OPRD,m
SHL OPRD,m
功能:把操作數OPRD左移m位,每移動一位,右邊用0補足1位,移出的最高位進入標志位CF
注: 算術左移和邏輯左移進行相同的動作,為了方便提供了兩個助記符。
(2) SAR(Shift Arithmetic Right) ;算數右移指令
格式:SAR OPRD,m
功能:操作數右移m位,同時每移1位,左邊的符號位保持不變,移出的最低位進入標志位CF
注: 對有符號數和無符號數,算數右移1位相當於除以2
(3) SHR(Shift Logic Right) ;邏輯右移指令
格式:SHR OPRD,m
功能:操作數右移m位,同時每移1位,左邊用0補足,移出的最低位進入標志位CF
注: 對無符號數,邏輯右移1位相當於除以2
3、循環移位指令:ROL、ROR、RCL、RCR
4 、循環指令:LOOP、LOOPE/LOOPZ、LOOPNE/LOOPNZ、JCXZ
(1) Loop ;計數循環指令
格式:loop 標號
功能:使轉移標號與Loop指令間的指令循環執行CX次
原理:指令執行至loop時,cx減1,如果cx不為0,則跳轉至標號處,否則繼續執行下一條指令
即:DEC CX
JNZ 標號
(2) LOOPE/LOOPZ ;等於/全零循環指令
格式:LOOPE 標號
LOOPZ 標號
功能:該指令使CX自減1,若結果不為0,並且ZF=1,則轉移至標號,否則順序執行。注意指令本身實施的CX自減1操作不影響標志
(3) LOOPNE/LOOPNZ ;不等於/非零循環指令
格式:LOOPNE 標號
LOOPNZ 標號
功能:該指令使CX自減1,若結果不為0,並且ZF=0,則轉移至標號,否則順序執行。注意指令本身實施的CX自減1操作不影響標志
(4) JCXZ ;跳轉指令
格式:JCXZ 標號
功能:當寄存器CX的值為0時跳轉到標號,否則順序執行
跳轉指令匯總:
助記符 | 說明 | 標志位/寄存器 | 助記符 | 說明 | 標志位/寄存器 |
---|---|---|---|---|---|
JZ | 為零跳轉 | ZF=1 | JNO | 無溢出跳轉 | OF=0 |
JNZ | 非零跳轉 | ZF=0 | JS | 有符號跳轉 | SF=1 |
JC | 進位跳轉 | CF=1 | JNS | 無符號跳轉 | SF=0 |
JNC | 無進位跳轉 | CF=0 | JP | 偶校驗跳轉 | PF=1 |
JO | 溢出跳轉 | OF=1 | JNP | 奇校驗跳轉 | PF=0 |
助記符 | 說明 |
---|---|
JE | 相等跳轉 (leftOp=rightOp) |
JNE | 不相等跳轉 (leftOp M rightOp) |
JCXZ | CX=0 跳轉 |
JECXZ | ECX=0 跳轉 |
JRCXZ | RCX=0 跳轉(64 位模式) |
助記符 | 說明 | 助記符 | 說明 |
---|---|---|---|
JA | 大於跳轉(若 leftOp > rightOp) | JB | 小於跳轉(若 leftOp < rightOp) |
JNBE | 不小於或等於跳轉(與 JA 相同) | JNAE | 不大於或等於跳轉(與 JB 相同) |
JAE | 大於或等於跳轉(若 leftOp ≥ rightOp) | JBE | 小於或等於跳轉(若 leftOp ≤ rightOp) |
JNB | 不小於跳轉(與 JAE 相同) | JNA | 不大於跳轉(與 JBE 相同) |
助記符 | 說明 | 助記符 | 說明 |
---|---|---|---|
JG | 大於跳轉(若 leftOp > rightOp) | JL | 小於跳轉(若 leftOp < rightOp) |
JNLE | 不小於或等於跳轉(與 JG 相同) | JNGE | 不大於或等於跳轉(與 JL 相同) |
JGE | 大於或等於跳轉(若 leftOp ≥ rightOp) | JLE | 小於或等於跳轉(若 leftOp ≤ rightOp) |
JNL | 不小於跳轉(與 JGE 相同) | JNG | 不大於跳轉(與 JLE 相同) |
3:通用寄存器用途
通用寄存器的主要用途
寄存器的分類 | 寄存器 | 主 要 用 途 |
|
通 用 寄 存 器 |
數據
寄存器 |
AX | 乘、除運算,字的輸入輸出,中間結果的緩存 |
AL | 字節的乘、除運算,字節的輸入輸出,十進制算術運算 |
||
AH | 字節的乘、除運算,存放中斷的功能號 |
||
BX | 存儲器指針 |
||
CX | 串操作、循環控制的計數器 |
||
CL | 移位操作的計數器 |
||
DX | 字的乘、除運算,間接的輸入輸出 |
||
變址 寄存器 |
SI | 存儲器指針、串指令中的源操作數指針 |
|
DI | 存儲器指針、串指令中的目的操作數指針 |
||
變址 寄存器 |
BP | 存儲器指針、存取堆棧的指針 |
|
SP | 堆棧的棧頂指針 |
||
指令指針 |
IP/EIP | ||
標志位寄存器 | Flag/EFlag | ||
32位 CPU的 段寄存器 |
16位CPU的 段寄存器 |
ES | 附加段寄存器 |
CS | 代碼段寄存器 | ||
SS | 堆棧段寄存器 | ||
DS | 數據段寄存器 | ||
新增加的 段寄存器 |
FS | 附加段寄存器 | |
GS | 附加段寄存器 |
4:常用DOS指令表
AH
|
功能
|
調用參數
|
返回參數
|
00
|
程序終止(同INT 20H)
|
CS=程序段前綴
|
|
01
|
鍵盤輸入並回顯
|
|
AL=輸入字符
|
02
|
顯示輸出
|
DL=輸出字符
|
|
03
|
異步通迅輸入
|
|
AL=輸入數據
|
04
|
異步通迅輸出
|
DL=輸出數據
|
|
05
|
打印機輸出
|
DL=輸出字符
|
|
06
|
直接控制台I/O
|
DL=FF(輸入)
DL=字符(輸出) |
AL=輸入字符
|
07
|
鍵盤輸入(無回顯)
|
|
AL=輸入字符
|
08
|
鍵盤輸入(無回顯)
檢測Ctrl-Break |
|
AL=輸入字符
|
09
|
顯示字符串
|
DS:DX=串地址
'$'結束字符串 |
|
0A
|
鍵盤輸入到緩沖區
|
DS:DX=緩沖區首地址
(DS:DX)=緩沖區最大字符數 |
(DS:DX+1)=實際輸入的字符數
|
0B
|
檢驗鍵盤狀態
|
|
AL=00 有輸入
AL=FF 無輸入 |
0C
|
清除輸入緩沖區並
請求指定的輸入功能 |
AL=輸入功能號
(1,6,7,8,A) |
|
0D
|
磁盤復位
|
|
清除文件緩沖區
|
0E
|
指定當前缺省的磁盤驅動器
|
DL=驅動器號 0=A,1=B,...
|
AL=驅動器數
|
0F
|
打開文件
|
DS:DX=FCB首地址
|
AL=00 文件找到
AL=FF 文件未找到 |
10
|
關閉文件
|
DS:DX=FCB首地址
|
AL=00 目錄修改成功
AL=FF 目錄中未找到文件 |
11
|
查找第一個目錄項
|
DS:DX=FCB首地址
|
AL=00 找到
AL=FF 未找到 |
12
|
查找下一個目錄項
|
DS:DX=FCB首地址
(文件中帶有*或?) |
AL=00 找到
AL=FF 未找到 |
13
|
刪除文件
|
DS:DX=FCB首地址
|
AL=00 刪除成功
AL=FF 未找到 |
14
|
順序讀
|
DS:DX=FCB首地址
|
AL=00 讀成功
=01 文件結束,記錄中無數據 =02 DTA空間不夠 =03 文件結束,記錄不完整 |
15
|
順序寫
|
DS:DX=FCB首地址
|
AL=00 寫成功
=01 盤滿 =02 DTA空間不夠 |
16
|
建文件
|
DS:DX=FCB首地址
|
AL=00 建立成功
=FF 無磁盤空間 |
17
|
文件改名
|
DS:DX=FCB首地址
(DS:DX+1)=舊文件名 (DS:DX+17)=新文件名 |
AL=00 成功
AL=FF 未成功 |
19
|
取當前缺省磁盤驅動器
|
|
AL=缺省的驅動器號 0=A,1=B,2=C,...
|
1A
|
置DTA地址
|
DS:DX=DTA地址
|
|
1B
|
取缺省驅動器FAT信息
|
|
AL=每簇的扇區數
DS:BX=FAT標識字節 CX=物理扇區大小 DX=缺省驅動器的簇數 |
1C
|
取任一驅動器FAT信息
|
DL=驅動器號
|
同上
|
21
|
隨機讀
|
DS:DX=FCB首地址
|
AL=00 讀成功
=01 文件結束 =02 緩沖區溢出 =03 緩沖區不滿 |
22
|
隨機寫
|
DS:DX=FCB首地址
|
AL=00 寫成功
=01 盤滿 =02 緩沖區溢出 |
23
|
測定文件大小
|
DS:DX=FCB首地址
|
AL=00 成功(文件長度填入FCB)
AL=FF 未找到 |
24
|
設置隨機記錄號
|
DS:DX=FCB首地址
|
|
25
|
設置中斷向量
|
DS:DX=中斷向量
AL=中斷類型號 |
|
26
|
建立程序段前綴
|
DX=新的程序段前綴
|
|
27
|
隨機分塊讀
|
DS:DX=FCB首地址
CX=記錄數 |
AL=00 讀成功
=01 文件結束 =02 緩沖區太小,傳輸結束 =03 緩沖區不滿 |
28
|
隨機分塊寫
|
DS:DX=FCB首地址
CX=記錄數 |
AL=00 寫成功
=01 盤滿 =02 緩沖區溢出 |
29
|
分析文件名
|
ES:DI=FCB首地址
DS:SI=ASCIIZ串 AL=控制分析標志 |
AL=00 標准文件
=01 多義文件 =02 非法盤符 |
2A
|
取日期
|
|
CX=年
DH:DL=月:日(二進制) |
2B
|
設置日期
|
CX:DH:DL=年:月:日
|
AL=00 成功
=FF 無效 |
2C
|
取時間
|
|
CH:CL=時:分
DH:DL=秒:1/100秒 |
2D
|
設置時間
|
CH:CL=時:分
DH:DL=秒:1/100秒 |
AL=00 成功
=FF 無效 |
2E
|
置磁盤自動讀寫標志
|
AL=00 關閉標志
AL=01 打開標志 |
|
2F
|
取磁盤緩沖區的首址
|
|
ES:BX=緩沖區首址
|
30
|
取DOS版本號
|
|
AH=發行號,AL=版本
|
31
|
結束並駐留
|
AL=返回碼
DX=駐留區大小 |
|
33
|
Ctrl-Break檢測
|
AL=00 取狀態
=01 置狀態(DL) DL=00 關閉檢測 =01 打開檢測 |
DL=00 關閉Ctrl-Break檢測
=01 打開Ctrl-Break檢測 |
35
|
取中斷向量
|
AL=中斷類型
|
ES:BX=中斷向量
|
36
|
取空閑磁盤空間
|
DL=驅動器號
0=缺省,1=A,2=B,... |
成功:AX=每簇扇區數
BX=有效簇數 CX=每扇區字節數 DX=總簇數 失敗:AX=FFFF |
38
|
置/取國家信息
|
DS:DX=信息區首地址
|
BX=國家碼(國際電話前綴碼)
AX=錯誤碼 |
39
|
建立子目錄(MKDIR)
|
DS:DX=ASCIIZ串地址
|
AX=錯誤碼
|
3A
|
刪除子目錄(RMDIR)
|
DS:DX=ASCIIZ串地址
|
AX=錯誤碼
|
3B
|
改變當前目錄(CHDIR)
|
DS:DX=ASCIIZ串地址
|
AX=錯誤碼
|
3C
|
建立文件
|
DS:DX=ASCIIZ串地址
CX=文件屬性 |
成功:AX=文件代號
錯誤:AX=錯誤碼 |
3D
|
打開文件
|
DS:DX=ASCIIZ串地址
AL=0 讀 =1 寫 =3 讀/寫 |
成功:AX=文件代號
錯誤:AX=錯誤碼 |
3E
|
關閉文件
|
BX=文件代號
|
失敗:AX=錯誤碼
|
3F
|
讀文件或設備
|
DS:DX=數據緩沖區地址
BX=文件代號 CX=讀取的字節數 |
讀成功:
AX=實際讀入的字節數 AX=0 已到文件尾 讀出錯:AX=錯誤碼 |
40
|
寫文件或設備
|
DS:DX=數據緩沖區地址
BX=文件代號 CX=寫入的字節數 |
寫成功:
AX=實際寫入的字節數 寫出錯:AX=錯誤碼 |
41
|
刪除文件
|
DS:DX=ASCIIZ串地址
|
成功:AX=00
出錯:AX=錯誤碼(2,5) |
42
|
移動文件指針
|
BX=文件代號
CX:DX=位移量 AL=移動方式(0:從文件頭絕對位移,1:從當前位置相對移動,2:從文件尾絕對位移) |
成功:DX:AX=新文件指針位置
出錯:AX=錯誤碼 |
43
|
置/取文件屬性
|
DS:DX=ASCIIZ串地址
AL=0 取文件屬性 AL=1 置文件屬性 CX=文件屬性 |
成功:CX=文件屬性
失敗:CX=錯誤碼 |
44
|
設備文件I/O控制
|
BX=文件代號
AL=0 取狀態 =1 置狀態DX =2 讀數據 =3 寫數據 =6 取輸入狀態 =7 取輸出狀態 |
DX=設備信息
|
45
|
復制文件代號
|
BX=文件代號1
|
成功:AX=文件代號2
失敗:AX=錯誤碼 |
46
|
人工復制文件代號
|
BX=文件代號1
CX=文件代號2 |
失敗:AX=錯誤碼
|
47
|
取當前目錄路徑名
|
DL=驅動器號
DS:SI=ASCIIZ串地址 |
(DS:SI)=ASCIIZ串
失敗:AX=出錯碼 |
48
|
分配內存空間
|
BX=申請內存容量
|
成功:AX=分配內存首地
失敗:BX=最大可用內存 |
49
|
釋放內容空間
|
ES=內存起始段地址
|
失敗:AX=錯誤碼
|
4A
|
調整已分配的存儲塊
|
ES=原內存起始地址
BX=再申請的容量 |
失敗:BX=最大可用空間
AX=錯誤碼 |
4B
|
裝配/執行程序
|
DS:DX=ASCIIZ串地址
ES:BX=參數區首地址 AL=0 裝入執行 AL=3 裝入不執行 |
失敗:AX=錯誤碼
|
4C
|
帶返回碼結束
|
AL=返回碼
|
|
4D
|
取返回代碼
|
|
AX=返回代碼
|
4E
|
查找第一個匹配文件
|
DS:DX=ASCIIZ串地址
CX=屬性 |
AX=出錯代碼(02,18)
|
4F
|
查找下一個匹配文件
|
DS:DX=ASCIIZ串地址
(文件名中帶有?或*) |
AX=出錯代碼(18)
|
54
|
取盤自動讀寫標志
|
|
AL=當前標志值
|
56
|
文件改名
|
DS:DX=ASCIIZ串(舊)
ES:DI=ASCIIZ串(新) |
AX=出錯碼(03,05,17)
|
57
|
置/取文件日期和時間
|
BX=文件代號
AL=0 讀取 AL=1 設置(DX:CX) |
DX:CX=日期和時間
失敗:AX=錯誤碼 |
58
|
取/置分配策略碼
|
AL=0 取碼
AL=1 置碼(BX) |
成功:AX=策略碼
失敗:AX=錯誤碼 |
59
|
取擴充錯誤碼
|
|
AX=擴充錯誤碼
BH=錯誤類型 BL=建議的操作 CH=錯誤場所 |
5A
|
建立臨時文件
|
CX=文件屬性
DS:DX=ASCIIZ串地址 |
成功:AX=文件代號
失敗:AX=錯誤碼 |
5B
|
建立新文件
|
CX=文件屬性
DS:DX=ASCIIZ串地址 |
成功:AX=文件代號
失敗:AX=錯誤碼 |
5C
|
控制文件存取
|
AL=00封鎖
=01開啟 BX=文件代號 CX:DX=文件位移 SI:DI=文件長度 |
失敗:AX=錯誤碼
|
62
|
取程序段前綴
|
|
BX=PSP地址
|
參考: https://blog.csdn.net/qq_40843865/article/details/81210164
參考: https://www.cnblogs.com/huzhongzhong/archive/2011/08/01/2123743.html