顯示具有 x86 Architecture 標籤的文章。 顯示所有文章
顯示具有 x86 Architecture 標籤的文章。 顯示所有文章

2011年4月21日 星期四

IA-32處理器 - 基本操作模式

IA-32處理器有三個基本操作模式
- Protected Mode。(保護模式)
- Real-address Mode。(實體位址模式)
- System Mangement Mode; SMM。(系統管理模式)

另一種模式是 Vitual-8086 Mode (虛擬8086模式),它是保護模式的特殊情況。
—>在保護模式下的同時,處理器還可以在安全的多工環境中,直接執行 Real-address Mode 軟體,例如像是 MS-DOS 程式。換句話說,就算有一個 MS-DOS 程式當機,或者此程式要將資料寫入系統記憶體區域,也不會影響其他正在執行的程式。 Windows XP 可以同時執行多個各別的 Vitual-8086 session (對話)。
* 每個程式都可以擁有自己的 1 MB 記憶體區域。

(1) Protected Mode:
Protected Mode 是處理器最原始的狀態,在這種模式下,所有指令與功能都是可以使用的。此時程式會被分配得到各自的記憶體空間,此記憶體空間稱為 segments (區段),且處理器會防止程式referrence (參考) 被指派的 segments (區段) 以外的記憶體。

(2) Real-address Mode:
* Real-address Mode 可以實作出 Intel 8086 處理器的程式執行環境,而且所實作的環境還具有一些額外的功能,例如切換到其他模式的功能。Real-address Mode 可以在 Windows 98 中使用,而且可以用來執行一個須要直接存取系統記憶體或硬體裝置的 MS-DOS 程式。在Real-address Mode 下執行的程式,可能導致作業系統當機(無法再對使用者所下達的命令加以反應)。
* Real-address Mode 的程式,最多僅能存取 1 MB 的記憶體範圍

(3) Ssytem Management Mode; SMM:
SMM 提供作業系統額外的機制,用於增加像電源管理和系統安全等功能。電腦製造商為了特定的系統設定,會使用自訂的處理器,而且這些廠商通常也會實作上述的額外功能。

基本的程式執行暫存器

Register(暫存器):
Register是在CPU內部的高速儲存空間,它是設計用來以遠高於一般記憶體的速度進行存取的動作。例如,當處理中的迴圈必須在速度上有最佳化效果時,迴圈計數器會儲存於暫存器而不是在變數中。
Purpose
Although the main registers (with the exception of the instruction pointer) are "general-purpose" and can be used for anything, it was envisioned that they be used for the following purposes:
  • AX/EAX/RAX: accumulator
  • BX/EBX/RBX: base index (ex: arrays)
  • CX/ECX/RCX: counter
  • DX/EDX/RDX: data/general
  • SI/ESI/RSI: "source index" for string operations.
  • DI/EDI/RDI: "destination index" for string operations.
  • SP/ESP/RSP: stack pointer for top address of the stack.
  • BP/EBP/RBP: stack base pointer for holding the address of the current stack frame.
  • IP/EIP/RIP: instruction pointer. Holds the program counter, the current instruction address.
    引用來源:http://en.wikipedia.org/wiki/X86#x86_registers

Basic program execution registers(基本的程式執行暫存器):
- 8 個 General-Purpose Registers (通用暫存器)   
  EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI
- 6個 Segment Registers (區段暫存器)   
  CS, SS, DS, ES, FS, GS
- 1個 EFLAGS (用於儲存處理器狀態旗標的暫存器)
- 1個 EIP, Instruction Pointer (指令指標)


EBP, Base Pointer (基底指標),高階語言經常使用 EBP 來參照堆疊中的函數參數和局部變數 (local variable)。除非有高超的程式設計能否則不應將它用於平常的算術運算或資料搬移。因此,它通常稱為 Extended Frame Pointer Register (延伸框架指標暫存器)。

EAX, Extended Accumulator (延伸累加器),在執行乘法與法指令時,會自動使用 EAX 暫存器。
EBX, Base Index (ex: arrays)
ECX, Counter, CPU 會自動使用 ECX 當做迴圈計數器。
EDX, Data / General
ESP, Stack Pointer(堆疊指標), ESP 會用於定址在 Stack (堆疊)中的資料。
ESI, Extended Source Index (延伸來源索引)
EDI, Extended Destination Index (延伸目的索引)
ESI與EDI常用在高速的記憶體轉移指令。

