特權級之間的轉換包括**段之間的轉換和資料段之間的轉換。對於資料段之間的轉換,只檢查選擇子中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 ...