先說一下段描述符裏屬性P位的作用,也非常簡潔明瞭,P位的作用就是決定這個段描述符是否有效
P = 1 段描述符有效
P = 0 段描述符無效
那怎麼快速確定一個段描述符是否有效呢?
我們來舉一個例子
可以看到圖中紅色部分對應的高4字節,藍色部分對應這低4字節,對應GDT表裏也就是這樣看
可以看到我們的p位就對應低四個字節的左邊第一個字節的第一個二進制位,也就是這裏
而我們將9拆分一下就是1001
第一個二進制位爲1所以這個段描述符是 有效的
而快速確定的方法就是這個字節大於或者等於8,想實驗一下的話可以自己拆拆看
段描述符與段寄存器的對應關係
上次我們說到一個問題
段描述符只有64位,但我們需要填充的是80位,還剩下16位怎麼填?
我們再看一下這張圖
再看一下這個結構體
struct SegMent
{
WORD Selector; // 段選擇子 16位 可見
WORD Attributes; // 段屬性 16位 不可見 只有少數幾個屬性位是有效的
DWORD Base // 段起始地址 32位 不可見 僅對於FS和GS有效
DWORD Limit // 段大小 32位 不可見 僅對於FS和GS有效
}
這裏對應的少了16位,接下來我們就是64位是如何變成80位的
首先我們來看比較簡單的一個DWORD Base
Base
屬性表示了段的基址一共是32位,而這個基址在段描述符裏是由三部分組成的
圖上分別對應着Base組成的三部分,加起來剛好是32位,如果對應GDT表裏,也就是這樣看
也是就是Base=Base 31:24+Base 23:16+Base 15:0
然後我們來找WORD Attributes
在高四字節的23:8位,也就是
然後我們來找DWORD Limit
也就是Seg Limit 19:16+Segment 15:0 = 20
現在才20位 DWORD Limit
一共是32位,剩下12位從哪裏來
這就引出了我們今天要提的另外一個屬性,G位
如果G位爲0在前面補12個0
如果G位爲1在後面補12個1
我們來看一個GDT表的例子
00cf9300`0000ffff高32字節=0000 0000 1100 1111 1001 0011 0000 0000
G位爲1,後面補12個1
也就是
Limit=1111+1111 1111 1111 1111+1111 1111 1111=FFFFFFFF
所以可以看到Limit的值大小是由G位決定的
下面就來總結一下怎麼拆解一個例子:
00cf9300`0000ffff
0000000011001111100100110000000000000000000000001111111111111111
P位爲1
G位爲1
struct SegMent
{
WORD Selector; // 段選擇子 16位 可見
WORD Attributes; // 段屬性 16位 不可見 只有少數幾個屬性位是有效的
DWORD Base // 段起始地址 32位 不可見 僅對於FS和GS有效
DWORD Limit // 段大小 32位 不可見 僅對於FS和GS有效
}
WORD Attributes=1100 1111 1001 0011=0xCF93
DWORD Base=0000 0000 0000 0000 0000 0000 0000 0000 =0x00000000
DWORD Limit =1111 1111 1111 1111 1111 1111 1111 1111=0xFFFFFFFF
其他屬性我們下次再說