共用方式為


x86 指示

在本節清單中,以星號標示的指示 (*) 特別重要。 未標示的指示並不重要。

在 x86 處理器上,指令是可變大小的,因此反向反組譯是模式比對的練習。 若要從位址向後反組譯,您應該從某個點開始反組譯,比您真正想要更進一步的反組譯,然後向前查看直到指示開始有意義為止。 前幾個指示可能沒有任何意義,因為您可能已在指令中間開始反組譯。 可惜的是,反組解碼永遠不會與指令資料流程同步處理,而且您必須嘗試在不同的起點反組譯,直到您找到可運作的起點為止。

對於妥善封裝的 switch 語句,編譯器會將資料直接發出至程式碼資料流程,因此透過 switch 語句進行反組譯通常會輪轉到沒有意義 (的指示,因為它們實際上是資料) 。 尋找資料結尾並繼續反組譯。

指令標記法

指示的一般標記法是將目的地暫存器放在左邊,並將來源放在右邊。 不過,此規則可能有一些例外狀況。

算術指令通常是與來源和目的地暫存器結合的雙暫存器。 結果會儲存至目的地。

部分指示同時具有 16 位和 32 位版本,但此處只會列出 32 位版本。 此處未列出浮點指令、特殊許可權指示,以及僅用於分段模型的指示, (Microsoft Win32 不會使用) 。

為了節省空間,許多指令會以合併形式表示,如下列範例所示。

*

MOV

r1r/m/#n

r1 = r/m/#n

表示第一個參數必須是暫存器,但第二個參數可以是暫存器、記憶體參考或立即值。

為了節省更多空間,您也可以如下列所示來表示指示。

*

MOV

r1/m、 r/m/#n

r1/m = r/m/#n

這表示第一個參數可以是暫存器或記憶體參考,而第二個參數可以是暫存器、記憶體參考或立即值。

除非另有說明,否則使用這個縮寫時,您無法同時選擇來源和目的地的記憶體。

此外,位大小的尾碼 (8、16、32) 可以附加至來源或目的地,以指出參數必須是該大小。 例如,r8 表示 8 位暫存器。

記憶體、資料傳輸和資料轉換

記憶體和資料傳輸指令不會影響旗標。

有效位址

*

Lea

r, m

載入有效位址。

(r = m) 位址

例如,LEA eax,[esi+4]表示eax = esi + 4。 這個指令通常用來執行算術。

資料傳輸

MOV

r1/m、 r2/m/#n

r1/m = r/m/#n

MOVSX

r1r/m

使用符號延伸模組移動。

*

MOVZX

r1r/m

以零副檔名移動。

