當目標**執行完畢,需要返回控制權給原**時,將產生返回控制權行為。返回控制權行為,比轉移控制權行為簡單得多。因為,一切條件已經在交出控制權之前準備完畢,返回時僅需出棧就行了。
1、
near call的返回
近呼叫情況下,段不改變,即 cs 不改變,許可權級別不改變。從棧中pop返回位址到eip暫存器時,需進行 limit 的檢查。
2、
直接控制權轉移的返回(
far call
或far jmp
)
直接轉移返回到相同許可權級別,發生跨段的返回,許可權不變。這時,cs 被從棧中 pop 出來的 cs 值載入進去,處理器會檢查 cpl 與這個 pop 出來的選擇子(calling procedure cs)中的rpl進行檢查,相等則屬相級返回。
3、
利用各種門符進行向高許可權**轉移後的返回
★ 檢查儲存在 called procedure stack
中的原calling procedure cs
的rpl
域以確保是從高許可權向低許可權**返回。
★ 原calling procedure cs及eip被pop到cs及eip 暫存器中。
★ 若有引數時,called procedureesp需恢復棧結構(加上相應引數size)
★ 原calling procedure ss及esp被pop到ss及esp暫存器中。
★ 若有引數時,原calling procedure esp 需恢復結構(加上相應引數size)。
★ 恢復原calling procedurecs後,將檢查每個segment selector(ds、es、fs及gs),假如資料段許可權高於cs,則被載入null segment selector。
作業系統必須至少建立乙個tss,4個許可權級別的堆疊結構(stack segment selector及stack pointer)必須被定義。
一、
堆疊及棧指標的許可權級別:
★ 3 級:stack selector及stack pointer儲存在ss暫存器及esp 暫存器中
★ 0、1及2級:相應的stack selector及stack pointer儲存在tss相應的域中。
二、當發生向高許可權級別**轉移時,發生堆疊的切換:
★ 根據cpl**移時cpl改變)在tss得到相應級別的堆疊結構(ss及esp)
★ 進行棧結構檢查,包括limit檢查、stack segment descriptor一系列的檢查後,stack selector
及stack pointer
載入到ss
及esp
暫存器。
★ 將原來級別的(許可權低)stack selector及stack pointer壓入新的堆疊中(許可權高),這個過程是:載入新的ss及
esp時,先臨時儲存舊的ss及
esp,再將臨時儲存舊的ss及
esp壓入新的堆疊中。
★ 若有引數,則壓入引數(引數個數定義在call gate中的param count域)
★ 壓入返回位址(cs及eip)
★ 若有錯誤碼,則壓入錯誤碼。
注意事項:
★ call gate 允許最多31個引數,在呼叫者的堆疊裡。發生切換時,將從呼叫者的堆疊裡複製到新的堆疊裡。
切換後堆疊結構圖:
calling procedure called procedure
… …param1
param2
param3
… …
… …calling ss
calling esp
param1
param2
param3
calling cs
calling eip
... ...
… … 頂
0
踩 0
中斷發生時使用者堆疊和核心堆疊的切換
如果乙個中斷產生時任務正在使用者 中執行,那麼該中斷會引起cpu特權級從3到0的變化,此時cpu就會執行使用者態堆疊到核心態堆疊的切換操作。cpu會從當前任務的任務狀態段tss中取得新堆疊的段選擇符和偏移量。因為中斷服務程式在核心中,屬於0級特權級 所以48位的核心態堆疊指標會從tss的ss0和es...
任務核心態堆疊與使用者態堆疊之間的切換
在linux 0.12系統中,所有中斷服務程式都屬於核心 如果乙個中斷產生時任務正在使用者 中執行,那麼該中斷就會引起cpu特權級從3級到0級的變化,此時cpu就會進行使用者態堆疊到核心態堆疊的切換操作。cpu會從當前任務的任務狀態段tss中取得新堆疊的段選擇 在linux 0.12系統中,所有中斷...
堆,棧,堆疊的區別
乙個程式一般分為3段 text段,data段,bss段 text段 就是放程式 的,編譯時確定,唯讀,data段 存放在編譯階段 而非執行時 就能確定的資料,可讀可寫 就是通常所說的靜態儲存區,賦了初值的全域性變數和靜態變數存放在這個區域,常量也存放在這個區域 bss段 定義而沒有賦初值的全域性變數...