Instruction Pointer(指令指標): 暫存器儲存著下一個即將執行的指令位址,有些特定的機器指令可以更動 EIP ,讓程式分支到新的位置去執行。

Segment Registers(區段暫存器): 在Real-Address Mode (實體位址模式)下, Segment Registers 用以定義 Segment 的 Base Address(基底位址), Segment 是預先指定的記憶體區域。在 Protected Mode 下, Segment Registers儲存的是”用於指向區段描述符表的指標”。有些 Segment 儲存的是程式指令(Code;程式碼),其他的 Segment 儲存的則是變數(Data;資料),另一種稱為 Stack Segment (堆疊區段)的區段,儲存的是局部變數以及函數參數。
CS, Code Segment
SS, Stack Segment
DS, Data Segment
ES, Extra Segment
FS, Flag Segment
GS, Global Segment
3.1-2 節區暫存器與指標暫存器


節區暫存器(segment register)又稱為段暫存器,在80386 CPU以下的規劃分別有CS、SS、DS、ES四個16位元的暫存器,386以後加入FS、GS兩個。規劃這些暫存器的主要目的是希望將主記憶體分成好幾個管理區域,分別可以指定給程式及不同目的的資料存放,例如CS就是規劃來指定給指令碼存放的區段,所以稱為指令段(code segment)暫存器,而SS為堆疊段(stack segment)暫存器,DS、ES分別為資料段(data segment) 及額外段(extra segment)暫存器,以及80386以後的CPU所加入的FS、GS分別為旗號段(flag segment) 及總體段(global segment)暫存器,這些段暫存器都可定義出特定資料存取的區段。

節區暫存器只關係著區段的粗略位址,80X86 CPU的實際位址必須仰賴節區暫存器有效位址共同的計算來決定(請參照圖3-1及圖3-4),計算的方法為:

實際位址 = 節區暫存器位址 × 16 + 有效位址


每一種節區暫存器在特定目的下必須配合一個特定的指標暫存器一起使用,而指標暫存器的內容往往就是有效位址的一部份或全部(請參考下一節定址法),例如指令段(CS)暫存器必須配合指令指標(IP)暫存器定義出指令的有效位址,因此:

指令實際位址 = 指令節區暫存器 × 16 + 指令指標暫存器

由於指令實際位址都由CPU的程式計數器(PC)來決定,因此80×86CPU的PC = CS × 16 + IP。此處的CS × 16,對於二進碼而言,只需將CS左移四個位元,再補上四個0即可。

另外,堆疊段(SS)暫存器也沒有其他的選擇,必須配合堆疊指標(SP)暫存器一起使用定義出堆疊資料存放的實際位址。而字串處理(搬移、搜尋、比較)指令中,字串來源的位址被定義在資料段(DS)暫存器與來源索引(SI)暫存器中,處理後存放的目標位址則被定義在額外段(ES)暫存器與目標索引(DI)暫存器中。至於基底指標暫存器(BP)與堆疊段(SS)暫存器合用時,才可以存取堆疊段的資料。以上這些段暫存器與其可配合的指標暫存器,簡記於下:

CS:IP        指令段:指令指標
SS:SP       堆疊段:堆疊指標
DS:SI        資料段:來源索引
ES:DI        額外段:目標索引
SS:BP       堆疊段:基底指標

在眾多型態的指標暫存器當中,它們的儲存值都是可以被指令所更改或讀取的,唯一不能被使用者更改或讀取者就是指令指標(IP)暫存器,它僅隨指令的進行自動指向指令的提取位址,所以有些書籍是將它歸類在特殊暫存器當中。

例3-1 某程式碼置於記憶體AC00h的指令段,80×86CPU目前正要提取有效位址為1234h的指令操作碼,請問此操作碼在記憶體中的實際位址。

解: CS=AC00h,IP=1234h,

則 實際位址= CS×16+IP=AC000h +1234h =AD234h

X86 定址模式 Addressing Mode 大全

引用來源:Frank's 資訊科技潮流站

Immediate Addressing Mode

這種表示法是最簡單的,完全不用去找位址,就直接把值給出來,給電腦去玩 (當然這樣程式比較沒有彈性)

例如 MOV AX,12h

