跳至內容

X86組合語言/X86架構及暫存器解釋

本頁使用了標題或全文手工轉換
維基教科書,自由的教學讀本

X86架構

[編輯]

x86架構有8個通用暫存器(GPR)、6段暫存器、1個標誌暫存器和指令指標。 64位元的x86有附加的暫存器。

通用暫存器(GPR) - 32位元命名約定

[編輯]

8個GPR是:

  1. 累加器暫存器(AX)。用在算術運算。
  2. 基址暫存器(BX)。作為一個指向資料的指標(在分段模式下,位於段暫存器DS)。
  3. 計數器暫存器(CX)。用於移位/迴圈指令和迴圈。
  4. 資料暫存器(DX)。用在算術運算和I/O操作。
  5. 堆疊指標暫存器(SP)。用於指向堆疊的頂部。
  6. 棧基址指標暫存器(BP)。用於指向堆疊的底部。
  7. 源變址暫存器(SI)。在流操作中用作源的一個指標。
  8. 目標索引暫存器(DI)。用作在流操作中指向目標的指標。

將它們以這樣的順序列出是有原因的:這個順序和堆疊操作中推入棧中的次序相同,我們以後會講到。

所有暫存器都可以在16位元和32位元模式下被存取。在16位元模式下,通過上面的列表中兩個字母的縮寫來確定該暫存器。在32位元模式下,這兩個字母的縮寫名字前有「E」(extended,延伸)。例如,「EAX'是累加器暫存器作為一個32位元的值。

類似地,在64位元的版本,「E」被替換為「R」,所以在64位元版本「EAX'被稱為'RAX'。

暫存器 累加器 計數器 資料 基址 堆疊指標 棧基址指標 源變址 目標索引
64-bit RAX RCX RDX RBX RSP RBP RSI RDI
32-bit EAX ECX EDX EBX ESP EBP ESI EDI
16-bit AX CX DX BX SP BP SI DI
8-bit AH AL CH CL DH DL BH BL

指標暫存器

[編輯]
暫存器別名 暫存器 預設的
區段暫存器
暫存器示意圖
來源索引暫存器 ESI = 32 bits
SI = 16 bits

31 16 15 0
ESI
SI


目的索引暫存器 EDI = 32 bits
DI = 16 bits

31 16 15 0
EDI
DI


堆疊指標暫存器 ESP = 32 bits
SP = 16 bits
SS
31 16 15 0
ESP
SP


基底指標暫存器 EBP = 32 bits
BP = 16 bits

31 16 15 0
EBP
BP


程式指標暫存器 EIP = 32 bits
IP = 16 bits
CS
31 16 15 0
EIP
IP


區段暫存器

[編輯]
暫存器別名 暫存器 暫存器示意圖
程式區段暫存器 CS = 16 bits
15 0
CS


資料區段暫存器 DS = 16 bits
15 0
DS


堆疊區段暫存器 SS = 16 bits
15 0
SS


額外區段暫存器 ES = 16 bits
15 0
ES


額外區段暫存器
(80386以後出現)
FS = 16 bits
15 0
FS


額外區段暫存器
(80386以後出現)
GS = 16 bits
15 0
GS


  • 在真實模式或虛擬86模式時,『區段暫存器』用來擴展定址的範圍由 64 KByte 到 1 MByte 。
  • 在保護模式時,『區段暫存器』將變成『選擇子暫存器』,用為對於程式與記憶體存取權限的控管的索引。

大多現代作業系統(如FreeBSD、Linux或Windows)的大多應用程式使用將幾乎所有段暫存器都指向同一位置(並使用頁面),從而便捷地停用這些暫存器。

EFLAGS暫存器

[編輯]

EFLAGS暫存器,在台灣也稱為「旗標暫存器」,是用一系列表示布林值的位來儲存操作的結果和處理器狀態的32位元暫存器。

這些位的名稱是:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
0 0 0 0 0 0 0 0 0 0 ID VIP VIF AC VM RF
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
  • AF:輔助進位旗標
  • CF:進位旗標
  • OF:溢位旗標
  • SF:符號(負號)旗標
  • PF:奇偶旗標
  • ZF:零值旗標
  • DF:方向旗標
  • IF:中斷旗標
  • TF:單步旗標

