特權級之間的轉換

2021-07-22 09:04:53 字數 1880 閱讀 5717

特權級之間的轉換包括**段之間的轉換和資料段之間的轉換。對於資料段之間的轉換,只檢查選擇子中rpl和段中dpl的值,如果rpl<=dpl則可以轉換,而對於**段之間的轉換,情況會稍微複雜。

**段之間特權級的轉換主要通過jmp和call指令實現,jmp和call的運算元可以直接是選擇子,但注意在用call時,要記得ret。call的運算元還可以是乙個呼叫門或者是乙個包含選擇子的tss或者是乙個包含tss的任務門。對於門,其實質就是描述符,與**段和資料段描述符不同,它是系統描述符,所以其s=0。暫時接觸到的門共有四種:呼叫門、中斷門、陷阱門和任務門。呼叫門只能放在gdt或ldt中,不能在idt中,中斷門和陷阱門則只能放在idt中,而任務門既可以放在gdt中也可以放在ldt和idt中。

這次碰到的問題有:

1.gdt中第四項(**中為呼叫門)的索引為0x18,開始寫為0x10了~

2.ret時,會檢查被呼叫者的cs,eip等值,所以如果沒有儲存的話,系統會崩潰

[cpp]view plain

copy

org 0x7c00  

mov ax,cs  

mov ds,ax  

;initgdt  

xor eax,eax  

mov ax,cs  

shl eax,4  

add eax,display  

mov word [gdt+10],ax  

shr eax,16  

mov byte [gdt+12],al  

mov byte [gdt+15],ah  

lgdt [gdt_addr]  

cli  

;a20  

in al,0x92  

or al,00000010b  

out 0x92,al  

;cr0 開cr0!  

mov eax,cr0  

or eax,0x1  

mov cr0,eax  

;jmp dword codeselector:0  

call gateselector:0  

jmp $;死迴圈 否則沒有**執行系統會崩潰  

gdt:  

dw 0,0,0,0  

dw 0x07ff  

dw 0x0000  

dw 0x9a00  

dw 0x00cf  

dw 0x07ff  

dw 0x8000  

dw 0x920b  

dw 0x00cf  

;gate 呼叫門可以放在gdt或ldt中 但不能放在idt中  

dw 0x0000  

dw 0x0008  

dw 0xec00  

dw 0x0000  

;選擇子  

codeselector: equ 0x08  

videoselector: equ 0x10  

gateselector: equ 0x18;第四項為0x18!!!  

;gdt位址  

gdt_addr:  

dw 0x07ff  

dw gdt,0  

;gate  

;gate:  

[bits 32]  

display:  

mov ax,videoselector  

mov gs,ax  

mov edi,(80*0+0)*2  

mov ah,0x0c  

mov al,'a'

mov [gs:edi],ax  

jmp $;retf出問題 沒儲存堆疊?  

times 510-($-$) db 0  

dw 0xaa55  

關於中斷的特權級轉換

此圖選自 linux核心完全注釋 由上圖可以看出,當特權級沒有轉換時,中斷處理程式和被中斷程序是同用乙個堆疊,但是當發生了堆疊切換,例如一般中斷程序都處於0特權級下,當3的特權級程序執行時,中斷發生,那麼處理器就要到tss處找到0級的ss和esp,然後切換堆疊,然後處理器把被中斷程序的ss,esp,...

3 2 3節 特權級

原來看第3.2.3節的時候,感覺很難的。為什麼會感覺難呢?因為這一節談到的特權級別關係比較複雜,不容易弄清楚。這次重看一次這一節後,進行了一點小結,這才感覺比較清楚了。這一節的主要內容可以用下面這個 來描述。目標 段 jmp指令 call指令 直接呼叫 通過呼叫門 一致碼段 cpl dpl,不檢查r...

CPL,DPL,RPL 特權級檢查

1 cpl,dpl,rpl都位於 rpl request privilege level,請求特權級,位於段暫存器後兩位 dpl descriptor privilege level,描述特權級,位於gdt idt中 cpl current privilege level,當前特權級,cs.rpl ...