就是直接把12這個值,丟到暫存器AX中

Register Operand Addressing Mode

這種表示法也沒有什麼位址可言,因為所指定的就是那個Register裡面的內容

例如 MOV AX,BX

就是純粹把 BX 裡面的資料移到 AX 中

Register Indirect Addressing Mode

這種表示法,就是把暫存器裡面的資料,變成一個位址來想

例如本來 BX 裡面放了 0123 這筆資料

用了 Register Indirect之後,就變成是指定 0123 這個位址

例如 MOV CX,[BX]

就是把記憶體位址 (DS)0 + BX 裡面的資料,移到 CX

至於為什麼是 (DS)0+BX..

based.GIF

因為,如果我們在組合語言程式裡面要求 BX (123) 位址的資料的時候

其實找到的是 (DS)0 + BX 位址的資料

因為上述的 BX  只是 Logical Address ,是寫程式方便用的

而 (DS)0 + BX 才是 Physical Address 才是實體真正操作的位址

PA = (DS)0 或 (CS)0 或 (SS)0 或 (ES)0  +  AX 或 BX 或 CX 或 DX


Based Addressing Mode

rbased.GIF

同上面那種方法,只是後面加了一個offset

寫成組合語言就像這樣

MOV CX,[BX]+0156h

而[BX]+0156h的實體記憶體位址是

(DS)0 + BX + 156

PA = (DS)0 或 (CS)0 或 (SS)0 或 (ES)0  +  AX 或 BX 或 CX 或 DX + offset


Based-Indexed Addressing Mode

basedindex.GIF

承上,只不過多了一個index值

組合語言寫法例 MOV CX,[BX+DI]+0156h

PA = (DS)0 或 (CS)0 或 (SS)0 或 (ES)0  +  AX 或 BX 或 CX 或 DX + SI 或 DI + offset

引用來源:X86 定址模式 Addressing Mode 大全

X86 CPU 暫存器 Register 大全

引用來源:Frank's 資訊科技潮流站

這是 Intel X86 架構下的 CPU 的所有暫存器 ( Register )

8088.JPG

首先,所有暫存器(Register)都只是一個長度為 16bit = 2byte = 1word 長度的一個空間

memblock.GIF

裡面存放 二進位 (Binary) 數字 , 負責記錄一筆數字資料 (最大值為65535)


01.JPG

CS = Code Segment,是指一個程式是從哪個位址開始

例如從000A,CS裡面就會記載000A

CS 通常會搭配 IP 使用,程式目前跑到的位置,就由 (CS)0 + IP 決定

如果跑到程式第一行,IP就是0,如果跑到第三行,IP就是2

那麼在實體記憶體實際上的位址就分別是 000A0 和 000A2

DS = Data Segment ,是指資料從記憶體的哪個位址開始

DS 通常會搭配其他暫存器使用,例如 BX、CX 等等

假如你在組合語言中要求使用 [BX] 這個位址的資料 ,而 BX = 3

那麼你其實找到的是在記憶體位置 (DS)0 + BX 位址的資料 ,即是000A3這個位址的資料   (假如DS=000A)

還是看不懂的,請來看看這篇吧~

SS = Stack Segment

這是表示你的堆疊( Stack )的底部位置

通常會搭配 SP 使用

SS + SP 就是目前 Stack 堆疊頂端的位址  (TOS,Top of Stack )

如果把一筆資料送入堆疊 ( PUSH ) ,那SP就會 -2

反之,若把一筆資料從堆疊中拿出 ( POP ) , 那SP就會 +2

(這裡的加減號並沒有打錯,如果有疑惑,請看這一篇)

ES = Extra Segment

這名符其實,是額外的Segment,大概可以靈活運用

不過若要賦值給它,則要注意

MOV ES,3H -> 這樣是錯的

MOV DX,3H
MOV ES,DX -> 這樣才可以


SI / DI 則分別代表

Source Index 和 Destination Index

(source=來源/Destination=目標)

舉個例子來講

組合語言指令中,MOV AX,BX

是將 BX 的資料複製到 AX

那麼,SI就要指向BX,DI就要指向AX


接下來的AX,BX,CX,DX

就是 General Purpose Registers (通用功能暫存器)

值得注意的是,這四個暫存器可以分成 High Bits 和 Low Bits 分別使用

