以下是轉自CSDN的壹篇詳細壹點的文章。
SYSENTER——快速系統調用
SYSENTER用來快速調用壹個0層的系統過程。SYSENTER是SYSEXIT的同伴指令。該指令經過了優化,它可以使將由用戶代碼(運行在3層)向操作系統或執行程序(運行在0層)發起的系統調用發揮最大的性能。
在調用SYSENTER指令前,軟件必須通過下面的MSR寄存器,指定0層的代碼段和代碼指針,0層的堆棧段和堆棧指針:
1.? IA32_SYSENTER_CS:壹個32位值。低16位是0層的代碼段的選擇子。該值同時用來計算0層的堆棧的選擇子。
2.? IA32_SYSENTER_EIP:包含壹個32位的0層的代碼指針,指向第壹條指令。
3.? IA32_SYSENTER_ESP:包含壹個32位的0層的堆棧指針。
MSR寄存器可以通過指令RDMSR/WRMSR來進行讀寫。寄存器地址如下表。這些地址值在以後的intel 64和IA32處理器中是固定不變的。
MSR 地址
IA32_SYSENTER_CS 174H
IA32_SYSENTER_ESP 175H
IA32_SYSENTER_EIP 176H
當執行SYSENTER,處理器會做下面的動作:
1.? 從IA32_SYSENTER_CS從取出段選擇子加載到CS中。
2.? 從IA32_SYSENTER_EIP取出指令指針放到EIP中
3.? 將IA32_SYSENTER_CS的值加上8,將其結果加載到SS中。
4.? 從IA32_SYSENTER_ESP取出堆棧指針放到ESP寄存器中
5.? 切換到0層。
6.? 若EFLAGS中VM標誌已被置,則清除VM標誌。
7.? 開始執行選擇的系統過程。
處理器不保存返回地址和調用過程的其他狀態信息。
SYSENTER指令總是轉移到DPL為0的保護模式下的代碼段。這條指令需要操作系統首先滿足下面的條件:
1.? 選擇的系統代碼段必須是壹個平坦的、32位最大為4G的代碼段。此段必須是可執行的、可讀、已存取、非壹致的。
2.? 選擇的系統堆棧段必須是壹個平坦的、32位最大為4G的數據段。此段必須可讀寫、已存取、可向上擴展。
SYSENTER可在除實地址模式外所有其他模式下執行。
SYSENTER和SYSEXIT是同伴指令,但是它們並不像CALL/RET指令對。當執行SYSENTER時,處理器並不會為用戶代碼保存狀態信息。而且無論是SYSENTER還是SYSEXIT都不能通過堆棧傳遞參數。
為了能通過SYSENTER/SYSEXIT指令,使控制在3層用戶代碼和0層操作系統代碼之間相互轉移,必須滿足下面的條件:
1.? 0層的代碼段和0層堆棧段段以及3層的代碼段和3層堆棧段在GDT中必須連續。這樣就可以使處理器能從從SYSENTER_CS_MSR的值計算出其他的選擇子的值了。
2.? .若要返回調用過程,由用戶代碼執行的快速系統調用“樁”(STUB)例程(通常在***享庫或DLL中)必須保存返回地址以及處理器的狀態信息;當要返回至用戶代碼時,操作系統或者由SYSENTER調用的執行程序必須使用這些保存的地址和狀態信息。
SYSENTER和SYSEXIT指令是從Pentium II開始新加入到IA32位架構中來的。這兩個指令在處理器上是否有效要看CPUID指令返回的EDX寄存器中SEP標記(SYSENTER/SYSEXIT存在標記)是否置上。操作系統若要檢查SEP標記必須要同時檢查處理器族(family)和型號(model),這樣才能確保結果的準確性。例如:
IF (CPUID SEP bit is set)
IF (Family == 6) AND (Model < 3) AND (Stepping < 3)
THEN
Fast System Call NOT supported
FI;
ELSE Fast System Call is supported
FI
當CPUID指令在Penitum Pro(Model 1)上執行,雖然返回的SEP標誌是置上的,但該處理器還是不支持SYSENTER/SYSEXIT指令的。