1. 程式人生 > >4.由真實模式到保護模式

4.由真實模式到保護模式

學習於網易雲課堂:Linux作業系統, 構建自己的核心,講師:Coding迪斯尼

目標:實現32位定址

之前的暫存器直接存著要訪問的地址,一個暫存器16位,2^16*2^4=2^20=2M,加上偏移2^16=64kb,也就是說,真實模式的定址範圍是2M+(-)64kb,現在要做的是暫存器儲存表結構的偏移地址,然後從表結構中得到32位的程式起始地址和程式的長度,程式所在記憶體的屬性(比如:可讀,可寫)

%include "pm.inc"

org 0x9000;基地址

jmp LABEL_BEGIN

[SECTION .gdt]
;描述記憶體地址|byte7    |byte6    |byte5    |byte4    |byte3    |byte2    |byte1    |byte0    |
;            |7654 3210|7654 3210|7654 3210|7654 3210|7654 3210|7654 3210|7654 3210|7654 3210|
;            |*********|    |----|...屬性..|*************地址************|-------段長度------|


;                             段基址  段長           屬性
LABEL_GDT:         Descriptor 0,      0,             0;
LABEL_DESC_CODE32: Descriptor 0,      SegCode32Len-1,DA_C+DA_32
LABEL_DESC_VIDEO:  Descriptor 0B8000h,0ffffh,        DA_DRW

GdtLen equ $-LABEL_GDT;24位元組,3個Descriptor的長度
GdtPtr dw  GdtLen-1
       dd  0;資料結構的起始地址
SelectorCode32 equ LABEL_DESC_CODE32-LABEL_GDT;LABEL_DESC_CODE32的地址偏移
SelectorVideo  equ LABEL_DESC_VIDEO-LABEL_GDT;LABEL_DESC_VIDEO的地址偏移

[SECTION .sl6]
[BITS 16]

LABEL_BEGIN:
   mov ax,cs
   mov ds,ax
   mov es,ax
   mov ss,ax
   mov sp,0100h
   
   xor eax,eax;異或清0 eax暫存器
   shl eax,4;cs暫存器*16
   add eax,LABEL_SEG_CODE32;cs+偏移,此處是真實模式定址,找到資料結構的偏移地址
   mov word [LABEL_DESC_CODE32+2],ax;把資料結構的地址寫入2,3
   shr eax,16
   mov byte[LABEL_DESC_CODE32+4],al
   mov byte[LABEL_DESC_CODE32+7],ah
   
   xor eax,eax
   mov ax,ds
   shl eax,4
   add eax,LABEL_GDT
   mov dword [GdtPtr+2],eax
   
   lgdt [GdtPtr];系統從資料結構中找記憶體的起始地址,資料長度
   
   cli
   
   in al,92h
   or al,00000010b
   out 92h,al
   
   mov eax,cr0
   or eax,1
   mov cr0,eax
   
   jmp dword SelectorCode32:0;跳轉到偏移地址
   
   [SECTION .s32]
   [BITS 32]
   
LABEL_SEG_CODE32:
   mov ax,SelectorVideo
   mov gs,ax
   mov si,msg
   mov ebx,10
   mov ecx,2
showChar:
   mov edi,(80*11)
   add edi,ebx
   mov eax,edi
   mul ecx
   
   mov edi,eax
   mov ah,0ch
   mov al,[si]
   cmp al,0
   je  end
   add ebx,1
   add si,1
   mov [gs:edi],ax
   jmp showChar
end:
   jmp $
   msg:
   DB "bairuixiang",0
SegCode32Len equ $-LABEL_SEG_CODE32
   

現在我們已經實現由核心載入器找到我們的程式碼,然後由之前的真實模式的定址變為保護模式的定址,找到真正要執行的程式碼,接著去執行。