天天看點

存儲器的保護

修改段寄存器時的保護

  GDT的基位址和界限,都在寄存器 GDTR 中。描述符在記憶體中的位址,是用索引号乘以 8,再和描述符表的線性基位址相加得到的,而這個位址必須在描述符表的位址範圍内。換句話說,索引号乘以 8 得到的數值,必須位于描述符表的邊界範圍之内。換句話說,處理器從 GDT 中取某個描述符時,就要求描述符的 8 個位元組都在 GDT 邊界之内,也就是索引号×8+7 小于等于邊界。

存儲器的保護

  除了按進行段的類别檢查外,還要檢查描述符中的 P 位。如果 P=0,表明雖然描述符已被定義,但該段實際上并不存在于實體記憶體中。此時,處理器中止處理,引發異常中斷 11。一般來說,應當定義一個中斷處理程式,把該描述符所對應的段從硬碟等外部存儲器調入記憶體,然後置 P 位。中斷傳回時,處理器将再次嘗試剛才的操作。

存儲器的保護

位址變換時的保護

  所謂位址變換的保護,其實就是對于偏移位址的限制,保護模式下,偏移位址不允許超過段界限。

段界限的計算方式:

  • G=0:則實際段界限就是描述符記載的段界限
  • G=1,:實際段界限是描述符的界限值*0x1000+0xFFF

  對于代碼段,因為代碼段是向上拓展的,是以偏移位址隻能是從0到段界限值,也就是:

  • 0<=(EIP+指令長度-1)<=實際使用的段界限

  上面這個限制對于向上拓展的資料段也是适用的,在向上拓展的代碼段中:

  • 0<=(EA+指令長度-1)<=實際使用的段界限

  對于向下拓展的資料段,特别是棧段,實際使用的段内偏移位址不允許通路最低的段界限,而對于最高端位址沒有限制,最大可以是0xFFFFFFFF(32位保護模式下),也就是:

  • 實際使用的段界限+1<=(ESP的内容 - 操作數的長度)<=0xFFFFFFFF

  對于向下拓展的資料段,假設段的描述符高速緩存器裡的線性基位址位0x00007c00,段的界限為0Xffffe,粒度為4KB,則實際的有效實體位址範圍是

  • 0x00007c00+0Xfffff000~0x00007c00+0xffffffff
  • 即0x00006c00~0x00007bff(回繞回來了)

  有時候資料在代碼段上,但是代碼段是不可以讀的,也不可以寫,如果想對代碼段做一些修改(比如調試程式加入斷點int3),那隻能是通過另外找一個資料段指向這個段來了(一般不推薦這麼做,因為一般來說資料段和代碼段要分開,不然會出現不可預料的錯誤。)當然别名技術并非僅僅可以用于讀寫代碼段,如果兩個程式想共享一個記憶體區域,可以為每個程式都建立一個描述符,使他們都指向同一個記憶體段

代碼清單

;代碼清單12-1
         ;檔案名:c12_mbr.asm
         ;檔案說明:硬碟主引導扇區代碼 

         ;設定堆棧段和棧指針 
         mov eax,cs      

         mov ss,eax

         mov sp,0x7c00      

         ;計算GDT所在的邏輯段位址

         mov eax,[cs:pgdt+0x7c00+0x02]      ;GDT的32位線性基位址 

         xor edx,edx

         mov ebx,16

         div ebx                            ;分解成16位邏輯位址 

         mov ds,eax                         ;令DS指向該段以進行操作

         mov ebx,edx                        ;段内起始偏移位址 

         ;建立0#描述符,它是空描述符,這是處理器的要求

         mov dword [ebx+0x00],0x00000000

         mov dword [ebx+0x04],0x00000000  

         ;建立1#描述符,這是一個資料段,對應0~4GB的線性位址空間

         mov dword [ebx+0x08],0x0000ffff    ;基位址為0,段界限為0xfffff

         mov dword [ebx+0x0c],0x00cf9200    ;粒度為4KB,存儲器段描述符 
         ;建立保護模式下初始代碼段描述符

         mov dword [ebx+0x10],0x7c0001ff    ;基位址為0x00007c00,512位元組 
         mov dword [ebx+0x14],0x00409800    ;粒度為1個位元組,代碼段描述符 
         ;建立以上代碼段的别名描述符

         mov dword [ebx+0x18],0x7c0001ff    ;基位址為0x00007c00,512位元組

         mov dword [ebx+0x1c],0x00409200    ;粒度為1個位元組,資料段描述符

         mov dword [ebx+0x20],0x7c00fffe

         mov dword [ebx+0x24],0x00cf9600

         ;初始化描述符表寄存器GDTR

         mov word [cs: pgdt+0x7c00],39      ;描述符表的界限   

         lgdt [cs: pgdt+0x7c00]
         in al,0x92                         ;南橋晶片内的端口 

         or al,0000_0010B

         out 0x92,al                        ;打開A20

         cli                                ;中斷機制尚未工作

         mov eax,cr0

         or eax,1

         mov cr0,eax                        ;設定PE位

         ;以下進入保護模式... ...

         jmp dword 0x0010:flush             ;16位的描述符選擇子:32位偏移                                             

         [bits 32]                          
  flush:                                     

         mov eax,0x0018                      

         mov ds,eax      

         mov eax,0x0008                     ;加載資料段(0..4GB)選擇子

         mov es,eax

         mov fs,eax

         mov gs,eax

         mov eax,0x0020                     ;0000 0000 0010 0000

         mov ss,eax

         xor esp,esp                        ;ESP <- 0      

         mov dword [es:0x0b8000],0x072e0750 ;字元'P'、'.'及其顯示屬性

         mov dword [es:0x0b8004],0x072e074d ;字元'M'、'.'及其顯示屬性

         mov dword [es:0x0b8008],0x07200720 ;兩個空白字元及其顯示屬性

         mov dword [es:0x0b800c],0x076b076f ;字元'o'、'k'及其顯示屬性
         ;開始冒泡排序 
         mov ecx,pgdt-string-1              ;周遊次數=串長度-1 
  @@1:
         push ecx                           ;32位模式下的loop使用ecx 

         xor bx,bx                          ;32位模式下,偏移量可以是16位,也可以 

  @@2:                                      ;是後面的32位 

         mov ax,[string+bx] 

         cmp ah,al                          ;ah中存放的是源字的高位元組 

         jge @@3 

         xchg al,ah 

         mov [string+bx],ax 
  @@3:

         inc bx 

         loop @@2 

         pop ecx 

         loop @@1      

         mov ecx,pgdt-string
         xor ebx,ebx                        ;偏移位址是32位的情況 
  @@4:                                      ;32位的偏移具有更大的靈活性

         mov ah,0x07

         mov al,[string+ebx]

         mov [es:0xb80a0+ebx*2],ax          ;示範0~4GB尋址。

         inc ebx

         loop @@4
         hlt 
;-------------------------------------------------------------------------------
     string           db 's0ke4or92xap3fv8giuzjcy5l1m7hd6bnqtw.'
;-------------------------------------------------------------------------------
     pgdt             dw 0
                      dd 0x00007e00      ;GDT的實體位址
;-------------------------------------------------------------------------------                             
     times 510-($-$$) db 0

                      db 0x55,0xaa
           

繼續閱讀