1. 程式人生 > >保護模式下的段暫存器值轉化為線性地址過程

保護模式下的段暫存器值轉化為線性地址過程

關鍵字: 段暫存器、段選擇子、全域性描述符表、區域性描述符表、段描述符、線性地址;     保護模式下使用段機制的CS,SS,DS,ESt,FS,GS儲存的並不是真實模式下的段地址,而是一個包含了段選擇子和偏移地址的組合值。CPU在讀取記憶體的時候,需要將段暫存器的值解析成為段地址,才能定位找到相應的段。下面我們一步一步解析這個過程。
    知識點:     段暫存器值=段選擇子,簡單來說,段選擇子就是用來指定段描述符的位置的一個值。
    段選擇子格式:
低0-1位表示特權級,為減少複雜度,目前不關注。低第2位表示指定的是描述符表是GDT(0)還是LDT(1),第3-15位指示段描述符在段描述表中的序號,很關鍵。     全域性描述符表,一個系統只有一個全域性描述符表,用來存放一些全域性的段描述符(下面有講述這個術語)。全域性描述符表第一個項值規定是空值。全域性描述符表的首地址由GDTR暫存器給出,這個值是線性地址,不需要解析。
    GDTR的是一個48位的值,16-47位範圍共32位(Base Address)的GDT基地址,0-15位範圍共16位(Limit)表示GDT表的大小(以位元組計算)。        在windbg核心模式,可以用r gdtr命令列出32位的基地址,用rgdtl列出16位的GDT大小值。

           r gdtr列出base address 指出段描述符表的基地址,是以平坦線性模式的地址顯示,這個是其他段地址使用段選擇子的基礎。            r gdtl列出limit以位元組為單位,如果limit是1023,則包含1024個位元組,GDT包含共有1024/8=128項段描述符。     段描述符:共64位值,下圖中的下部分是低32位,上部分是高32位。此段描述符中指出的段地址為:(32:24)(23:16)(15:00)這個值(共32位),就是我們所求的線性段地址了。
區域性描述符表暫存器LDTR表示當前任務的LDT表在GDTR中的索引,其格式是典型的段選擇子。(結合全域性描述符表理解) 段機制和頁機制一起工作原理示意圖,頁基制需要另一篇文章詳細介紹。

使用windbg來做上述過程的實驗: 1. 使用r命令列出暫存器值 kd> r eax=00000001 ebx=00000000 ecx=8080a188 edx=8292eadc esi=8080a188 edi=00000029 eip=82868bc0 esp=8292eaf8 ebp=8292eca4 iopl=0         nv up ei pl nz na po nc cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00200202 2. 以cs為例,因為其值0008是段暫存器值=段選擇子,我們使用.formats命令顯示二進位制數 kd> .formats 0008 Evaluate expression:   Hex:     00000008   Decimal: 8   Octal:   00000000010   Binary:  00000000 00000000 00000000 00001000   Chars:   ....   Time:    Thu Jan 01 08:00:08 1970   Float:   low 1.12104e-044 high 0   Double:  3.95253e-323 第2位為0,表示使用的是全域性描述符表,我們使用r gdtr命令檢視全域性描述符表的首地址。 kd> r gdtr gdtr=80b95000 第3-15位值為1,表示使用的是全域性描述符表的第1個項(從0開始,第0項一定為0);我們檢視全域性描述符表的內容: kd> dd 80b95000 80b95000
  00000000 00000000 0000ffff 00cf9b00 80b95010  0000ffff 00cf9300 0000ffff 00cffa00 80b95020  0000ffff 00cff300 600020ab 80008b1c 80b95030  1c003748 82409393 00000fff 0040f200 80b95040  0400ffff 0000f200 00000000 00000000 80b95050  f0000068 82008992 f0680068 82008992 80b95060  00000000 00000000 00000000 00000000 80b95070  500003ff 800092b9 00000000 00000000 可見第0項的確為0,第一項內容為0000ffff 00cf9b00。根據段描述符的格式,段描述符中指出的段地址為:(32:24)(23:16)(15:00)這個值(共32位)為線性地址。 kd> .formats 0000ffff Evaluate expression:   Hex:     0000ffff   Decimal: 65535   Octal:   00000177777   Binary:  00000000 00000000 11111111 11111111   Chars:   ....   Time:    Fri Jan 02 02:12:15 1970   Float:   low 9.18341e-041 high 0   Double:  3.23786e-319 kd> .formats 00cf9b00 Evaluate expression:   Hex:     00cf9b00   Decimal: 13605632   Octal:   00063715400   Binary:  00000000 11001111 10011011 00000000   Chars:   ....   Time:    Sun Jun 07 19:20:32 1970   Float:   low 1.90656e-038 high 0   Double:  6.72208e-317 得出(32:24)(23:16)(15:00)這三個地方的值都為0,所以找到的線性段地址為0。也就是cs=0008指定的線性段地址為0. 我們為驗證結果,使用dg命令檢視段選擇子所指定的段描述符的內容 kd> dg 0008                                   P Si Gr Pr Lo Sel    Base     Limit     Type    l ze an es ng Flags ---- -------- -------- ---------- - -- -- -- -- -------- 0008 00000000 ffffffff Code RE Ac 0 Bg Pg P  Nl 00000c9b 結果正確。 3. 再以fs=0030為例驗證。 kd> .formats 0030 Evaluate expression:   Hex:     00000030   Decimal: 48   Octal:   00000000060   Binary:  00000000 00000000 00000000 00110000   Chars:   ...0   Time:    Thu Jan 01 08:00:48 1970   Float:   low 6.72623e-044 high 0   Double:  2.37152e-322 可見低第2位為0,指定的是全域性描述符表。同樣使用r gdtr找全域性描述符基地址,然後定位第110b的段描述符: kd> r gdtr gdtr=80b95000 kd> dd 80b95000+6*8 l2 80b95030  1c003748 82409393 kd> .formats 1c003748  Evaluate expression:   Hex:     1c003748   Decimal: 469776200   Octal:   03400033510   Binary:  00011100 00000000 00110111 01001000   Chars:   ..7H   Time:    Tue Nov 20 13:23:20 1984   Float:   low 4.24231e-022 high 0   Double:  2.321e-315 kd> .formats 82409393 Evaluate expression:   Hex:     82409393   Decimal: -2109697133   Octal:   20220111623   Binary:  10000010 01000000 10010011 10010011   Chars:   .@..   Time:    ***** Invalid   Float:   low -1.41483e-037 high -1.#QNAN   Double:  -1.#QNAN 得出的線性段地址二進位制值為:  10000010    10010011   00011100 00000000   B 轉變為16進製為:82931c00; 使用dg來驗證線性段地址: kd> dg 30                                   P Si Gr Pr Lo Sel    Base     Limit     Type    l ze an es ng Flags ---- -------- -------- ---------- - -- -- -- -- -------- 0030 82931c00 00003748 Data RW Ac 0 Bg By P  Nl 00000493 結果正確。 參考資料: Intel64 and IA-32 Architectures Software Developer's Manual.pdf
張銀奎《軟體除錯》