二、8086彙編命令大全
8086彙編命令大全
1、基礎指令
1.1、MOV
指令
將逗號前的暫存器中的值修改為逗號後暫存器的值、記憶體的值或指定的值
語法:
mov [暫存器], [需要放入的值]
示例:
mov ax, 100
將 100 賦值到
ax
暫存器
也可以將一個暫存器中的值賦值到另一個暫存器
mov bx, 100 ; 將100賦值到bx
mov ax, bx ; 將bx中的值賦值到ax中
也可以將記憶體中的值賦值到暫存器中
mov ax, 2000H ; 將段地址先儲存到ax中 mov ds, ax ; 設定段地址 mov bx, 1000H ; 將偏移地址儲存到bx中,以便引用 mov ax, [bx] ; 將段地址為2000,偏移地址為1000的記憶體中的值賦值到ax中 mov ax, ds:[bx] ; 效果同上 mov ax, ds:[1000H] ; 效果同上
在原始碼中,不可以直接使用
[0]
來表示偏移地址,必須引用其他暫存器中的值,或者使用ds:[0]
這種格式。
1.2、使用 idata
可以在程式中使用 idata
更方便的定位到指定的偏移地址
示例:
mov ax, [bx+10]
mov ax, [bx+si+10]
可以在設定偏移地址的方括號中使用運算
1.3、操作符 PTR
一般在執行計算時,指令後的暫存器會預設指定計算的值是字資料還是位元組資料。例如:add al, sp:[0]
和 add ax, sp:[0]
,但是在一些特殊情況下,編譯器無從得知需要計算的數是字資料還是位元組資料,此時,就需要操作符 ptr
來指定資料型別。
語法:
[指令] [word/byte] ptr [操作]
示例:
inc word ptr sp:[0] ; 以字為單位將指定記憶體中的資料自加
1.4、操作符 OFFSET
取得對應標號的偏移地址
示例:
s:mov ax, offset s ; 將標號s所處的偏移地址複製到ax暫存器中
2、計算指令
2.1、ADD
加法
將第二個值和第一個暫存器中的值相加,並放入第一個暫存器中,用法同 mov
。
語法:
add [暫存器], [需要相加的值]
2.2、 SUB
減法
減法運算,用法同 add
指令
示例:
sub ax, 10
2.2、INC
自增& DEC
自減
自增,將指定的值加一。
語法:
inc [暫存器]
inc [記憶體地址]
自減,將指定的值減一
語法:
dec [暫存器]
dec [記憶體地址]
2.3、AND
與運算
邏輯與指令,將兩個值進行邏輯與計算
1 and 1 = 1
0 and 1 = 0
1 and 0 = 0
0 and 0 = 0
語法:
and [暫存器、記憶體地址], [暫存器、記憶體地址]
示例:
and ax, bx
2.4、OR
或運算
邏輯或雲端,將兩個值進行邏輯或計算
1 or 1 = 1
0 or 1 = 1
1 or 0 = 1
0 or 0 = 0
語法:
or [暫存器、記憶體地址], [暫存器、記憶體地址]
示例:
or ax, bx
2.5、 MUL
乘法
對指定數值進行乘法計算
- 8位的值進行相乘時結果在
ax
中,乘數預設在al
中 - 16位的值進行相乘時
dx
中為高位ax
中為低位,乘數預設在ax
中
2.6、 DIV
除法
除法指令 division
對暫存器的值進行除法運算。
- 當除數為位元組型資料時,執行
div
指令後ax
暫存器中的值會被作為被除數- 結果:
al
中為結果的商ah
中為餘數
- 當除數為字型資料時
dx
和ax
中的值會拼接到一起作為一個雙字型資料作為被除數,即(dx)*10000h+(ax)
- 結果:
ax
中為商dx
中為餘數
示例:
assume cs:code
code segment
start:mov ax, 4d00h
mov dx, 25h ; 設定被除數為 254d00
mov bx, 7d0h ; 設定除數為 7d0
div bx
mov ax, 4c00h
int 21h
code ends
end start
3、轉移指令
3.1、迴圈 LOOP
3.1.1、單迴圈
使用此指令可以跳轉到指定的程式碼開始迴圈,若暫存器 cx
的值為0時則繼續執行,若不為0時則會跳轉到指定的程式碼進行迴圈,迴圈一次完成後會將 cx
中的值減一。
語法:
s:[程式碼段]
[程式碼...]
loop s ; 跳轉到標號為 s 的程式碼上繼續執行
loop
是否執行是判斷cx
中值,所以在使用loop
時一定要將cx
中的值儲存處理。
3.1.2、多層迴圈
在多層迴圈的情況下,所有的 loop
指令使用的都是 cx
的值,所以在執行內層迴圈時需要將 cx
的值進行儲存復原操作。
此操作可以使用暫存器和記憶體來實現,暫存器由於數量有限而且易被覆蓋,而獨立的記憶體地址在多個迴圈巢狀的情況下容易混淆,故使用棧來暫存復原 cx
的值。
格式:
assume cs:code, ss:stack
stack segment
dw 0,0,0,0,0,0,0,0
stack ends
code segment
start:mov ax, stack
mov ss, ax
mov sp, 10h
mov cx, 10 ; 設定外層迴圈次數
s0:[...do something...]
push cx ; 儲存外層迴圈次數
mov cx, 20 ; 設定內層迴圈次數
s1:[...do something...]
loop s1
pop cx ; 復原外層迴圈次數
loop s0
mov ax, 4c00h
int 21h
code ends
3.2、 JUMP
無條件轉移指令
jump
為無條件轉移,可以只修改 ip
,也可以同時修改 cs
和 ip
跳轉需要的兩種資訊
- 轉移的目的地址
- 轉移的距離
- 段間轉移
- 段內短轉移
- 段內近轉移
3.2.1、偏移距離轉移
語法:
jmp [標號]
示例:
assume cs:code
code segment
start:mov ax, 1111h
jmp s
mov ax, 2222h
s:mov ax, 3333h
mov ax, 4c00h
int 21h
code ends
end start
此指令使用的資料位為8位,所以跳轉的極限位置為
-128~127
超出此區域會發生錯誤。使用位移的方式確定跳轉的地址時,無論這段程式碼放置在記憶體的任何位置,都可以正常執行。
3.2.2、段地址偏移地址轉移
語法:
jmp far ptr [標號]
示例:
assume cs:code
code segment
start:mov ax, 0
mov ax, 11h
jmp far ptr s ; 此跳轉指令編譯後為 JMP 076E:010B
db 256 dup (0)
s:add ax, 1
mov ax, 4c00h
int 21h
code ends
end start
這種格式的跳轉指令是直接改變
cs
和ip
暫存器中的值,從而實現遠距離跳轉。
3.2.3、使用暫存器和記憶體中的地址轉移
直接使用暫存器或記憶體中儲存的內容作為 ip
暫存器的值進行跳轉
語法:
- 暫存器
mov ax, 0123h
jmp ax
- 記憶體
jmp word ptr ds:[12]
- 實現段間跳轉
jmp dword ptr ds:[12]
段間跳轉使用的的是雙字型資料,指定
記憶體單元地址
為ip
的值,記憶體單元地址+2
的資料為cs
暫存器的值。
3.3、 JCXZ
條件轉移指令
根據條件:若暫存器 cx
的值為0,則跳轉到指定標號的程式碼段,若 cx
不為0則繼續向下執行。
格式:
jcxz short [標號]
4、棧段指令
4.1、入棧 PUSH
將指定的資料壓入棧底,sp
暫存器中儲存的內容是棧底的指標,值為棧底的偏移地址。
語法:
push [暫存器、記憶體地址、資料]
示例:
push ds:[bx]
4.2、出棧 POP
將棧頂的資料出棧到指定的暫存器或記憶體中
語法:
pop [暫存器、記憶體地址]
示例:
pop ds:[bx]
在使用棧段進行入棧出棧操作時,一定要先設定好
sp
暫存器的值。
5、偽指令
指令語句在源程式彙編時會產生可供計算機執行的指令程式碼,即目的碼。彙編程式除指令語句外,還需要提供一些指令,用於輔助源程式的彙編。比如指定程式或資料存放的起始地址,為資料分配一段連續的記憶體單元等。這些指令在彙編時並不生成目的碼,不影響程式執行,因此稱之為偽指令。
5.1、變數定義
5.1.1、 db
指令
定義一個位元組長度的資料
db 10,20
5.1.2、 dw
指令
定義兩個位元組長度的資料,也稱為字型變數
dw 0123h,0234h
5.1.3、 dd
指令
定義四個位元組長度的資料,也稱為雙字型變數
dd 123,234
5.2、 DUP
定義多個變數
使用 dup
偽指令可以同時定義多個變數
格式:
[db/dw/dp] [需要生成的數量] dup ([值],..)
示例:
dw 3 dup (0) ; 同 dw 0,0,0
dw 3 dup (0,1) ; 同 dw 0,1,0,1,0,1
6、暫存器
6.1、暫存器
-
AX,BX,CX,DX 資料暫存器:
-
AX (Accumulator):累加暫存器,也稱之為累加器
-
BX (Base):基地址暫存器
-
CX (Count):計數器暫存器
-
DX (Data):資料暫存器
-
以上四個暫存器都可以分為兩個8位的暫存器,例如
ax
可以分為al
,ah
-
-
SP 和 BP 指標暫存器:
- SP (Stack Pointer):堆疊指標暫存器
- BP (Base Pointer):基指標暫存器
-
SI 和 DI 變址暫存器:
- SI (Source Index):源變址暫存器
- DI (Destination Index):目的變址暫存器
- 只有
bx,bp,si,di
可以放在[]
中進行定址操作。並且只可以存在四種組合bx,si
bx,di
bp,si
bp,di
- 在
[]
定址時使用bp
並且沒有顯式給出段地址,段地址預設在ss
中
6.2、段暫存器
-
CS (Code Segment):程式碼段暫存器;
-
DS (Data Segment):資料段暫存器;
-
SS (Stack Segment):堆疊段暫存器;
-
ES (Extra Segment):附加段暫存器;
7、函式呼叫
7.1、 CALL
指令
用於和 ret
指令配合時間函式呼叫和返回,用法與 jmp
指令類似實現程式碼的跳轉,但在跳轉前會將 cs
和 ip
中的值 push
到棧中以用於程式返回。
語法:
call [標誌位]
call [word/dword] ptr [記憶體地址]
7.2、 RET
和 RETF
指令
用於將 cs
和 ip
暫存器返回到原來的地址,ret
命令會執行 pop ip
而 retf
命令則會執行 pop cs
和 pop ip
兩條命令。
語法:
ret
;-------
retf
7.3、將 CALL
和 RET
配合使用
示例:
assume cs:code, ss:stack
stack segment
db 16 dup(0) ; 用來儲存 cs 和 ip 的值
stack ends
code segment
start:mov ax, stack
mov ss, ax
mov sp, 16
call s ; 呼叫 s 程式碼段,實現函式呼叫
mov ax, 4c00h
int 21h
s:mov ax, 0
add ax, 10h
ret ; 返回到 call 命令後,實現函式返回
code ends
end start
8、標誌暫存器指令
8.1、 ADC
指令
adc
指令用於在計算時將 CF
標誌暫存器的值也進行帶入運算,可以用來實現更多位數的資料運算,使用格式與 add
相同。
格式:
adc [暫存器], [數值/暫存器/記憶體]
示例:
adc ax, 10
公式
(ax)+10+(cf)
使用 adc
指令計算 1EF000H
和 201000H
的值:
assume cs:code
code segment
start:
mov ax, 001eh ; 第一個數的高位
mov bx, 0f000h ; 第一個數的低位
add bx, 1000h ; 將低位相加,進位儲存到CF中
adc ax, 20h ; 兩數高位和CF中的進位相加
; 結果 ax 中為高位 bx 中為低位
mov ax, 4c00h
int 21h
code ends
end start
8.2、 SBB
指令
sbb
指令用法與 adc
指令相同,此指令使用者兩數相減再減去 cf
標記暫存器中的值。
示例:
sbb ax, bx
公式:
(ax)-(bx)-(cf)
8.3、 CMP
指令
此指令功能相當於減法指令,但是不儲存結果只會影響標誌暫存器的值。其他指令通過識別被影響的標誌暫存器來得知比較結果。
格式:
cmp [操作物件1], [操作物件2]
示例:
mov ax, 8
mov bx, 3
cmp ax, bx
執行後:
ax不變
ZF=0
PF=1
SF=0
CF=0
OF=0
通過此指令可以判斷標誌暫存器的值來確定兩個數的大小關係
a
為值1,b
為值2
ZF
若為1則表示兩個數相等ZF
若為0則表示兩個數不相等OF
若為0,沒有溢位SF
為1,表示a<b
SF
為0,表示a>b
OF
為1,有溢位SF
的含義正好和表達的相反
8.4、條件轉移指令
指令 | 含義 | 檢測內容 |
---|---|---|
je | 等於轉移 | ZF=1 |
jne | 不等於轉移 | ZF=0 |
jb | 低於轉移 | CF=1 |
jnb | 不低於轉移 | CF=0 |
ja | 高於轉移 | CF=0&ZF=0 |
jna | 不高於轉移 | CF=1orZF=1 |
8.5、串傳送指令
每次執行指令 SI,DI
暫存器都會根據 DF
標誌位進行相應的增減。
((es)*16+di)=((es)*16+si)
- 如果
DF=0
- 增加
SI,DI
- 增加
- 如果
DF=1
- 減少
SI,DI
- 減少
串傳送指令和
rep
指令進行配合可以實現迴圈多次複製,迴圈條件和loop
指令相同。
8.5.1、 MOVSB
位元組傳送
每次 SI,DI
加一,實現正向複製。
示例:
assume cs:code,ds:data
data segment
db 'hello world'
db 11 dup (0)
data ends
code segment
start:
mov ax, data
mov ds, ax
mov si, 0
mov es, ax
mov di, 11
mov cx, 11
cld
rep movsb
mov ax,4c00h
int 21h
code ends
end start
結果:
8.5.2、 MOVSW
字傳送
效果同 movsb
指令,movsw
傳送的為字型資料。
8.6、修改 DF
標誌位
設定 DF
標誌:
cld ; 將DF設定為0
std ; 將DF設定為1
8.7、 PUSHF
& POPF
將標誌暫存器中的資料進行入棧和出棧,用法同 push
和 pop
指令。