MOVSXMOVZX 是從來源到目的地執行符號延伸或零延伸模組的特殊 mov 指令版本。 這是唯一允許來源和目的地大小不同的指令。 (事實上,它們的大小必須不同。

堆疊操作

堆疊是由 esp暫存器所指向。 esp的值是最近推送的堆疊頂端 (,首先要彈出) ;較舊的堆疊元素位於較高的位址。

PUSH

r/m/#n

將值推送至堆疊。

POP

r/m

堆疊的 Pop 值。

PUSHFD

將旗標推送至堆疊。

POPFD

堆疊中的快顯旗標。

PUSHAD

推送所有整數暫存器。

POPAD

快顯所有整數暫存器。

ENTER

#n,#n

建置堆疊框架。

*

離開

卸載堆疊框架

C/C++ 編譯器不使用 enter 指令。 (輸入 指示是用來實作 Algol 或 Pascal.) 等語言的巢狀程式

保留指示相當於:

mov esp, ebp
pop ebp

資料轉換

CBW

將位元組 (al) 轉換成 (ax) 。

CWD

將單字 (ax) 轉換為 dword (dxax) 。

CWDE

將單字 (ax) 轉換為 dword (eax) 。

CDQ

將 dword (eax) 轉換為 qword (edxeax) 。

所有轉換都會執行符號延伸模組。

算術和位操作

所有算術和位操作指令都會修改旗標。

演算法

ADD

r1/m、 r2/m/#n

r1/m += r2/m/#n

ADC

r1/m、 r2/m/#n

r1/m += r2/m/#n + carry

SUB

r1/m、 r2/m/#n

r1/m -= r2/m/#n

SBB

r1/m、 r2/m/#n

r1/m -= r2/m/#n + 攜帶

NEG

r1/m

r1/m = -r1/m

公司

r/m

r/m += 1

DEC

r/m

r/m -= 1

Cmp

r1/m、 r2/m/#n

計算 r1/m - r2/m/#n

cmp指令會計算減法,並根據結果設定旗標,但會擲回結果。 其後面通常會接著條件 式跳躍 指示,以測試減法的結果。

MUL

r/m8

斧頭 = * r/m8

MUL

r/m16

dxax ax = * r/m16

MUL

r/m32

edxeax eax * = r/m32

IMUL

r/m8

斧頭 = * r/m8

IMUL

r/m16

dxax ax = * r/m16

IMUL

r/m32

edxeax eax * = r/m32

IMUL

r1r2/m

r1 *= r2/m

IMUL

r1r2/m、#n

r1 = r2/m * #n

不帶正負號和帶正負號的乘法。 乘法之後的旗標狀態為未定義。

Div

r/m8

(ahal) = (axr/m8, ax / % r/m8)

Div

r/m16

(dxax) = dxax / r/m16

Div

r/m32

(edxeax) = edxeax / r/m32

IDIV

r/m8

(ahal) = ax / r/m8

IDIV

r/m16

(dxax) = dxax / r/m16

IDIV

r/m32

(edxeax) = edxeax / r/m32

不帶正負號和帶正負號的除法。 虛擬程式碼說明中的第一個暫存器會接收餘數,而第二個則會收到商數。 如果結果溢位目的地,就會產生除法溢位例外狀況。

未定義除法之後的旗標狀態。

*

SETcc

r/m8

r/m8 設定為 0 或 1

如果條件 cc 為 true,則 8 位值會設定為 1。 否則,8 位值會設定為零。

二進位編碼十進位

除非您正在偵錯以 COBOL 撰寫的程式碼,否則不會看到這些指示。

DAA

加法後的小數調整。

Das

減法後的小數調整。

這些指示會在執行已封裝的二進位編碼小數運算之後調整 al 暫存器。

Aaa

ASCII 會在加法後調整。

Aas

ASCII 會在減法之後調整。

這些指示會在執行解壓縮的二進位編碼小數運算之後調整 al 暫存器。

Aam

ASCII 會在乘法之後調整。

AAD

ASCII 會在除法後調整。

這些指示會在執行解壓縮的二進位編碼小數運算之後調整 alah 暫存器。

AND

r1/m、 r2/m/#n

r1/m = r1/m 和 r2/m/#n

OR

r1/m、 r2/m/#n

r1/m = r1/m 或 r2/m/#n

XOR

r1/m、 r2/m/#n

r1/m = r1/m xor r2/m/#n

NOT

r1/m

r1/m = 位而非 r1/m

*

TEST

r1/m、 r2/m/#n

計算 r1/m 和 r2/m/#n

測試指令會計算邏輯 AND 運算子,並根據結果設定旗標,但會擲回結果。 它通常會接著條件式跳躍指示,以測試邏輯 AND 的結果。

SHL

r1/m、 cl/#n

r1/m << = cl/#n

Shr

r1/m、 cl/#n

r1/m >> = cl/#n零填滿

*

SAR 里亞爾

r1/m、 cl/#n

r1/m >> = cl/#n sign-fill

最後一個位移出的位置會放在攜帶中。

SHLD

r1r2/m、 cl/#n

向左移雙精度浮點數。

r1 左移為 cl/#n,填滿 r2/m 的頂端位。 最後一個位移出的位置會放在攜帶中。

SHRD

r1r2/m、 cl/#n

向右移雙精度浮點數。

cl/#n 向右移r1,填滿r2/m 的底部位。 最後一個位移出的位置會放在攜帶中。

ROL

r1cl/#n

cl/#n向左旋轉r1

Ror

r1cl/#n

cl/#n 向右旋轉r1

RCL

r1cl/#n

cl/#n左旋轉r1/C。

RCR

r1cl/#n

cl/#n 旋轉r1/C。

旋轉就像移動,不同之處在于移出的位會隨著傳入填滿位重新出現。 旋轉指令的 C 語言版本會將攜帶位併入旋轉中。

BT

r1r2/#n

r1的位r2/#n複製到攜帶中。

BTS

r1r2/#n

設定r1的位r2/#n,將先前的值複製到 carry 中。

Btc

r1r2/#n

清除r1的位r2/#n,將先前的值複製到 carry。

控制流程

Jcc

dest

分支條件式。

JMP

dest

直接跳躍。

JMP

r/m

間接跳躍。

CALL

dest

直接呼叫 。

*

CALL

r/m

呼叫間接。

呼叫指令會將傳回位址推送至堆疊,然後跳至目的地。

*

Ret

#n

傳回

重試指令會快顯並跳至堆疊上的傳回位址。 RET指令中的非零#n表示在快顯傳回位址之後,應該將值#n新增至堆疊指標。

如果結果為非零,請遞減 ecx 並跳躍。

LOOPZ

如果結果為非零且已設定zr,則遞減ecx並跳躍。

LOOPNZ

如果結果為非零且zr清楚,請遞減ecx並跳躍。

JECXZ

如果 ecx 為零,則跳躍。

這些指令是 x86 的 CISC 傳統,而且在最近的處理器中,實際上比寫出長路的對等指令慢。

字串操作

MOVST

Tesi 移至 edi。

CMPST

比較esiediT

SCAST

edi掃描T以取得 accT。

LODST

Tesi 載入至 accT。

STOST

從 acc T 儲存Tedi

執行作業之後,來源和目的地暫存器會根據 (向上或向下) 方向旗標的設定,依 sizeof (T) 遞增或遞減。

指令前面可以加上 REP ,以重複 ecx 暫存器所指定的作業次數。

rep mov指令是用來複製記憶體區塊。

rep stos指令可用來使用 accT填滿記憶體區塊。

標誌

LAHF

從旗標載入 ah

SAHF

ah 儲存為旗標。

Stc

設定攜帶。

Clc

清除攜帶。

CMC

補數攜帶。

性病

將方向設定為 向下。

CLD

將方向設定為 向上。

性病

啟用中斷。

CLI

停用中斷。

內嵌的指示

XCHG

r1r/m

交換 r1r/m。

XADD

r1r/m

r1 新增至 r/m,並將原始值放在 r1 中。

CMPXCHG

r1r/m

比較和交換條件式。

cmpxchg指令是下列不可部分完成的版本:

   cmp     accT, r/m
   jz      match
   mov     accT, r/m
   jmp     done
match:
   mov     r/m, r1
done:

雜項

INT

#n

設陷到核心。

綁定

r, m

如果 r 不在範圍內,則設陷。

*

NOP

無作業。

XLATB

al = [ebx + al]

BSWAP

r

在暫存器中交換位元組順序。

以下是 int 指令的特殊案例。

INT

3

偵錯工具中斷點設陷。

INT 3的 opcode 0xCC。 NOP的 opcode 是0x90。

偵錯程式碼時,您可能需要修補一些程式碼。 您可以將違規的位元組取代為 0x90 來執行此動作。

習語

XOR

rr

r = 0

TEST

rr

檢查 r = 0。

*

ADD

rr

r 向左移 1。