例如 AX 可以拆成 AH 和 AL

memblock.GIF

當然,也可以自己就是一個暫存器使用

memblock.GIF

一般來說這四個暫存器可以隨時使用

但是這四個暫存器各自有特殊的功用

AX =Accumulator

例如在做乘法/除法的時候,AX暫存器就很特別

例如 MUL CX 這個指令

其實是把 CX 乘以 AX 的結果 放入 AX 之中

另外,發出I/O指令,也是由AX記載的內容決定要發出哪個指令

BX = Based

例如 XLAT指令,就是把  (DS)0 + AL + BX 的記憶體位址內容 丟到 AL 中

CX = Counter

Counter顧名思義是計數器,LOOP系列指令會對它產生影響

讓我們來看看以下這段程式碼

           MOV CX,5
AGAIN: NOP
           LOOPNZ AGAIN

( LOOPNZ = 若CX不為0就繼續 )

LOOPNZ這個指令是針對CX做變化,每跑到這個指令一次,就會把CX減去1
那麼,跑了5次之後,CX終於會扣到變成0,LOOP就結束

DX = Data

做一般資料傳輸用途。


Status Register (FLAGS)

這也是一個 16bit = 2byte = 1word 長度的 register

剛好每一個 bit 能放的就是 0 或 1

如果放 0 ,那個狀態,就是沒有 (reset)

放 1 就是有 (set)

以下是每一個 bit 分別代表的 flag (灰色代表保留未使用的)

flag.JPG

以下一一介紹

CF = Carry Flag = 進位

如果指令的運作中,使得資料產生了Carry,那麼CF就會變成 1 (set),反之就是 0 (reset)

例如 1000000000000000 + 1000000000000000 = 1 0000000000000000 

(注意,結果超出 1 位,紅色的1 已經跑到那筆資料的外面了,而那個 1 就是 carry)

carry.GIF

如果還是不太清楚的話

你只要把Carry當作是 16th bit 就可以了  (就是最左邊的那格,再往左延伸出去一格,變成從左往右數來第17格)

把整個記憶體位址當作有17個bit 去運算,如果 16th bit 是 1 ,那carry就是1,反之就是 0

ssss.GIF

(這也是為什麼發生進位和借位時,carry都是1)


PF = Parity Flag

看看計算的結果之中,存在幾個位數的「1」

如果是偶數個的話,PF=1,反之PF=0

舉例

00001010 => Parity Bit 為 1 (set)

00001000 => Parity Bit 為 0 (reset)


AF = Auxiliary Flag

相似CF,但這裡是以四個Bit為一組來做判斷的 ( 不過實際上只有偵測 4th bit 有沒有 進位carry 或 借位borrow )

auxx.GIF

像這張圖的情況,AF=1

這種四個bit一組的情況,就是在BCD的情況常用。


ZF = Zero Flag

如果計算出來的結果是 0 ,那麼 ZF=1 ,反之ZF=0

SF = Sign Flag

如果計算出來的結果有負號,那麼SF=1,反之SF=0

TF = Trap Flag

如果TF設定成1,那麼電腦的程式會逐行執行 (用於除錯等用途)

IF = Interrupt Flag

決定該CPU是否可以接受從外部發出的中斷請求

DF = Direction Flag

決定字串的讀取是由「高位讀到低位」(small endian)還是「低位讀到高位」(big endian)

X86的設計,預設是small endian

例如 在small endian

位址 00 資料為 34 ,位址 01 資料為 12

那麼這個字串讀起來就是 1234

(DF=0時,就是small endian)

OF = Overflow Flag

如果資料計算結果,產生溢位(overflow),OF=1,反之OF=0

OF = Overflow Flag

X86 CPU 堆疊概念

引用來源:Frank's 資訊科技潮流站

stack.GIF

這是 X86 CPU 的堆疊概念

不過很詭異的是,他的堆疊方法剛好是「倒過來的」

Stack的底端在最頭頂的Address,Stack的最上層居然是往下數的

這也就是為什麼

每增加一筆資料 (PUSH) 到堆疊中, SP反而要 減 2

每減少一筆資料 (POP ) SP 是 加 2

(是 2 而不是 1 的原因,是因為stack每一層都占2bytes)

另外,這個Stack的大小是固定的

就只有 FFFE 這麼大而已 (約64KB)