1. 程式人生 > 其它 >二、8086彙編命令大全

二、8086彙編命令大全

技術標籤:彙編程式語言彙編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 中為餘數
  • 當除數為字型資料時
    • dxax 中的值會拼接到一起作為一個雙字型資料作為被除數,即 (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 ,也可以同時修改 csip

跳轉需要的兩種資訊

  • 轉移的目的地址
  • 轉移的距離
    • 段間轉移
    • 段內短轉移
    • 段內近轉移

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

這種格式的跳轉指令是直接改變 csip 暫存器中的值,從而實現遠距離跳轉。

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 可以分為 alah

  • 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 指令類似實現程式碼的跳轉,但在跳轉前會將 csip 中的值 push 到棧中以用於程式返回。

語法:

call [標誌位]
call [word/dword] ptr [記憶體地址] 

7.2、 RETRETF 指令

用於將 csip 暫存器返回到原來的地址,ret 命令會執行 pop ipretf 命令則會執行 pop cspop ip 兩條命令。

語法:

ret
;-------
retf

7.3、將 CALLRET 配合使用

示例:

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 指令計算 1EF000H201000H 的值:

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

將標誌暫存器中的資料進行入棧和出棧,用法同 pushpop 指令。