X86組合語言/X86架構及寄存器解釋
X86架構
編輯x86架構有8個通用寄存器(GPR)、6段寄存器、1個標誌寄存器和指令指針。 64位的x86有附加的寄存器。
通用寄存器(GPR) - 32位命名約定
編輯8個GPR是:
- 累加器寄存器(AX)。用在算術運算。
- 基址寄存器(BX)。作為一個指向數據的指針(在分段模式下,位於段寄存器DS)。
- 計數器寄存器(CX)。用於移位/循環指令和循環。
- 數據寄存器(DX)。用在算術運算和I/O操作。
- 堆棧指針寄存器(SP)。用於指向堆棧的頂部。
- 棧基址指針寄存器(BP)。用於指向堆棧的底部。
- 源變址寄存器(SI)。在流操作中用作源的一個指針。
- 目標索引寄存器(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 |
| |||||||||
目的索引暫存器 | EDI = 32 bits DI = 16 bits |
| |||||||||
堆疊指標暫存器 | ESP = 32 bits SP = 16 bits |
SS |
| ||||||||
基底指標暫存器 | EBP = 32 bits BP = 16 bits |
| |||||||||
程式指標暫存器 | EIP = 32 bits IP = 16 bits |
CS |
|
區段暫存器
編輯暫存器別名 | 暫存器 | 暫存器示意圖 | |||
程式區段暫存器 | CS = 16 bits |
| |||
資料區段暫存器 | DS = 16 bits |
| |||
堆疊區段暫存器 | SS = 16 bits |
| |||
額外區段暫存器 | ES = 16 bits |
| |||
額外區段暫存器 (80386以後出現) |
FS = 16 bits |
| |||
額外區段暫存器 (80386以後出現) |
GS = 16 bits |
|
- 在真實模式或虛擬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