- 論壇徽章:
- 0
|
5.6、 觀察 xp 實際的 segmentation 情景
使用 bochs 可以很容易很直觀地觀察調(diào)試系統(tǒng)。下面選取一個 xp 啟動的實際片斷,如下:
<bochs:7> sreg
cs:s=0x001b, dl=0x0000ffff, dh=0x00cffa00, valid=1
ds:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
ss:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
ss:s=0x0023, dl=0x0000ffff, dl=0x00cff300, valid=31
fs:s=0x003b, dl=0xe000ffff, dl=0x7f40f3fd, valid=7
gs:s=0x0000, dl=0x00000000, dl=0x00000000, valid=0
ldtr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
tr:s=0x0028, dl=0x200020ab, dh=800008b04, valid=1
gdtr:base=0x8003f000, limit=0x3ff
idtr:base=0x8003f400, limit=0x7ff |
1、GDTR.base 是 0x8003f000, GDTR.limit 是 0x3ff
2、IDTR.base 是 0x8003f400, IDTR.limit 是 0x7ff
3、LDTR.selector 為 0x0000
這里沒有建立 LDT,它的 selector 是 0x0000,也就是 NULL descriptor。
5.6.1、 觀察 cs register
觀察 cs 的信息:
1、cs 使用的 selector 正是前面提到的 0x1b
2、接下來的 dl=0x0000ffff, dh=0x00cffa00 其實就是 descriptor 信息。
來看一看 cs 的 descriptor 的什么:
<bochs:8> x/2 0x8003f000+3*8
0x8003f018 <bogus+ 0>: 0x0000ffff 0x00cffa00 |
cs 使用的 selector 是 0x1b,因此:selector.RPL = 3 使用的權(quán)限 3 selector.TI = 0,使用 GDT,selector.SI = 3
descriptor 的地址在:gdtr.base + 3 * 8 = 0X8003f018。
它的值按 64 位顯示是:0x00cffa00_0000ffff。
那么,descriptor 的信息:
1、 base = 0x00000000,這是 32 位值。
2、 limit = 0xffffff,這是一個 20 位的值。
3、 DPL = 11b,也就是 3 級。
4、 S 位是 1,它是一個非系統(tǒng)的 descriptor,也就是屬于 segment descriptor。
5、 type 是 1010b,顯示它是一個 execute/readable non-conforming 類型的 code segment descriptor。
6、 limit 的粒度位 G 位是 1,顯示它是 4K 粒度的。
7、 最后缺省位 D 位是 1, 表明目標(biāo) code segment 的 32 位代碼。
對這個 descriptor 描述的信息,歸納一下為:segment 是 32 位的代碼段,基地址是 0x00000000,訪問權(quán)限是 3 級,limit 是 0xFFFFF * 0x1000 + 0xFFF = 4G。
物理上這個 descriptor 被加載到 cs register 里。
5.6.2、 觀察 ds register
我們看看 ds 加載的 descriptor 的又是怎樣的。
ds 使用的 selector 是 0x23:TI = 0,SI = 4 以及 RPL = 3。
獲取 descirptor :
<bochs:9> x/2 0x8003f000+4*8
0x8003f020 <bogus+ 0>: 0x0000ffff 0x00cff300 |
這個 descriptor 的值是:0x00cff300_0000ffff (64 位值)
1、 base = 0x00000000,這是 32 位值。
2、 limit = 0xffffff,這是一個 20 位的值。
3、 DPL = 11b,也就是 3 級。
4、 S 位是 1,它是一個非系統(tǒng)的 descriptor,也就是屬于 segment descriptor。
5、 type 是 0011b,顯示它是一個具有 R/W 權(quán)限的 data segment descriptor。
6、 limit 的粒度位 G 位是 1,顯示它是 4K 粒度的。
7、 最后缺省位 D 位是 1, 同 code segment descriptor 意義一致
---------------------------
這個 descriptor 與上面 cs 的 descriptor 不同之處僅是 type 不同。這個 descriptor 是個 data segment descriptor。
5.6.3、 平坦的內(nèi)存模式
現(xiàn)在的操作系統(tǒng)絕大部分使用平坦的內(nèi)存模式,這種模式下,所有 segment 的基址是 0x00000000,但是 windows 使用了 FS 來定義非零基址的段。 FS 描述的段的基地址是:0x7f3de000,使用 FS 來管理一些系統(tǒng)信息。
使用了平坦模式,導(dǎo)致可以使用 ds 讀取 cs 的數(shù)據(jù),或者可以執(zhí)行 cs 以外的如:ds 或 ss 的代碼。在 segmentation 這個階段里 processor 無法阻止 stack 里的代碼可以執(zhí)行這一情況。直至在 paging 保護措施上才得到解決。
既然使用了平坦模式,邏輯地址與線性地址是一致的。導(dǎo)致現(xiàn)代操作系統(tǒng)已經(jīng)弱化邏輯地址這個概念,虛擬地址一般就指線性地址
因此:對于兩條指令
mov eax, dword ptr cs:[0x8012100]
mov eax, dword ptr ds:[0x8012100]
-------------------------------------
結(jié)果是完全一致的。當(dāng)然這是有提前的。提前是:cs 裝的這個 code segment 是可讀的。
但是,對于這兩條指令,情況就不同了:
mov dword ptr cs:[0x8012100],eax
mov dword ptr ds:[0x8012100],eax
-------------------------------------
第 1 條是會出錯的。這里 cs 裝的 code segment 是不可寫的。 |
|