指令指標

[編輯]

如果沒有建立過分支,EIP暫存器包含下一條將要執行的指令的位址。

EIP只能在一個call指令後從堆疊讀出。

記憶體中字的儲存

[編輯]

x86架構是小端序的,即多位元組數值的最低位位元組首先寫入。(這隻針對位元組的排序,不對於位。)

所以x86上的32位元數值B3B2B1B016在記憶體中會表示為:

小端序表示法
B0 B1 B2 B3

例如,32位元的雙字0x1BA583D4 (0x表示十六進制)在記憶體中寫為:

小端序例子
D4 83 A5 1B

執行記憶體轉儲時會把其視為0xD4 0x83 0xA5 0x1B

二補數表示

[編輯]

二補數是以二進制表示負整數的標準方式。符號是由對所有的位取反並加一來改變的。

二補數例子
開始: 0001
取反: 1110
加一: 1111

0001表示十進制的1

1111表示十進制的-1

尋址方式

[編輯]

尋址方式給出了運算元給出的方式。

暫存器尋址
(運算元位址R所在位址欄位)
mov ax, bx  ; moves contents of register bx into ax
Immediate
(實際位址所在欄位)
mov ax, 1   ; moves value of 1 into register ax

mov ax, 010Ch ; moves value of 0x010C into register ax
直接記憶體尋址
(運算元位址所在位址欄位)
.data
my_var dw 0abcdh ; my_var = 0xabcd
.code
mov ax, my_var ; copy my_var content in ax (ax=0xabcd)
mov ax, [my_var] ; copy the content of memory that my_var pointed at to ax
直接偏移尋址
(通過算數改變位址)
byte_tbl db 12,15,16,22,..... ; Table of bytes
mov al,[byte_tbl+2]
mov al,byte_tbl[2] ; same as the former
暫存器間接尋址
(field points to a register that contains the operand address)
mov ax,[di]
The registers used for indirect addressing are BX, BP, SI, DI
基址
mov ax,[bx + di]
例如,如果我們是在討論一個陣列,BX包含陣列的起始位址和DI包含陣列的索引。
基址變址:
mov ax,[bx + di + 10]

[編輯]

棧是一個後進先出(LIFO)的資料結構,資料被壓到棧頂並會以逆序出棧。

 mov ax, 006Ah
 mov bx, F79Ah
 mov cx, 1124h
 push ax

你將AX中的數值壓入棧頂, 它現在的數值為$006A。

push bx

你對BX中的數值做相同的操作,現在棧中有$006A和$F79A。

push cx

如今棧中有$006A、$F79A和$1124。

call do_stuff

Do some stuff. The function is not forced to save the registers it uses, hence us saving them.

pop cx

取出最後一個壓入棧中的元素到CX,即$1124;現在棧中有$006A和$F79A.

pop bx

取出最後一個壓入棧中的元素到BX,即$F79A;現在棧中只有$006A。

pop ax

取出最後一個壓入棧中的元素到AX,即$006A;現在棧是空的。

棧通常用來向函式或過程傳遞參數,並用來記錄call指令使用時的控制流。棧的另一個常見的用途是臨時儲存暫存器。

CPU的工作模式

[編輯]

真實模式 (Real mode)

[編輯]
  • 參照: 真實模式 (維基百科)
  • 特性:
    • 記憶體定址限制: 1 MByte (每一個記憶體區段限定 64 Kbyte, 使用區段暫存器擴展可存取的記憶體範圍到 1 MByte)
    • 暫存器與資料操作寬度: 16 bits 與 8 bits

保護模式 (Protected Mode)

[編輯]

16位元保護模式 (16-bit protected mode)

[編輯]
  • 特性:
    • 記憶體定址限制: 16 MByte
    • 暫存器與資料操作寬度: 16 bits 與 8 bits

32位元保護模式 (32-bit protected mode)

[編輯]
  • 特性:
    • 記憶體定址限制: 4 GByte
    • 暫存器與資料操作寬度: 32 bits 與 16 bits 與 8 bits

虛擬86模式

[編輯]