X86寄存器
·x86寄存器分類:
8個通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
1個標志寄存器:EFLAGS
6個段寄存器:CS、DS、ES、FS、GS、SS
5個控制寄存器:CR0、CR1、CR2、CR3、CR4
8個調試寄存器:DR0、DR1、DR2、DR3、DR4、DR5、DR6、DR7
4個系統地址寄存器:GDTR、IDTR、LDTR、TR
其他寄存器:EIP、TSC等。
一. 通用寄存器
32位 |
16位 |
8位 |
EAX |
AX |
AH、AL |
EBX |
BX |
BH、BL |
ECX |
CX |
CH、CL |
EDX |
DX |
DH、DL |
ESI |
SI |
|
EDI |
DI |
|
ESP |
SP |
|
EBP |
BP |
|
如上表,有8個通用寄存器,且其中的16位寄存器並沒有專門分配硬件,而是與32位寄存器通用來實現。在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不僅可傳送數據、暫存數據保存算術邏輯運算結果,而且也可作為指針寄存器,所以,這些32位寄存器相比16位CPU中的AX、BX、CX、DX更具有通用性。
EAX:累加器(Accumulator), 它的低16位即是AX,而AX又可分為高8位AH和低8位AL。EAX是很多加法乘法的缺省寄存器,存放函數的返回值,用累加器進行的操作可能需要更少時間,在80386及其以上的微處理器中可以用來存放存儲單元的偏移地址。AX寄存器是算術運算的主要寄存器。
EBX:基地址寄存器(Base Register), 它的低16位即是BX,而BX又可分為高8位BH和低8位BL。主要用於在內存尋址時存放基地址。
ECX:計數寄存器(Count Register),它的低16位即是CX,而CX又可分為高8位CH和低8位CL。在循環和字符串操作時,要用它來控制循環次數;在位操作 中,當移多位時,要用CL來指明移位的位數;是重復(REP)前綴指令和LOOP指令的內定計數器。
EDX:數據寄存器(Data Register),它的低16位即是DX,而DX又可分為高8位DH和低8位DL。在進行乘、除運算時,它可作為默認的操作數參與運算,也可用於存放I/O的端口地址;且總是被用來放整數除法產生的余數。
ESI/EDI:分別叫做源/目標索引寄存器(Source/Destination Index Register),它們的低16位分別是SI、DI。它們主要用於存放存儲單元在段內的偏移量,用它們可實現多種存儲器操作數的尋址方式,為以不同的地址形式訪問存儲單元提供方便。在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目標串。此外,它們又作為通用寄存器可以進行任意的常規的操作,如加減移位或普通的內存間接尋址。
EBP/BSP:分別是基址針寄存器(Base Pointer Register)/堆棧指針寄存器(Stack Pointer Register),低16位是BP、SP,其內存分別放着一個指針,該指針永遠指向系統棧最上面一個棧幀的棧頂/底部。主要用於存放堆棧內存儲單元的偏移量,用它們可實現多種存儲器操作數的尋址方式,為以不同的地址形式訪問存儲單元提供方便。指針寄存器不可分割成8位寄存器。作為通用寄存器,也可存儲算術邏輯運算的操作數和運算結果。並且規定:BP為基指針(Base Pointer)寄存器,用它可直接存取堆棧中的數據;SP為堆棧指針(Stack Pointer)寄存器,用它只可訪問棧頂。在32位平台上,ESP每次減少4字節。EBP最經常被用作高級語言函數調用的"框架指針"(frame pointer),EBP 構成了函數的一個框架,在C++反匯編中EBP通常是局部變量、傳進來的參數。這里要注意在intel系統中棧是向下生長的(棧越擴大其值越小,堆恰好相反)。在通常情況下ESP是可變的,隨着棧的生長而逐漸變小,而ESB寄存器是固定的,只有當函數的調用后,發生入棧操作而改變,在函數執行結束之后需要還原。
二.狀態寄存器:
EFLAGS屬於狀態寄存器,它們對程序地執行至關重要。
EFLAGS:主要用於提供程序的狀態及進行相應的控制。32位的EFLAGS寄存器包含一組狀態標志、系統標志以及一個控制標志。在x86處理器初始化之后,EFLAGS寄存器的狀態值為0000 0002H。第1、3、5、15以及22到31位均被保留,這個寄存器中的有些標志通過使用特殊的通用指令可以直接被修改,但並沒有指令能夠檢查或者修改整個寄存器。通過使用LAHF/SAHF/PUSHF/POPF/POPFD等指令,可以將EFLAGS寄存器的標志位成組移到程序棧或EAX寄存器,或者從這些設施中將操作后的結果保存到EFLAGS寄存器中。在EFLAGS寄存器的內容被傳送到棧或是EAX寄存器后,可以通過位操作指令(BT,BTS, BTR, BTC)檢查或修改這些標志位。當調用中斷或異常處理程序時,處理器將在程序棧上自動保存EFLAGS的狀態值。若在中斷或異常處理時發生任務切換,那么EFLAGS寄存器的狀態將被保存在TSS中,注意是將要被掛起的本次任務的狀態。
1、狀態標志(Status Flags)
EFLAGS寄存器的狀態標志(0、2、4、6、7以及11位)是指示算術指令(如ADD, SUB, MUL以及DIV指令)的結果,這些狀態標志的作用如下:
CF(bit 0) [Carry flag] 若算術操作產生的結果在最高有效位(most-significant bit)發生進位或借位則將其置1,反之清零。這個標志指示無符號整型運算的溢出狀態,這個標志同樣在多倍精度運算(multiple-precision arithmetic)中使用。
PF(bit 2) [Parity flag] 如果結果的最低有效字節(least-significant byte)包含偶數個1位則該位置1,否則清零。
AF(bit 4) [Adjust flag] 如果算術操作在結果的第3位發生進位或借位則將該標志置1,否則清零。這個標志在BCD(binary-code decimal)算術運算中被使用。
ZF(bit 6) [Zero flag] 若結果為0則將其置1,反之清零。
SF(bit 7) [Sign flag] 該標志被設置為有符號整型的最高有效位。(0指示結果為正,反之則為負)
OF(bit 11) [Overflow flag] 如果整型結果是較大的正數或較小的負數,並且無法匹配目的操作數時將該位置1,反之清零。這個標志為帶符號整型運算指示溢出狀態。
在這些狀態標志中,只有CF標志能夠通過使用STC, CLC以及CMC指令被直接修改,或者通過位指令(BT, BTS, BTR以及BTC)將指定的位拷貝至CF標志中。
這些狀態標志允許單個的算術操作產生三種不同數據類型的結果:無符號整型,有符號整型以及BCD整型。如果把該結果當做無符號整型,那么CF標志指示越界(out-of-range)狀態——即進位或借位,如果被當做有符號整型,則OF標志指示進位或借位,若作為BCD數,那么AF標志指示進位或借位。SF標志指示有符號整數的符號位,ZF指示結果為零。此外在執行多倍精度算術運算時,CF標志用來將一次運算過程中帶進位的加法(ADC)或帶借位的減法(SBB)產生的進位或借位傳遞到下一次運算過程中。
2、控制標志(DF flag)
DF(bit10)[Direction flag]控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)。設置DF標志使得串指令自動遞減(從高地址向低地址方向處理字符串),清除該標志則使得串指令自動遞增。STD以及CLD指令分別用於設置以及清除DF標志。
3、系統標志以及IOPL域(System Flags and IOPL Field)
EFLAGS寄存器中的這部分標志用於控制操作系統或是執行操作,它們不允許被應用程序所修改。這些標志的作用如下:
TF(bit 8) [Trap flag]將該位設置為1以允許單步調試模式,清零則禁用該模式。
IF(bit 9)[Interrupt enable flag]該標志用於控制處理器對可屏蔽中斷請求(maskable interrupt requests)的響應。置1以響應可屏蔽中斷,反之則禁止可屏蔽中斷。
IOPL(bits 12 and 13) [I/O privilege level field]指示當前運行任務的I/O特權級(I/O privilege level),正在運行任務的當前特權級(CPL)必須小於或等於I/O特權級才能允許訪問I/O地址空間。這個域只能在CPL為0時才能通過POPF以及IRET指令修改。
NT(bit 14) [Nested task flag]這個標志控制中斷鏈和被調用任務。若當前任務與前一個執行任務相關則置1,反之則清零。
RF(bit 16) [Resume flag]控制處理器對調試異常的響應。
VM(bit 17) [Virtual-8086 mode flag]置1以允許虛擬8086模式,清除則返回保護模式。
AC(bit 18) [Alignment check flag]該標志以及在CR0寄存器中的AM位置1時將允許內存引用的對齊檢查,以上兩個標志中至少有一個被清零則禁用對齊檢查。
VIF(bit 19) [Virtual interrupt flag]該標志是IF標志的虛擬鏡像(Virtual image),與VIP標志結合起來使用。使用這個標志以及VIP標志,並設置CR4控制寄存器中的VME標志就可以允許虛擬模式擴展(virtual mode extensions)
VIP(bit 20) [Virtual interrupt pending flag]該位置1以指示一個中斷正在被掛起,當沒有中斷掛起時該位清零。與VIF標志結合使用。
ID(bit 21) [Identification flag]程序能夠設置或清除這個標志指示了處理器對CPUID指令的支持。
三.段寄存器:
段寄存器是根據內存分段的管理模式而設置的。內存單元的物理地址由段寄存器的值和一個偏移量組合而成的,這樣可用兩個較少位數的值組合成一個可訪問較大物理空間的內存地址,x86的段寄存器有6個----CS/DS/ES/SS/FS/GS,均為16位。
DS:CS段寄存器包含代碼段的段選擇符,代碼段保存正在執行的指令。處理器從代碼段讀取指令時,使用有CS寄存器中的段選擇符與EIP寄存器聯合構成的邏輯地址。EIP保存要執行的下一條指令在代碼段中的偏移量。CS寄存器不能有應用程序顯式地的加載。相反,可以通過某些指令或處理器內部操作隱式地加載。這些指令/內部操作,例如過程調用,中斷處理,或者任務切換,用於改變程序的執行流,從而導致更新CS寄存器。
DS/ES/FS/GS:這四個寄存器指向四個數據段。多個數據段的存在允許高效地且安全地訪問不同的數據結構類型。例如,可以創建如下的四個數據段:第一個數據段保存當前程序模塊的數據結構,第二個數據段保存更高級別程序模塊導出的數據,第三個數據段保存動態創建的數據結構,最后一個數據段保存另一個程序共享出來的數據。要想訪問更多的數據段,應用程序必須按需將數據段對應的段選擇符加載到DS/ES/FS/GS寄存器中的其中一個當中。
SS:SS寄存器包含棧段的段選擇符,這里棧段用於存儲程序/任務/當前正在執行的處理器程序的棧幀。所有的棧操作都使用SS棧段寄存器來定位棧段。與CS代碼段寄存器不同,SS寄存器可以顯式地加載,這樣就允許應用程序建立多個棧段,並在這些段間切換。
四.控制寄存器
X86提供了控制寄存器,來決定CPU的操作模式和當前執行的任務的屬性。有4個控制寄存器:CR0、CR1、CR2、CR3;均為32位,用於控制和確定處理器的操作模式以及當前執行任務的特性,保存全局性和任務無關的機器狀態。這幾個寄存器是與分頁機制密切相關的,因此,在進程管理及虛擬內存管理中會涉及到這幾個寄存器。對控制寄存器的讀寫是通過mov指令來實現。
CR0:包含6個預定義標志,分為協處理器控制位和保護控制位兩類:
1. CR0中協處理器控制位:
CR0的4個位:擴展類型位ET、任務切換位TS、仿真位EM和數學存在位MP用於控制80x86浮點(數學)協處理器的操作。CR0的ET位(標志)用於選擇與協處理器進行通信所使用的協議,即指明系統中使用的是80387還是80287協處理器。TS、MP和EM位用於確定浮點指令或WAIT指令是否應該產生一個設備不存在(Device Not Available,DNA)異常。這個異常可用來僅為使用浮點運算的任務保存和恢復浮點寄存器。對於沒有使用浮點運算的任務,這樣做可以加快它們之間的切換操作。
(1)ET:CR0的位4是擴展類型(Extension Type)標志。當該標志為1時,表示指明系統中有80387協處理器,並使用32位協處理器協議。ET=0指明使用80287協處理器。如果仿真位EM=1,則該位將被忽略。在處理器復位操作時,ET位會被初始化指明系統中使用的協處理器類型。如果系統中有80387,則ET被設置成1,否則若有一個80287或者沒有協處理器,則ET被設置成0。
(2)TS:CR0的位3是任務已切換(Task Switched)標志。該標志用於推遲保存任務切換時的協處理器內容,直到新任務開始實際執行協處理器指令。處理器在每次任務切換時都會設置該標志,並且在執行協處理器指令時測試該標志。如果設置了TS標志並且CR0的EM標志為0,那么在執行任何協處理器指令之前會產生一個設備不存在異常。如果設置了TS標志但沒有設置CR0的MP和EM標志,那么在執行協處理器指令WAIT/FWAIT之前不會產生設備不存在異常。如果設置了EM標志,那么TS標志對協處理器指令的執行無影響。在任務切換時,處理器並不自動保存協處理器的上下文,而是會設置TS標志。這個標志會使得處理器在執行新任務指令流的任何時候遇到一條協處理器指令時產生設備不存在異常。設備不存在異常的處理程序可使用CLTS指令清除TS標志,並且保存協處理器的上下文。如果任務從沒有使用過協處理器,那么相應協處理器上下文就不用保存。
(3)EM:CR0的位2是仿真(EMulation)標志。當該位設置時,表示處理器沒有內部或外部協處理器,執行協處理器指令時會引起設備不存在異常;當清除時,表示系統有協處理器。設置這個標志可以迫使所有浮點指令使用軟件來模擬。
(4)MP:CR0的位1是監控協處理器(Monitor coProcessor或Math Present)標志。用於控制WAIT/FWAIT指令與TS標志的交互作用。如果MP=1、TS=1,那么執行WAIT指令將產生一個設備不存在異常;如果MP=0,則TS標志不會影響WAIT的執行。
2. CR0中保護控制位:
(1)PE:CR0的位0是啟用保護(Protection Enable)標志。當設置該位時即開啟了保護模式;當復位時即進入實地址模式。這個標志僅開啟段級保護,而並沒有啟用分頁機制。若要啟用分頁機制,那么PE和PG標志都要置位。
(2)PG:CR0的位31是分頁(Paging)標志。當設置該位時即開啟了分頁機制;當復位時則禁止分頁機制,此時所有線性地址等同於物理地址。在開啟這個標志之前必須已經或者同時開啟PE標志。即若要啟用分頁機制,那么PE和PG標志都要置位。
下表列出了通過使用PE和PG位選擇的處理器工作方式。由於只有在保護方式下才可啟用分頁機制,所以盡管兩個位分別為0和1共可以有四種組合,但只有三種組合方式有效。PE=0且PG=1是無效組合,因此,用PG為1且PE為0的值裝入CR0寄存器將引起通用保護異常。需要注意的是,PG位的改變將使系統啟用或禁用分頁機制,因而只有當所執行的程序的代碼和至少有一部分數據在線性地址空間和物理地址空間具有相同的地址的情況下,才能改變PG位。
CR1:CR1是未定義的控制寄存器,供今后開發的處理器使用,在80386中不能使用CR1,否則會引起無效指令操作異常。
CR2:是頁故障線性地址寄存器,保存最后一次出現頁故障的全32位線性地址。在報告頁異常時,處理器會把引起異常的線性地址存放在CR2中。因此操作系統中的頁異常處理程序可以通過檢查CR2的內容來確定線性地址空間中哪一個頁面引發了異常。
CR3:含有頁目錄表物理內存基地址,因此該寄存器也被稱為頁目錄基地址寄存器PDBR(Page-Directory Base address Register)。CR3用於保存頁目錄表的起始物理地址。由於目錄是頁對齊的,所以僅高20位有效,低12 位保留未用。向CR3中裝入一個新值時,低12位必須為0;但從CR3中取值時,低12位被忽略。每當用MOV指令重置CR3的值時,會導致分頁機制高速緩沖區的內容無效,用此方法,可以在啟用分頁機制之前,即把PG位置1之前,預先刷新分頁機制的高速緩存。CR3寄存器即使在CR0寄存器的PG位或PE位為0時也可裝入,如在實模式下也可設置CR3,以便進行分頁機制的初始化。在任務切換時,CR3要被改變,但是如果新任務中CR3的值與原任務中CR3的值相同,那么處理器不刷新分頁高速緩存,以便當任務共享也表時有較快的執行速度。
五.調試寄存器:
調試寄存器主要作用是調試應用代碼、系統代碼、開發多任務操作系統.來監視代碼的運行和處理器的性能。
DR0-DR3:保留32位斷點的線性地址。
DR4-DR5:保留、未定義。
DR6:B0—B3:斷點狀態的監測;BD:調試寄存器訪問監測、置位,表明在指令流中,下一條指令將訪問其中的一個調試寄存器;BS:單步執行標志位;BT:任務轉換標志位。
DR7:L0—L3:局部斷點使能標志位;G0--G3: 全局斷點使能標志位;LE AND GE:置位,表明處理器可以監測導致數據斷點的指令,推薦置位為1;GD:通用監測使能標志位,表明是否開啟調試寄存器保護;LEN0 through LEN3 : 用來表明相應斷點地址寄存器內存位置的大小;R/W0 through R/W3: 相應斷點的狀態。
六.系統地址寄存器:
全局描述符表GDT、局部描述符表LDT和中斷描述符表IDT等都是保護方式下非常重要的特殊段,它們包含有為段機制所用的重要表格。為了方便快速地定位這些段,處理器采用一些特殊的寄存器保存這些段的基地址和段界限。我們把這些特殊的寄存器稱為系統地址寄存器。
1.全局描述符表寄存器GDTR:GDTR長48位,其中高32位為基地址,低16位為界限。由於GDT 不能有GDT本身之內的描述符進行描述定義,所以處理器采用GDTR為GDT這一特殊的系統段提供一個偽描述符。GDTR給定了GDT。GDTR中的段界限以字節為單位。由於段選擇子中只有13位作為描述符索引,而每個描述符長8個字節,所以用16位的界限足夠。通常,對於含有N個描述符的描述符表的段界限設為8*N-1。
2.局部描述符表寄存器LDTR:局部描述符表寄存器LDTR規定當前任務使用的局部描述符表LDT。LDTR類似於段寄存器,由程序員可見的16位的寄存器和程序員不可見的高速緩沖寄存器組成。實際上,每個任務的局部描述符表LDT作為系統的一個特殊段,由一個描述符描述。而用於描述符LDT的描述符存放在GDT中。在初始化或任務切換過程中,把描述符對應任務LDT的描述符的選擇子裝入LDTR,處理器根據裝入LDTR可見部分的選擇子,從GDT中取出對應的描述符,並把LDT的基地址、界限和屬性等信息保存到LDTR的不可見的高速緩沖寄存器中。隨后對LDT的訪問,就可根據保存在高速緩沖寄存器中的有關信息進行合法性檢查。LDTR寄存器包含當前任務的LDT的選擇子。所以,裝入到LDTR的選擇子必須確定一個位於GDT中的類型為LDT的系統段描述符,也即選擇子中的TI位必須是0,而且描述符中的類型字段所表示的類型必須為LDT。可以用一個空選擇子裝入LDTR,這表示當前任務沒有LDT。在這種情況下,所有裝入到段寄存器的選擇子都必須指示GDT中的描述符,也即當前任務涉及的段均由GDT中的描述符來描述。如果再把一個TI位為1的選擇子裝入到段寄存器,將引起異常。
3.中斷描述符表寄存器IDTR:中斷描述符表寄存器IDTR指向中斷描述符表IDT。IDTR長48 位,其中32位的基地址規定IDT的基地址,16位的界限規定IDT的段界限。由於80386只支持256個中斷異常,所以IDT表最大長度是2K,以字節位單位的段界限為7FFH。IDTR 指示IDT的方式與GDTR指示GDT的方式相同。
4.任務狀態段寄存器TR:任務狀態段寄存器TR包含指示描述當前任務的任務狀態段的描述符選擇子,從而規定了當前任務的狀態段。任務狀態段的格式在后面的文章中介紹。TR也有程序員可見和不可見兩部分。當把任務狀態段的選擇子裝入到TR可見部分時,處理器自動把選擇子所索引的描述符中的段基地址等信息保存到不可見的高速緩沖寄存器中。在此之后,對當前任務狀態段的訪問可快速方便地進行。裝入到TR的選擇子不能為空,必須索引位於GDT中的描述符,且描述符的類型必須是TSS。
七.其他寄存器:
EIP:主要用於存放當前代碼段即將被執行的下一條指令的偏移,但其本質上並不能直接被指令直接訪問。這個寄存器指令由控制轉移指令、中斷及異常所控制。讀操作通過執行call指令並取得棧中所存放的地址來實現,而寫操作則通過修改程序棧中的返回指令指針並執行RET/IRET指令來完成,因此盡管這個寄存器相當重要,但其實並不是操作系統在實現過程中所需關注的焦點。
TSC:(時間戳寄存器)每個時鍾周期時其值加1,重啟時清零。通過RDTSC指令讀取TSC寄存器,只有當CR4寄存器的TSD位為0時,才可以在任何優先級下執行該指令,否則只能在特權級下執行該指令。
浮點寄存器:由於在80486微處理器內部設有浮點運算器,因此在其內部有相應的寄存器,其中包括8個80位通用數據寄存器、1個48位指令指針寄存器、1個48位數據指針寄存器、1個16位控制字寄存器、1個16位狀態字寄存器和1個16位標記字寄存器。